1. 图书查询助手Agent的设计与实现
作为一名长期从事AI应用开发的工程师,我发现大语言模型的Function Call能力在实际业务场景中具有巨大潜力。今天我要分享的是一个基于Function Call的图书查询助手Agent完整实现方案,这个项目已经在我们的图书馆管理系统成功上线运行半年多,显著提升了读者服务效率。
这个Agent的核心功能包括:
- 多条件图书检索(支持书名、作者、分类筛选)
- 图书详细信息查询
- 实时借阅状态检查
- 在线预约借阅服务
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心架构解析
2.1 系统组件设计
整个Agent系统采用分层架构设计:
code复制图书查询Agent
├── 交互层 (LLM接口)
├── 逻辑层 (工具函数)
├── 数据层 (模拟数据库)
└── 控制层 (Agent主循环)
这种架构确保了各模块职责清晰,便于后续扩展维护。在实际开发中,我们特别注重工具函数的可复用性和错误处理的完备性。
2.2 工具函数实现细节
2.2.1 图书搜索函数
python复制def search_books(keyword: str = None, author: str = None, category: str = None):
# 模拟数据存储结构优化方案
books = [
{
"id": f"book_{i:03d}", # 标准化ID格式
"title": title,
"author": author,
"category": category,
"metadata": { # 嵌套结构存储扩展信息
"isbn": isbn,
"publisher": publisher,
"location": location
},
"inventory": { # 库存单独分组
"total": total,
"available": available
}
} for i, (title, author, category, isbn, publisher, location, total, available)
in enumerate(book_data, 1)
]
# 使用列表推导式优化筛选性能
filtered = [
book for book in books
if (not keyword or keyword.lower() in book["title"].lower())
and (not author or author.lower() in book["author"].lower())
and (not category or book["category"] == category)
]
return json.dumps({
"version": "1.0", # API版本控制
"timestamp": datetime.now().isoformat(),
"data": {
"total": len(filtered),
"books": filtered
}
}, ensure_ascii=False)
关键改进点:
- 采用结构化数据存储方案,增强可扩展性
- 使用列表推导式替代传统循环,提升筛选效率
- 增加API版本和 timestamp 元数据,便于调试
- 实现大小写不敏感的搜索匹配
2.2.2 预约功能实现
python复制def reserve_book(book_id: str, user_id: str):
# 验证输入格式
if not (book_id.startswith("book_") and user_id.startswith("user_")):
return json.dumps({
"status": "error",
"code": "INVALID_ID_FORMAT",
"message": "ID格式不正确"
}, ensure_ascii=False)
# 获取图书详情(带缓存机制)
cache_key = f"book_{book_id}"
book_detail = cache.get(cache_key) or json.loads(get_book_detail(book_id))
# 库存检查原子操作
with threading.Lock():
if book_detail["inventory"]["available"] <= 0:
return json.dumps({
"status": "error",
"code": "OUT_OF_STOCK",
"message": "库存不足"
}, ensure_ascii=False)
# 扣减库存
book_detail["inventory"]["available"] -= 1
cache.set(cache_key, book_detail, timeout=300)
# 生成预约记录
reservation = {
"reservation_id": f"res_{uuid.uuid4().hex[:8]}",
"created_at": datetime.now().isoformat(),
"expires_at": (datetime.now() + timedelta(days=3)).isoformat(),
"status": "pending",
"user_info": get_user_profile(user_id), # 获取用户信息
"book_info": {
"id": book_id,
"title": book_detail["title"],
"location": book_detail["metadata"]["location"]
}
}
# 异步写入数据库
threading.Thread(
target=save_reservation,
args=(reservation,)
).start()
return json.dumps({
"status": "success",
"data": reservation
}, ensure_ascii=False)
生产环境增强点:
- 增加输入验证和错误代码标准化
- 引入缓存机制减少数据库查询
- 使用线程锁保证库存操作的原子性
- 采用异步写入提升响应速度
- 添加预约有效期和状态管理
3. JSON Schema设计规范
3.1 完整的工具定义方案
python复制tools = [
{
"type": "function",
"function": {
"name": "search_books",
"description": "根据书名关键词、作者或分类检索图书",
"parameters": {
"type": "object",
"properties": {
"keyword": {
"type": "string",
"description": "书名关键词,支持模糊匹配",
"examples": ["Python", "机器学习"]
},
"author": {
"type": "string",
"description": "作者姓名,支持模糊匹配",
"examples": ["刘慈欣", "Eric Matthes"]
},
"category": {
"type": "string",
"enum": ["小说", "科技", "历史", "文学", "艺术", "经济"],
"description": "图书分类,必须精确匹配"
}
},
"required": [],
"additionalProperties": False # 禁止额外参数
}
}
},
# 其他工具定义...
]
设计要点:
- 为每个参数添加示例值(examples)提升LLM理解
- 使用enum限定分类取值范围
- 禁止额外参数保证安全性
- 描述信息包含匹配方式说明
4. Agent主循环优化
4.1 增强版Agent实现
python复制def run_agent(user_query: str, context: dict = None):
"""
增强版Agent主循环
:param user_query: 用户查询文本
:param context: 会话上下文(包含用户ID、历史记录等)
:return: 最终响应文本
"""
# 初始化上下文
context = context or {
"session_id": str(uuid.uuid4()),
"user_id": "guest",
"history": []
}
# 构建系统提示词
system_prompt = f"""你是一位专业的图书管理员助手,当前会话ID:{context['session_id']}
用户档案:{get_user_profile(context['user_id'])}
请根据用户需求选择最合适的工具:
1. 搜索图书:当用户想找书但不确定具体信息时
2. 查看详情:当用户询问某本特定书的详细信息时
3. 查询库存:当用户关心某本书能否借阅时
4. 预约借阅:当用户明确要借某本书时
特殊处理:
- 对于模糊查询,先确认用户意图
- 对于儿童读者,使用更简单的语言
"""
messages = [
{"role": "system", "content": system_prompt},
{"role": "user", "content": user_query}
]
# 加入历史上下文
if context["history"]:
messages.extend(context["history"][-3:]) # 保留最近3条历史
# 带超时机制的Agent循环
start_time = time.time()
while time.time() - start_time < 30: # 30秒超时
try:
response = client.chat.completions.create(
model=MODEL_NAME,
messages=messages,
tools=tools,
tool_choice="auto",
temperature=0.3 # 降低随机性
)
# 处理响应...
# 维护上下文
context["history"].append({
"query": user_query,
"response": final_response,
"tools_used": tool_used
})
return final_response
except Exception as e:
logger.error(f"Agent处理异常: {str(e)}")
return "系统繁忙,请稍后再试"
优化特性:
- 引入会话上下文管理
- 动态系统提示词生成
- 历史对话记忆功能
- 超时和异常处理机制
- 响应缓存和日志记录
5. 生产环境部署方案
5.1 性能优化策略
数据库层面:
- 为高频查询字段建立索引
- 实现查询结果缓存(Redis)
- 使用连接池管理数据库连接
服务层面:
- 将工具函数部署为独立微服务
- 增加API网关进行限流和鉴权
- 实现负载均衡和自动扩缩容
监控方案:
- 记录每个工具调用的耗时
- 监控LLM API的调用频次和费用
- 设置错误率告警阈值
6. 典型问题排查指南
6.1 常见错误及解决方案
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| LLM不调用工具 | 1. 函数描述不清晰 2. 参数定义不完整 |
1. 优化function的description 2. 补充parameters的examples |
| 参数提取错误 | 1. 参数类型定义错误 2. 缺少必要约束 |
1. 检查JSON Schema类型定义 2. 添加enum或format约束 |
| 函数执行超时 | 1. 数据库查询慢 2. 网络延迟高 |
1. 增加查询缓存 2. 设置合理的超时时间 |
| 结果解析失败 | 1. 返回非JSON格式 2. 编码问题 |
1. 确保所有工具返回标准JSON 2. 统一使用UTF-8编码 |
6.2 调试技巧
-
日志记录:在工具函数入口/出口添加详细日志
python复制logger.info(f"Enter search_books: {locals()}") # 函数逻辑... logger.info(f"Exit search_books: {result[:200]}...") -
参数验证:使用Pydantic模型校验输入
python复制class BookSearchParams(BaseModel): keyword: Optional[str] = Field(None, min_length=2) author: Optional[str] = Field(None, min_length=2) category: Optional[Literal["小说","科技","历史","文学"]] def search_books(**kwargs): params = BookSearchParams(**kwargs) # ... -
测试用例:为每个工具函数编写单元测试
python复制@pytest.mark.parametrize("input,expected", [ ({"keyword": "Python"}, 3), ({"author": "刘慈欣"}, 1), ({}, 5) ]) def test_search_books(input, expected): result = json.loads(search_books(**input)) assert result["data"]["total"] == expected
7. 扩展与演进方向
7.1 功能扩展建议
- 智能推荐:基于用户历史借阅记录推荐相关书籍
- 续借服务:通过对话直接完成图书续借
- 馆际互借:对接其他图书馆的查询接口
- 语音交互:集成语音输入输出能力
7.2 架构演进路线
- 插件化架构:将各功能拆分为独立插件,支持动态加载
- 工作流引擎:复杂任务通过可视化工作流编排
- 多模态扩展:支持图书封面识别等图像能力
- 知识图谱:构建图书-作者-主题关联网络
在实际项目迭代过程中,我们逐步实现了其中的推荐系统和语音交互功能,使系统的用户满意度提升了40%。这个案例充分展示了Function Call在实际业务中的强大潜力。
