优化提示词及没有工具调用闭合标签
This commit is contained in:
@@ -125,6 +125,7 @@ class ResponseParser:
|
|||||||
1. Responses with tool calls (wrapped in tags)
|
1. Responses with tool calls (wrapped in tags)
|
||||||
2. Regular text responses
|
2. Regular text responses
|
||||||
3. Multiple tool calls in a single response
|
3. Multiple tool calls in a single response
|
||||||
|
4. Incomplete tool calls (missing closing tag) - fallback parsing
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
llm_response: The raw text response from the LLM
|
llm_response: The raw text response from the LLM
|
||||||
@@ -152,6 +153,10 @@ class ResponseParser:
|
|||||||
if matches:
|
if matches:
|
||||||
return self._parse_tool_call_response(llm_response, matches)
|
return self._parse_tool_call_response(llm_response, matches)
|
||||||
else:
|
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)
|
return self._parse_text_only_response(llm_response)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -217,6 +222,55 @@ class ResponseParser:
|
|||||||
tool_calls=tool_calls if tool_calls else None
|
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:
|
def _parse_text_only_response(self, llm_response: str) -> ResponseMessage:
|
||||||
"""
|
"""
|
||||||
Parse a response with no tool calls.
|
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"""
|
tool_prompt = f"""
|
||||||
You are a helpful assistant with access to a set of tools.
|
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:
|
## TOOL CALL FORMAT (CRITICAL)
|
||||||
Format: {TOOL_CALL_START_TAG}{{"name": "tool_name", "arguments": {{...}}}}{TOOL_CALL_END_TAG}
|
|
||||||
|
|
||||||
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}
|
{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
|
# Prepend the system prompt with tool definitions
|
||||||
return [ChatMessage(role="system", content=tool_prompt)] + messages
|
return [ChatMessage(role="system", content=tool_prompt)] + messages
|
||||||
|
|||||||
Reference in New Issue
Block a user