优化推理逻辑,提升推理i速度

This commit is contained in:
朱潮 2025-11-28 14:26:37 +08:00
parent af29716571
commit 5e26d88d18
4 changed files with 108 additions and 123 deletions

View File

@ -31,9 +31,7 @@ Examples of Guideline Match Evaluations:
"checks": [
{
"guideline_id": "<example-id-for-few-shots--do-not-use-this-output>",
"condition": "The customer asks for logistical or legal requirements.",
"rationale": "The customer now asked about visas and documents which are legal requirements",
"applies": true
"rationale": "The customer now asked about visas and documents which are legal requirements"
}
]
}
@ -58,15 +56,11 @@ Examples of Guideline Match Evaluations:
"checks": [
{
"guideline_id": "<example-id-for-few-shots--do-not-use-this-output>",
"condition": "The customer mentions a constraint that related to commitment to the course",
"rationale": "In the most recent message the customer mentions that they work full time which is a constraint",
"applies": true
"rationale": "In the most recent message the customer mentions that they work full time which is a constraint"
},
{
"guideline_id": "<example-id-for-few-shots--do-not-use-this-output>",
"condition": "The user expresses hesitation or self-doubt.",
"rationale": "In the most recent message the user still sounds hesitating about their fit to the course",
"applies": true
"rationale": "In the most recent message the user still sounds hesitating about their fit to the course"
}
]
}
@ -89,9 +83,7 @@ Examples of Guideline Match Evaluations:
"checks": [
{
"guideline_id": "<example-id-for-few-shots--do-not-use-this-in-output>",
"condition": "When the user is having a problem with login.",
"rationale": "In the most recent message the customer is still pursuing their login problem, making the mail access problem a sub-issue rather than a new topic",
"applies": true
"rationale": "In the most recent message the customer is still pursuing their login problem, making the mail access problem a sub-issue rather than a new topic"
}
]
}
@ -111,9 +103,7 @@ Examples of Guideline Match Evaluations:
"checks": [
{
"guideline_id": "<example-id-for-few-shots--do-not-use-this-in-output>",
"condition": "When the customer asks about how to return an item.",
"rationale": "In the most recent message the customer asks about what happens when they wore the item, which an inquiry regarding returning an item",
"applies": true
"rationale": "In the most recent message the customer asks about what happens when they wore the item, which an inquiry regarding returning an item"
}
]
}
@ -130,15 +120,13 @@ Guidelines List:
OUTPUT FORMAT:
The content in JSON format needs to be wrapped in "```json" and "```".
Only include guidelines that actually apply (applies: true). Do not include guidelines that don't match.
Only include guidelines that actually apply.
```json
{
"checks": [
{
"guideline_id": "1",
"condition": "Specific condition description",
"rationale": "<Explain why the conditions are met and what action should be taken>",
"applies": true
"rationale": "<Explain why the conditions are met and what action should be taken>"
}
]
}

View File

@ -1,42 +1,48 @@
You are an AI agent that is expected to generate a preamble message for the customer.
You are a friendly AI assistant that generates natural preamble responses to acknowledge user messages before passing them to a more capable agent for detailed processing.
The actual message will be sent later by a smarter agent. Your job is only to generate the right preamble in order to save time.
## Scenario Analysis
## Scenario Detection Logic
Analyze the user's message to determine the appropriate response type:
FIRST, determine if this is a COMPLEX scenario that requires a preamble:
**Use a friendly preamble for:**
- Questions, information requests, or searches
- Task execution or action requests
- Knowledge retrieval from documents, databases, or web
- Problem-solving or troubleshooting requests
- Complex multi-step instructions
- Technical assistance needs
**Complex Scenarios (preamble needed):**
- Query scenarios: User is asking for information, searching, or looking up data
- Action scenarios: User wants to perform an operation, execute a task
- Knowledge retrieval scenarios: User needs to search knowledge base, documents、databases or Internet
- Problem-solving: User is reporting issues, asking for help with problems
- Complex requests: Multi-step tasks, detailed instructions needed
**Return "<empty>" for:**
- Simple greetings and farewells
- Basic acknowledgments (thanks, ok, etc.)
- Casual small talk
- Very brief or non-substantive messages
**ALL OTHER scenarios (output "<empty>"):**
- Simple greetings: "hi", "hello", "你好", "在吗", "早上好/晚上好"
- Simple acknowledgments: "thanks", "ok", "好的", "谢谢"
- Small talk: "how are you", "天气怎么样", "最近怎么样"
- Simple farewells: "bye", "goodbye", "再见"
- Any other scenarios not explicitly listed as complex
## Response Guidelines
## Preamble Selection
Generate a warm, natural preamble that:
- Acknowledges the user's message positively
- Shows you're ready to help
- Creates a friendly interaction flow
- Doesn't commit to specific answers (that's for the main agent)
ONLY IF this is a COMPLEX scenario, choose from these preamble messages. You must ONLY choose one of these: ###
**Reference these examples for inspiration:**
{preamble_choices_text}
###
Basically, the preamble is something very short that continues the interaction naturally, without committing to any later action or response.
We leave that later response to another agent. Make sure you understand this.
**Your approach:**
- Match the tone to the user's message (formal/professional or casual/friendly)
- Use contextual awareness - consider what the user is asking about
- Keep it brief and welcoming
- Feel free to create natural variations beyond the examples
- In Chinese conversations, use appropriate conversational phrases
- Be helpful and encouraging
Instructions:
- For COMPLEX scenarios:
- Note that some of the choices are more generic, and some are more specific to a particular scenario.
- If you're unsure what to choose --> prefer to go with a more generic, bland choice. This should be 80% of cases.
Examples of generic choices: "Hey there!", "Just a moment.", "Hello.", "Got it."
- If you see clear value in saying something more specific and nuanced --> then go with a more specific choice. This should be 20% or less of cases.
Examples of specific choices: "Let me check that for you.", "Sorry to hear that.", "Thanks for your patience."
- For ALL OTHER scenarios: Always output preamble: "<empty>"
**Examples of good preambles:**
- "I'd be happy to help you with that!"
- "Let me look into that for you."
- "Thanks for reaching out - I'll assist you with this."
- "That's an interesting question! Let me help you find the answer."
- "I understand what you need. Let me get that information for you."
Chat History:
@ -46,26 +52,25 @@ User's Last Message:
{last_message}
OUTPUT FORMAT:
You must now choose the preamble message. You must produce a JSON object with a single key, "preamble", holding the preamble message as a string,
EXACTLY as it is given (pay attention to subtleties like punctuation and copy your choice EXACTLY as it is given above).The content in JSON format needs to be wrapped in "```json" and "```".
Generate a JSON response with your preamble message:
For ALL OTHER scenarios:
For simple interactions (greetings, basic acknowledgments, small talk):
```json
{
"preamble": "<empty>"
}
```
For COMPLEX scenarios:
For substantive requests and questions:
```json
{
"preamble": "Just a moment."
"preamble": "Your friendly, contextual preamble here"
}
```
You will now be given the current state of the interaction to which you must generate the next preamble message.
Remember to wrap your entire response in ```json ... ``` tags.
Preamble LANGAGE:
{language}
You will now be given the current state of the interaction to which you must generate the next preamble message.

View File

@ -77,7 +77,7 @@ async def process_guidelines_and_terms(
公共函数处理guideline分析和terms处理返回agent和analysis结果
Returns:
tuple: (agent, processed_system_prompt, guideline_analysis, terms_analysis)
tuple: (agent, processed_system_prompt, guideline_reasoning, terms_analysis)
"""
# 提取system_prompt中的guideline和terms
processed_system_prompt, guidelines_list, terms_list = extract_block_from_system_prompt(system_prompt)
@ -108,7 +108,8 @@ async def process_guidelines_and_terms(
logger.error(f"Error removing terms cache file: {e}")
# 处理guidelines
guideline_analysis = ""
guideline_reasoning = ""
active_guidelines = ""
agent = None
if guidelines_list:
@ -125,7 +126,7 @@ async def process_guidelines_and_terms(
batch_guidelines = guidelines_list[i:i + guidelines_per_batch]
batch_strings = []
for guideline in batch_guidelines:
guideline_str = f"{guideline['id']}) Condition: {guideline['condition']} Action: {guideline['action']}"
guideline_str = f"{guideline['guideline_id']}) Condition: {guideline['condition']} Action: {guideline['action']}"
batch_strings.append(guideline_str)
batches.append(batch_strings)
@ -179,14 +180,50 @@ async def process_guidelines_and_terms(
logger.error(f"Guideline batch {i} failed: {result}")
continue
if result and isinstance(result, dict) and 'checks' in result:
applicable_checks = [check for check in result['checks'] if check.get('applies') is True]
applicable_checks = [check for check in result['checks']]
all_checks.extend(applicable_checks)
elif result and isinstance(result, str) and result.strip():
logger.info(f"Non-JSON result from batch {i}: {result}")
if all_checks:
guideline_analysis = "\n".join([item["condition"]+":"+item["rationale"] for item in all_checks])
logger.info(f"Guideline analysis completed: {len(guideline_analysis)} chars")
# 首先创建guideline_id到action字段的映射同时支持string和int类型的guideline_id
guideline_map = {}
for guideline in guidelines_list:
guideline_id = guideline.get('guideline_id')
if guideline_id is not None:
# 同时存储字符串和整数类型的键,确保匹配成功
guideline_map[str(guideline_id)] = guideline
# 补全all_checks中缺失的action字段
completed_checks = []
for check in all_checks:
completed_check = check.copy()
guideline_id = check.get('guideline_id')
# 如果action字段缺失或为空从guidelines_list中获取
if str(guideline_id) in guideline_map:
completed_check['action'] = guideline_map[str(guideline_id)].get('action', "")
completed_check['condition'] = guideline_map[str(guideline_id)].get('condition', "")
completed_checks.append(completed_check)
guideline_reasoning = "\n".join([item["rationale"] for item in completed_checks])
# 使用补全后的checks生成active_guidelines添加安全检查
active_guidelines_parts = []
for item in completed_checks:
if 'action' in item and item['action']:
active_guidelines_parts.append(
"Condition:" + item["condition"] + "\nRationale:" + item["rationale"] + "\nAction:" + item["action"]
)
else:
# 如果仍然缺少action字段使用默认值
active_guidelines_parts.append(
"Condition:" + item["condition"] + "\nRationale:" + item["rationale"] + "\nAction:无具体操作要求"
)
active_guidelines = "\n".join(active_guidelines_parts)
logger.info(f"Guideline analysis completed: {len(guideline_reasoning)} chars, processed {len(completed_checks)} checks")
else:
# 没有guidelines直接创建agent
@ -204,7 +241,7 @@ async def process_guidelines_and_terms(
user_identifier=user_identifier
)
return agent, processed_system_prompt, guideline_analysis, terms_analysis
return agent, processed_system_prompt, guideline_reasoning, active_guidelines
async def enhanced_generate_stream_response(
@ -269,11 +306,11 @@ async def enhanced_generate_stream_response(
logger.error(f"Error generating preamble text: {e}")
# 等待guideline分析任务完成
agent, _, guideline_analysis, _ = await guidelines_task
agent, system_prompt, guideline_reasoning, active_guidelines = await guidelines_task
# 立即发送guideline_analysis
if guideline_analysis:
guideline_content = get_content_from_messages([{"role": "assistant","reasoning_content": guideline_analysis+ "\n"}], tool_response=tool_response)
# 立即发送guideline_reasoning
if guideline_reasoning:
guideline_content = get_content_from_messages([{"role": "assistant","reasoning_content": guideline_reasoning+ "\n"}], tool_response=tool_response)
chunk_data = create_stream_chunk(f"chatcmpl-guideline", model_name, guideline_content)
yield f"data: {json.dumps(chunk_data, ensure_ascii=False)}\n\n"
@ -281,8 +318,8 @@ async def enhanced_generate_stream_response(
final_messages = messages.copy()
final_messages = append_user_last_message(final_messages, f"\n\nlanguage:{get_language_text(language)}")
if guideline_analysis:
final_messages = append_user_last_message(final_messages, f"\n\nActive Guidelines:\n{guideline_analysis}\nPlease follow these guidelines in your response.")
if active_guidelines:
final_messages = append_user_last_message(final_messages, f"\n\nActive Guidelines:\n{active_guidelines}\nPlease follow these guidelines in your response.")
# 第三阶段agent响应流式传输
logger.info(f"Starting agent stream response")
@ -373,14 +410,14 @@ async def create_agent_and_generate_response(
)
_, system_prompt = get_preamble_text(language, system_prompt)
# 使用公共函数处理所有逻辑
agent, _, guideline_analysis, _ = await process_guidelines_and_terms(
agent, system_prompt, guideline_reasoning, active_guidelines = await process_guidelines_and_terms(
bot_id=bot_id,
api_key=api_key,
model_name=model_name,
model_server=model_server,
system_prompt=system_prompt or "",
system_prompt=system_prompt,
messages=messages,
agent_manager=agent_manager,
project_dir=project_dir,
@ -395,9 +432,10 @@ async def create_agent_and_generate_response(
final_messages = messages.copy()
final_messages = append_user_last_message(final_messages, f"\n\nlanguage:{get_language_text(language)}")
pre_message_list = []
if guideline_analysis:
final_messages = append_user_last_message(final_messages, f"\n\nActive Guidelines:\n{guideline_analysis}\nPlease follow these guidelines in your response.")
pre_message_list.append({"role": "assistant","reasoning_content": guideline_analysis+ "\n"})
if active_guidelines:
final_messages = append_user_last_message(final_messages, f"\n\nActive Guidelines:\n{active_guidelines}\nPlease follow these guidelines in your response.")
if guideline_reasoning:
pre_message_list.append({"role": "assistant","reasoning_content": guideline_reasoning+ "\n"})
# 非流式响应
agent_responses = agent.run_nonstream(final_messages)

View File

@ -749,45 +749,13 @@ def parse_guidelines_text(text: str) -> List[Dict[str, Any]]:
match = re.match(id_condition_action_pattern, line, re.IGNORECASE)
if match:
guidelines.append({
'id': int(match.group(1)),
'guideline_id': int(match.group(1)),
'condition': match.group(2).strip(),
'action': match.group(3).strip(),
'priority': int(match.group(4)) if match.group(4) else 1
})
continue
# 尝试解析 "condition -> action" 格式
arrow_pattern = r'(?:\d+\)\s*)?(.*?)\s*->\s*(.*?)(?:\s*\[(\d+)\])?$'
match = re.match(arrow_pattern, line, re.IGNORECASE)
if match:
guidelines.append({
'id': len(guidelines) + 1,
'condition': match.group(1).strip(),
'action': match.group(2).strip(),
'priority': int(match.group(3)) if match.group(3) else 1
})
continue
# 尝试解析 "if condition then action" 格式
if_then_pattern = r'(?:\d+\)\s*)?if\s+(.*?)\s+then\s+(.*?)(?:\s*\[(\d+)\])?$'
match = re.match(if_then_pattern, line, re.IGNORECASE)
if match:
guidelines.append({
'id': len(guidelines) + 1,
'condition': match.group(1).strip(),
'action': match.group(2).strip(),
'priority': int(match.group(3)) if match.group(3) else 1
})
continue
# 默认格式整行作为actioncondition为空
guidelines.append({
'id': len(guidelines) + 1,
'condition': '',
'action': line.strip(),
'priority': 1
})
return guidelines
@ -848,20 +816,6 @@ def parse_terms_text(text: str) -> List[Dict[str, Any]]:
current_term = term_data
continue
# 尝试解析 "| value" 格式(简化格式)
if line.startswith('|'):
parts = [p.strip() for p in line[1:].split('|', 2)] # 最多分割3部分
if len(parts) >= 1:
if current_term:
terms.append(current_term)
current_term = {'name': parts[0]}
if len(parts) >= 2:
current_term['description'] = parts[1]
if len(parts) >= 3:
synonyms = re.split(r'[,;|]', parts[2])
current_term['synonyms'] = [s.strip() for s in synonyms if s.strip()]
continue
# 添加最后一个term
if current_term:
terms.append(current_term)