Agent 开发实战:幻觉和工具选择错误的 5 个解决方案
Agent 开发实战:幻觉和工具选择错误的 5 个解决方案
0. 痛点:Agent 开始"胡说八道"了
你有没有遇到过这种情况:
用户:帮我查一下腾讯的股价
Agent:好的,让我查询...
[调用 get_stock_price("腾讯")]
[API 返回:{"error": "Invalid symbol"}]
Agent:腾讯的股价是 123.45 元
[幻觉!因为工具调用失败,Agent 瞎编了一个数字]
用户:今天北京天气怎么样?
Agent:好的,让我查询...
[调用 get_weather("北京")]
Agent:北京今天晴天,温度 25°C
[实际是雨天,Agent 没有调用工具就直接回答了]
或者更糟:
用户:帮我查一下苹果公司的市值
Agent:好的,让我查询...
[调用 get_weather("苹果")]
[工具选择错误!应该是 get_company_info("苹果")]
这就是幻觉(Hallucination)和工具选择错误(Tool Selection Error)。
1. 问题根源:为什么 Agent 会幻觉和选错工具?
原因 1:工具描述不清晰
# 工具定义(描述不清晰)
tools = [
{
"name": "get_weather",
"description": "获取天气", # 太简略!
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
}
}
}
]
# 问题:Agent 不知道这个工具能查哪些城市、返回什么格式
# 容易选错工具或误解返回结果
原因 2:Few-shot 示例不足
# System Prompt(缺少示例)
prompt = """
你是一个助手,可以调用以下工具:
- get_weather(city): 获取天气
- get_stock_price(symbol): 获取股价
用户问题:
"""
# 问题:没有示例,Agent 不知道如何正确调用工具
# 容易选错工具或传错参数
原因 3:输出格式约束不够严格
# 工具定义(输出格式不严格)
tools = [
{
"name": "get_weather",
"description": "获取天气",
"parameters": {...},
"returns": "天气信息" # 太模糊!
}
]
# 问题:Agent 不知道返回格式,容易自由发挥(幻觉)
解决方案 1:优化工具描述(Tool Description Optimization)
原理
给工具写清晰、详细的描述,让 Agent 准确理解工具的用途和限制。
# ❌ 错误示例(描述太简略)
{
"name": "get_weather",
"description": "获取天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
}
}
}
# ✅ 正确示例(描述详细)
{
"name": "get_weather",
"description": """
获取指定城市的当前天气信息。
支持的城市:北京、上海、广州、深圳、杭州、成都(其他城市返回错误)
返回格式:{"weather": "晴天/多云/雨天/雪天", "temperature": 温度(摄氏度)}
注意事项:如果城市不支持,返回 {"error": "City not supported"}
""",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称(中文,例如:北京、上海)"
}
},
"required": ["city"]
},
"returns": {
"type": "object",
"properties": {
"weather": {"type": "string", "description": "天气状况"},
"temperature": {"type": "number", "description": "温度(摄氏度)"}
}
}
}
自动化工具描述优化
from typing import Dict, Any
def optimize_tool_description(tool_def: Dict[str, Any]) -> Dict[str, Any]:
"""
自动优化工具描述
优化策略:
1. 描述要包含:功能、支持范围、返回格式、注意事项
2. 参数要包含:类型、描述、示例值
3. 返回值要包含:类型、描述、示例
"""
optimized = tool_def.copy()
# 1. 优化描述
if "description" in optimized:
desc = optimized["description"]
# 如果描述太短,提示需要补充
if len(desc) < 50:
print(f"⚠️ 工具 {optimized['name']} 的描述太短,建议补充:功能、支持范围、返回格式、注意事项")
# 2. 优化参数描述
if "parameters" in optimized:
for param_name, param_def in optimized["parameters"].get("properties", {}).items():
if "description" not in param_def:
print(f"⚠️ 参数 {param_name} 缺少描述,建议补充")
param_def["description"] = f"{param_name} 参数" # 默认描述
# 3. 添加返回值描述(如果缺失)
if "returns" not in optimized:
print(f"⚠️ 工具 {optimized['name']} 缺少返回值描述,建议补充")
optimized["returns"] = {"description": "返回值格式待补充"}
return optimized
# 使用示例
tool_def = {
"name": "get_weather",
"description": "获取天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
}
}
}
optimized_tool = optimize_tool_description(tool_def)
print(json.dumps(optimized_tool, indent=2, ensure_ascii=False))
优点:提高工具选择准确率,减少幻觉
缺点:需要人工编写高质量描述(AI 辅助)
解决方案 2:Few-shot 示例(Few-shot Examples)
原理
在 System Prompt 中提供几个正确调用的示例,让 Agent 学习如何正确调用工具。
# System Prompt 模板(带 Few-shot 示例)
FEW_SHOT_PROMPT = """
你是一个助手,可以调用以下工具:
- get_weather(city): 获取指定城市的天气
- get_stock_price(symbol): 获取指定股票的股价
【重要】调用工具时,必须严格按照以下格式:
```json
{
"tool": "工具名",
"parameters": {
"参数名": "参数值"
}
}
【示例 1】
用户:北京今天天气怎么样?
你的思考:需要调用 get_weather 工具,参数是 city=“北京”
你的回答:
{
"tool": "get_weather",
"parameters": {
"city": "北京"
}
}
【示例 2】
用户:腾讯的股价是多少?
你的思考:需要调用 get_stock_price 工具,参数是 symbol=“0700.HK”(腾讯港股代码)
你的回答:
{
"tool": "get_stock_price",
"parameters": {
"symbol": "0700.HK"
}
}
【示例 3】
用户:今天天气真好啊
你的思考:这是闲聊,不需要调用工具
你的回答:是的,今天天气确实不错!
现在,请处理用户的问题:
用户问题:{user_query}
“”"
**代码示例:动态生成 Few-shot 示例**
```python
from typing import List, Dict
class FewShotGenerator:
"""
Few-shot 示例生成器
"""
def __init__(self):
self.examples: List[Dict] = []
def add_example(self, user_query: str, tool_name: str, parameters: Dict, reasoning: str):
"""添加一个示例"""
self.examples.append({
"user_query": user_query,
"tool_name": tool_name,
"parameters": parameters,
"reasoning": reasoning
})
def generate_prompt(self, user_query: str) -> str:
"""生成带 Few-shot 的 Prompt"""
prompt = """
你是一个助手,可以调用以下工具:
- get_weather(city): 获取指定城市的天气
- get_stock_price(symbol): 获取指定股票的股价
【示例】
"""
# 添加所有示例
for i, example in enumerate(self.examples, 1):
prompt += f"""
【示例 {i}】
用户:{example['user_query']}
你的思考:{example['reasoning']}
你的回答:
```json
{{
"tool": "{example['tool_name']}",
"parameters": {json.dumps(example['parameters'], ensure_ascii=False)}
}}
“”"
# 添加当前用户问题
prompt += f"""
现在,请处理用户的问题:
用户问题:{user_query}
“”"
return prompt
使用示例
generator = FewShotGenerator()
添加示例
generator.add_example(
user_query=“北京今天天气怎么样?”,
tool_name=“get_weather”,
parameters={“city”: “北京”},
reasoning=“需要调用 get_weather 工具,参数是 city=北京”
)
generator.add_example(
user_query=“腾讯的股价是多少?”,
tool_name=“get_stock_price”,
parameters={“symbol”: “0700.HK”},
reasoning=“需要调用 get_stock_price 工具,参数是 symbol=0700.HK”
)
生成 Prompt
user_query = “上海明天会下雨吗?”
prompt = generator.generate_prompt(user_query)
print(prompt)
**优点**:显著提高工具选择准确率
**缺点**:占用 Token(示例越多,Token 消耗越大)
---
## 解决方案 3:输出格式约束(Output Format Constraints)
### 原理
强制 Agent 按照严格格式输出,减少自由发挥(幻觉)。
```python
from typing import Dict, Any
import json
import re
class OutputFormatter:
"""
输出格式约束器
"""
def __init__(self, schema: Dict[str, Any]):
"""
Args:
schema: 输出格式 Schema
例如:
{
"type": "object",
"properties": {
"tool": {"type": "string", "enum": ["get_weather", "get_stock_price", "none"]},
"parameters": {"type": "object"}
},
"required": ["tool"]
}
"""
self.schema = schema
def format(self, output: str) -> Dict[str, Any]:
"""
格式化输出(解析 + 验证)
Returns:
解析后的字典
Raises:
ValueError: 输出格式不符合 Schema
"""
# 1. 尝试解析 JSON
try:
parsed = json.loads(output)
except json.JSONDecodeError:
# 2. 如果解析失败,尝试从文本中提取 JSON
parsed = self._extract_json(output)
# 3. 验证格式
self._validate(parsed)
return parsed
def _extract_json(self, text: str) -> Dict[str, Any]:
"""从文本中提取 JSON"""
# 匹配 ```json ... ```代码块
match = re.search(r"```json\s*(\{.*?\})\s*```", text, re.DOTALL)
if match:
return json.loads(match.group(1))
# 匹配 { ... }(简单匹配)
match = re.search(r"\{.*\}", text, re.DOTALL)
if match:
return json.loads(match.group(0))
raise ValueError("无法从输出中提取 JSON")
def _validate(self, parsed: Dict[str, Any]):
"""验证格式是否符合 Schema"""
# 检查必需字段
for field in self.schema.get("required", []):
if field not in parsed:
raise ValueError(f"缺少必需字段:{field}")
# 检查字段类型
properties = self.schema.get("properties", {})
for field, field_schema in properties.items():
if field in parsed:
expected_type = field_schema.get("type")
if expected_type == "string" and not isinstance(parsed[field], str):
raise ValueError(f"字段 {field} 应该是字符串,实际类型:{type(parsed[field])}")
elif expected_type == "object" and not isinstance(parsed[field], dict):
raise ValueError(f"字段 {field} 应该是对象,实际类型:{type(parsed[field])}")
# 检查枚举值
for field, field_schema in properties.items():
if field in parsed and "enum" in field_schema:
if parsed[field] not in field_schema["enum"]:
raise ValueError(f"字段 {field} 的值应该是 {field_schema['enum']} 之一,实际值:{parsed[field]}")
# 使用示例
schema = {
"type": "object",
"properties": {
"tool": {
"type": "string",
"enum": ["get_weather", "get_stock_price", "none"]
},
"parameters": {"type": "object"}
},
"required": ["tool"]
}
formatter = OutputFormatter(schema)
# 测试 1:正确格式
output1 = '{"tool": "get_weather", "parameters": {"city": "北京"}}'
parsed1 = formatter.format(output1)
print(f"解析结果 1:{parsed1}")
# 测试 2:从文本中提取 JSON
output2 = "好的,让我查询一下:\n```json\n{"tool": "get_weather", "parameters": {"city": "北京"}}\n```"
parsed2 = formatter.format(output2)
print(f"解析结果 2:{parsed2}")
# 测试 3:错误格式(缺少必需字段)
output3 = '{"parameters": {"city": "北京"}}'
try:
parsed3 = formatter.format(output3)
except ValueError as e:
print(f"格式验证失败:{e}")
# 测试 4:错误格式(字段类型错误)
output4 = '{"tool": 123, "parameters": {"city": "北京"}}'
try:
parsed4 = formatter.format(output4)
except ValueError as e:
print(f"格式验证失败:{e}")
集成到 Agent
class AgentWithOutputFormatting:
"""带输出格式约束的 Agent"""
def __init__(self, llm, output_schema: Dict):
self.llm = llm
self.formatter = OutputFormatter(output_schema)
def run(self, user_query: str) -> Dict[str, Any]:
"""运行 Agent(带输出格式验证)"""
# 1. 生成 Prompt
prompt = self._build_prompt(user_query)
# 2. 调用 LLM
output = self.llm.call(prompt)
# 3. 格式化输出(解析 + 验证)
try:
formatted = self.formatter.format(output)
return formatted
except ValueError as e:
print(f"输出格式错误:{e}")
# 返回错误标记
return {"tool": "error", "error": str(e)}
def _build_prompt(self, user_query: str) -> str:
"""构建 Prompt(包含输出格式要求)"""
return f"""
你是一个助手,可以调用以下工具:
- get_weather(city): 获取指定城市的天气
- get_stock_price(symbol): 获取指定股票的股价
【输出格式要求】
你必须严格按照以下 JSON 格式输出:
```json
{{
"tool": "工具名(必须是 get_weather、get_stock_price 或 none 之一)",
"parameters": {{"参数名": "参数值"}}
}}
【示例】
用户:北京今天天气怎么样?
输出:
{{"tool": "get_weather", "parameters": {{"city": "北京"}}}}
现在,请处理用户的问题:
用户问题:{user_query}
“”"
使用示例
class MockLLM:
def call(self, prompt: str) -> str:
# 模拟 LLM 输出(可能格式不正确)
return “好的,让我查询一下北京天气…\njson\n{"tool": "get_weather", "parameters": {"city": "北京"}}\n”
llm = MockLLM()
schema = {
“type”: “object”,
“properties”: {
“tool”: {“type”: “string”, “enum”: [“get_weather”, “get_stock_price”, “none”]},
“parameters”: {“type”: “object”}
},
“required”: [“tool”]
}
agent = AgentWithOutputFormatting(llm, schema)
result = agent.run(“北京今天天气怎么样?”)
print(f"Agent 输出:{result}")
**优点**:强制格式,减少幻觉
**缺点**:LLM 可能不遵守格式(需要多次重试)
---
## 解决方案 4:工具选择验证(Tool Selection Validation)
### 原理
在调用工具之前,验证 Agent 选择的工具是否合理。
```python
from typing import Dict, Any, List
import difflib
class ToolSelectionValidator:
"""
工具选择验证器
"""
def __init__(self, tools: List[Dict[str, Any]]):
self.tools = tools
self.tool_names = [t["name"] for t in tools]
def validate(self, user_query: str, selected_tool: str, parameters: Dict) -> Dict[str, Any]:
"""
验证工具选择是否合理
Returns:
{"valid": True} 或 {"valid": False, "reason": "..."}
"""
# 1. 检查工具是否存在
if selected_tool not in self.tool_names:
# 尝试模糊匹配
suggestion = self._suggest_tool(selected_tool)
return {
"valid": False,
"reason": f"工具 {selected_tool} 不存在",
"suggestion": suggestion
}
# 2. 检查参数是否匹配
tool_def = next(t for t in self.tools if t["name"] == selected_tool)
required_params = tool_def.get("parameters", {}).get("required", [])
for param in required_params:
if param not in parameters:
return {
"valid": False,
"reason": f"缺少必需参数:{param}"
}
# 3. 检查工具是否适合用户问题(简化:关键词匹配)
relevance = self._check_relevance(user_query, selected_tool)
if relevance < 0.5:
return {
"valid": False,
"reason": f"工具 {selected_tool} 可能不适合用户问题(相关度:{relevance:.2f})",
"suggestion": self._suggest_tool_for_query(user_query)
}
return {"valid": True}
def _suggest_tool(self, wrong_name: str) -> str:
"""模糊匹配建议工具名"""
matches = difflib.get_close_matches(wrong_name, self.tool_names, n=1)
return matches[0] if matches else "(无建议)"
def _check_relevance(self, user_query: str, tool_name: str) -> float:
"""检查工具和用户问题的相关度(简化:关键词匹配)"""
keywords_map = {
"get_weather": ["天气", "气温", "下雨", "晴天"],
"get_stock_price": ["股价", "股票", "市值", "涨"]
}
keywords = keywords_map.get(tool_name, [])
if not keywords:
return 1.0
# 计算关键词匹配率
matched = sum(1 for kw in keywords if kw in user_query)
return matched / len(keywords)
def _suggest_tool_for_query(self, user_query: str) -> str:
"""根据用户问题建议工具"""
for tool_name, keywords in {
"get_weather": ["天气", "气温", "下雨", "晴天"],
"get_stock_price": ["股价", "股票", "市值", "涨"]
}.items():
if any(kw in user_query for kw in keywords):
return tool_name
return "(无建议)"
# 使用示例
tools = [
{
"name": "get_weather",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
},
{
"name": "get_stock_price",
"parameters": {
"type": "object",
"properties": {
"symbol": {"type": "string"}
},
"required": ["symbol"]
}
}
]
validator = ToolSelectionValidator(tools)
# 测试 1:工具不存在
result1 = validator.validate("北京天气怎么样?", "get_wether", {"city": "北京"})
print(f"验证结果 1:{result1}")
# 测试 2:缺少必需参数
result2 = validator.validate("北京天气怎么样?", "get_weather", {})
print(f"验证结果 2:{result2}")
# 测试 3:工具不适合用户问题
result3 = validator.validate("腾讯股价是多少?", "get_weather", {"city": "深圳"})
print(f"验证结果 3:{result3}")
# 测试 4:验证通过
result4 = validator.validate("北京天气怎么样?", "get_weather", {"city": "北京"})
print(f"验证结果 4:{result4}")
集成到 Agent
class AgentWithToolValidation:
"""带工具选择验证的 Agent"""
def __init__(self, llm, tools: List[Dict]):
self.llm = llm
self.tools = tools
self.validator = ToolSelectionValidator(tools)
def run(self, user_query: str) -> Dict[str, Any]:
"""运行 Agent(带工具选择验证)"""
# 1. LLM 选择工具
selected_tool, parameters = self._llm_select_tool(user_query)
# 2. 验证工具选择
validation = self.validator.validate(user_query, selected_tool, parameters)
if not validation["valid"]:
print(f"⚠️ 工具选择验证失败:{validation['reason']}")
print(f"建议工具:{validation.get('suggestion', '(无建议)')}")
# 返回验证失败标记
return {
"tool": "validation_failed",
"error": validation["reason"],
"suggestion": validation.get("suggestion")
}
# 3. 调用工具
result = self._call_tool(selected_tool, parameters)
return result
def _llm_select_tool(self, user_query: str) -> tuple[str, Dict]:
"""LLM 选择工具(简化:模拟)"""
# 实际应该调用 LLM
if "天气" in user_query:
return "get_weather", {"city": "北京"}
elif "股价" in user_query:
return "get_stock_price", {"symbol": "0700.HK"}
else:
return "none", {}
def _call_tool(self, tool_name: str, parameters: Dict) -> Any:
"""调用工具(简化:模拟)"""
print(f"调用工具:{tool_name},参数:{parameters}")
return {"result": "工具调用成功"}
# 使用示例
agent = AgentWithToolValidation(MockLLM(), tools)
# 测试
result = agent.run("北京天气怎么样?")
print(f"Agent 输出:{result}")
优点:提前发现工具选择错误,减少无效调用
缺点:增加延迟(需要验证步骤)
解决方案 5:幻觉检测(Hallucination Detection)
原理
在 Agent 输出后,检测是否包含幻觉(编造的信息)。
from typing import Dict, Any, List
import re
class HallucinationDetector:
"""
幻觉检测器
"""
def __init__(self, knowledge_base: Dict[str, Any] = None):
"""
Args:
knowledge_base: 知识库(用于验证事实性)
例如:{"腾讯股价": 123.45, "北京天气": "晴天"}
"""
self.knowledge_base = knowledge_base or {}
def detect(self, user_query: str, agent_output: str, tool_results: List[Dict] = None) -> Dict[str, Any]:
"""
检测幻觉
Returns:
{"hallucination": False} 或 {"hallucination": True, "reason": "..."}
"""
# 1. 检查是否包含工具未返回的信息
if tool_results:
for result in tool_results:
if not self._is_info_from_tool(agent_output, result):
return {
"hallucination": True,
"reason": "输出包含工具未返回的信息(可能幻觉)"
}
# 2. 检查是否包含与知识库矛盾的信息
if self.knowledge_base:
contradiction = self._check_contradiction(agent_output)
if contradiction:
return {
"hallucination": True,
"reason": f"输出与知识库矛盾:{contradiction}"
}
# 3. 检查是否包含不确定的表述(可能幻觉)
uncertain_patterns = ["可能", "大概", "也许", "应该", "估计"]
for pattern in uncertain_patterns:
if pattern in agent_output:
return {
"hallucination": True,
"reason": f"输出包含不确定的表述:{pattern}"
}
return {"hallucination": False}
def _is_info_from_tool(self, agent_output: str, tool_result: Dict) -> bool:
"""检查输出信息是否来自工具返回结果"""
# 简化:检查输出是否包含工具返回的关键信息
for value in tool_result.values():
if str(value) in agent_output:
return True
return False
def _check_contradiction(self, agent_output: str) -> str:
"""检查输出是否与知识库矛盾"""
for key, value in self.knowledge_base.items():
if key in agent_output and str(value) not in agent_output:
return f"{key} 应该是 {value},但输出说是别的"
return ""
# 使用示例
knowledge_base = {
"腾讯股价": 123.45,
"北京天气": "晴天"
}
detector = HallucinationDetector(knowledge_base)
# 测试 1:正常输出(无幻觉)
output1 = "腾讯的股价是 123.45 元"
tool_results1 = [{"price": 123.45}]
result1 = detector.detect("腾讯股价是多少?", output1, tool_results1)
print(f"检测结果 1:{result1}")
# 测试 2:幻觉(工具未返回的信息)
output2 = "腾讯的股价是 123.45 元,市盈率是 18.5"
tool_results2 = [{"price": 123.45}] # 没有返回市盈率
result2 = detector.detect("腾讯股价是多少?", output2, tool_results2)
print(f"检测结果 2:{result2}")
# 测试 3:幻觉(与知识库矛盾)
output3 = "腾讯的股价是 999.99 元"
tool_results3 = [{"price": 123.45}]
result3 = detector.detect("腾讯股价是多少?", output3, tool_results3)
print(f"检测结果 3:{result3}")
# 测试 4:幻觉(不确定的表述)
output4 = "腾讯的股价大概是 123 元左右"
tool_results4 = [{"price": 123.45}]
result4 = detector.detect("腾讯股价是多少?", output4, tool_results4)
print(f"检测结果 4:{result4}")
更先进的幻觉检测:用 LLM 做 Judge
class LLMAsJudgeHallucinationDetector:
"""用 LLM 做 Judge 检测幻觉"""
def __init__(self, judge_llm):
self.judge_llm = judge_llm
def detect(self, user_query: str, agent_output: str, tool_results: List[Dict] = None) -> Dict[str, Any]:
"""用 LLM 判断输出是否包含幻觉"""
# 构建 Judge Prompt
judge_prompt = f"""
你是一个事实核查员。请判断 Agent 的输出是否包含幻觉(编造的信息)。
用户问题:{user_query}
Agent 输出:
{agent_output}
工具返回结果:
{json.dumps(tool_results, ensure_ascii=False) if tool_results else "(无工具调用)"}
请判断 Agent 输出是否包含幻觉(即:输出包含工具未返回的信息,或与已知事实矛盾)。
输出格式(JSON):
```json
{{
"hallucination": true/false,
"reason": "判断理由"
}}
“”"
# 调用 Judge LLM
judge_output = self.judge_llm.call(judge_prompt)
# 解析 Judge 输出
try:
result = json.loads(judge_output)
return result
except json.JSONDecodeError:
# 解析失败,返回未知
return {"hallucination": "unknown", "reason": "Judge LLM 输出格式错误"}
# 使用示例
class MockJudgeLLM:
def call(self, prompt: str) -> str:
# 模拟 Judge LLM 输出
return '{"hallucination": false, "reason": "输出与工具返回结果一致"}'
judge_llm = MockJudgeLLM()
detector = LLMAsJudgeHallucinationDetector(judge_llm)
# 测试
output = "腾讯的股价是 123.45 元"
tool_results = [{"price": 123.45}]
result = detector.detect("腾讯股价是多少?", output, tool_results)
print(f"Judge 检测结果:{result}")
优点:准确检测幻觉,提高输出可信度
缺点:增加延迟和成本(需要调用 Judge LLM)
效果对比
| 方案 | 幻觉减少 | 工具选择准确率提升 | 实现难度 | 适用场景 |
|---|---|---|---|---|
| 优化工具描述 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐ | 所有场景(基础) |
| Few-shot 示例 | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ | 工具选择复杂 |
| 输出格式约束 | ⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ | 输出格式固定 |
| 工具选择验证 | N/A | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 工具数量多 |
| 幻觉检测 | ⭐⭐⭐⭐⭐ | N/A | ⭐⭐⭐⭐ | 高可信度要求 |
避坑指南
1. 工具描述不是越详细越好
错误做法:
# 描述太长(占用大量 Token)
"description": "获取天气。这个函数可以查询全球任意城市的天气,包括温度、湿度、风速、风向、气压、能见度、云量、紫外线指数、空气质量指数、..."
正确做法:
# 描述简洁但完整(控制在 200 字以内)
"description": "获取指定城市的当前天气(温度、天气状况)。支持城市:北京、上海、广州、深圳、杭州、成都。"
2. Few-shot 示例不是越多越好
错误做法:
# 10 个示例(占用大量 Token)
examples = [示例1, 示例2, ..., 示例10]
正确做法:
# 3-5 个精选示例(覆盖常见场景)
examples = [示例1, 示例2, 示例3] # 3 个就够了
3. 幻觉检测不是万能的
错误做法:
# 对所有输出都做幻觉检测(成本高)
if True: # 无条件检测
detector.detect(...)
正确做法:
# 只对高风险输出做检测(成本高,谨慎使用)
if risk_level == "high": # 例如:金融、医疗场景
detector.detect(...)
延伸思考
1. 如何自动优化工具描述?
方案:用 LLM 生成工具描述,人工审核后使用。
def auto_generate_tool_description(tool_code: str) -> str:
"""用 LLM 自动生成工具描述"""
prompt = f"""
请根据以下工具代码,生成清晰、详细的工具描述(包含:功能、参数、返回值、注意事项)。
工具代码:
{tool_code}
输出格式(JSON):
```json
{{
"name": "工具名",
"description": "工具描述",
"parameters": {{"参数名": "参数描述"}},
"returns": "返回值描述"
}}
“”"
return llm.call(prompt)
### 2. 如何让 Agent 自我纠正工具选择错误?
**方案**:让 Agent 在调用工具前,先"思考"一下。
```python
# Agent Prompt 模板(带思考步骤)
prompt = f"""
用户问题:{user_query}
请按以下步骤思考:
1. 用户想要什么信息?
2. 我有哪些工具可以用?
3. 哪个工具最适合?为什么?
4. 需要哪些参数?从哪里获取?
然后,输出工具调用 JSON。
"""
3. 如何衡量幻觉减少的效果?
方案:用标注数据集评测。
def evaluate_hallucination_reduction(agent, test_dataset: List[Dict]) -> Dict:
"""
评测幻觉减少效果
test_dataset: [
{"user_query": "...", "expected_output": "...", "tool_results": [...]},
...
]
"""
results = {"hallucination": 0, "total": len(test_dataset)}
for item in test_dataset:
agent_output = agent.run(item["user_query"])
# 检测幻觉
detection = detector.detect(item["user_query"], agent_output, item["tool_results"])
if detection["hallucination"]:
results["hallucination"] += 1
results["hallucination_rate"] = results["hallucination"] / results["total"]
return results
总结
幻觉和工具选择错误是 Agent 开发的核心痛点,需要组合多种方案:
基础方案(必做) → 优化工具描述 + Few-shot 示例
进阶方案(推荐) → 输出格式约束 + 工具选择验证
高级方案(可选) → 幻觉检测(成本高,高风险场景用)
关键原则:
- 工具描述要清晰、详细(但不要太长)
- Few-shot 示例要精选(3-5 个足够)
- 输出格式要约束(减少自由发挥)
- 工具选择要验证(提前发现问题)
- 高风险场景要检测幻觉(提高可信度)
下一篇预告:《Agent 开发实战:多 Agent 死循环的 5 个解决方案》
更多推荐



所有评论(0)