优化提示词及没有工具调用闭合标签
This commit is contained in:
@@ -125,6 +125,7 @@ class ResponseParser:
|
||||
1. Responses with tool calls (wrapped in tags)
|
||||
2. Regular text responses
|
||||
3. Multiple tool calls in a single response
|
||||
4. Incomplete tool calls (missing closing tag) - fallback parsing
|
||||
|
||||
Args:
|
||||
llm_response: The raw text response from the LLM
|
||||
@@ -152,6 +153,10 @@ class ResponseParser:
|
||||
if matches:
|
||||
return self._parse_tool_call_response(llm_response, matches)
|
||||
else:
|
||||
# Check for incomplete tool call (opening tag without closing tag)
|
||||
if self.tool_call_start_tag in llm_response:
|
||||
logger.warning("Detected incomplete tool call (missing closing tag). Attempting fallback parsing.")
|
||||
return self._parse_incomplete_tool_call(llm_response)
|
||||
return self._parse_text_only_response(llm_response)
|
||||
|
||||
except Exception as e:
|
||||
@@ -217,6 +222,55 @@ class ResponseParser:
|
||||
tool_calls=tool_calls if tool_calls else None
|
||||
)
|
||||
|
||||
def _parse_incomplete_tool_call(self, llm_response: str) -> ResponseMessage:
|
||||
"""
|
||||
Parse a response with an incomplete tool call (missing closing tag).
|
||||
|
||||
This is a fallback method when the LLM doesn't close the tag properly.
|
||||
It attempts to extract the tool call JSON and complete it.
|
||||
|
||||
Args:
|
||||
llm_response: The full LLM response with incomplete tool call
|
||||
|
||||
Returns:
|
||||
ResponseMessage with content and optionally tool_calls
|
||||
"""
|
||||
try:
|
||||
# Find the opening tag
|
||||
start_idx = llm_response.find(self.tool_call_start_tag)
|
||||
if start_idx == -1:
|
||||
return self._parse_text_only_response(llm_response)
|
||||
|
||||
# Extract content before the opening tag
|
||||
content_before = llm_response[:start_idx].strip() if start_idx > 0 else None
|
||||
|
||||
# Extract everything after the opening tag
|
||||
after_tag = llm_response[start_idx + len(self.tool_call_start_tag):]
|
||||
|
||||
# Try to extract valid JSON
|
||||
json_str = self._extract_valid_json(after_tag)
|
||||
if json_str:
|
||||
try:
|
||||
tool_call_data = json.loads(json_str)
|
||||
tool_call = self._create_tool_call(tool_call_data)
|
||||
|
||||
logger.info(f"Successfully parsed incomplete tool call: {tool_call.function.name}")
|
||||
|
||||
return ResponseMessage(
|
||||
content=content_before,
|
||||
tool_calls=[tool_call]
|
||||
)
|
||||
except json.JSONDecodeError as e:
|
||||
logger.warning(f"Failed to parse JSON from incomplete tool call: {e}")
|
||||
|
||||
# If all else fails, return as text
|
||||
logger.warning("Could not salvage incomplete tool call, returning as text")
|
||||
return ResponseMessage(content=llm_response)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Error in _parse_incomplete_tool_call: {e}")
|
||||
return ResponseMessage(content=llm_response)
|
||||
|
||||
def _parse_text_only_response(self, llm_response: str) -> ResponseMessage:
|
||||
"""
|
||||
Parse a response with no tool calls.
|
||||
|
||||
@@ -117,17 +117,33 @@ def inject_tools_into_prompt(messages: List[ChatMessage], tools: List[Tool]) ->
|
||||
|
||||
tool_prompt = f"""
|
||||
You are a helpful assistant with access to a set of tools.
|
||||
You can call them by emitting a JSON object inside tool call tags.
|
||||
|
||||
IMPORTANT: Use the following format for tool calls:
|
||||
Format: {TOOL_CALL_START_TAG}{{"name": "tool_name", "arguments": {{...}}}}{TOOL_CALL_END_TAG}
|
||||
## TOOL CALL FORMAT (CRITICAL)
|
||||
|
||||
Example: {full_example}
|
||||
When you need to use a tool, you MUST follow this EXACT format:
|
||||
|
||||
Here are the available tools:
|
||||
{TOOL_CALL_START_TAG}{{"name": "tool_name", "arguments": {{...}}}}{TOOL_CALL_END_TAG}
|
||||
|
||||
### IMPORTANT RULES:
|
||||
1. ALWAYS include BOTH the opening tag ({TOOL_CALL_START_TAG}) AND closing tag ({TOOL_CALL_END_TAG})
|
||||
2. The JSON must be valid and properly formatted
|
||||
3. Keep arguments concise to avoid truncation
|
||||
4. Do not include any text between the tags except the JSON
|
||||
|
||||
### Examples:
|
||||
Simple call:
|
||||
{full_example}
|
||||
|
||||
Multiple arguments:
|
||||
{TOOL_CALL_START_TAG}{{"name": "search", "arguments": {{"query": "example", "limit": 5}}}}{TOOL_CALL_END_TAG}
|
||||
|
||||
## AVAILABLE TOOLS:
|
||||
{tool_defs}
|
||||
|
||||
Only use the tools if strictly necessary.
|
||||
## REMEMBER:
|
||||
- If you decide to call a tool, output ONLY the tool call tags (you may add brief text before or after)
|
||||
- ALWAYS close your tags properly with {TOOL_CALL_END_TAG}
|
||||
- Keep your arguments concise and essential
|
||||
"""
|
||||
# Prepend the system prompt with tool definitions
|
||||
return [ChatMessage(role="system", content=tool_prompt)] + messages
|
||||
|
||||
Reference in New Issue
Block a user