首页 / 资讯中心 / 文章详情

【三个月 AI Agent 实战学习】Day 27:工具设计原则 —— 写好 Docstring 让模型更聪明

【三个月 AI Agent 实战学习】Day 27:工具设计原则 —— 写好 Docstring 让模型更聪明 ★ FEATURED ARTICLE
Day 27工具设计原则 —— 写好 Docstring 让模型更聪明欢迎来到第二十七天在构建 Agent 的过程中工具的质量直接决定了 Agent 的性能。模型能否在正确的时机调用正确的工具并传递正确的参数很大程度上取决于我们如何描述工具。今天我们将深入探讨工具设计的核心原则重点理解Docstring文档字符串对模型行为的影响并通过对比实验让你亲眼看到模糊描述与清晰描述带来的巨大差异。一、今日学习目标理解工具描述Docstring在 Agent 中的关键作用它是模型了解工具的唯一渠道。掌握编写高质量工具描述的原则明确功能、输入输出格式、使用场景、限制条件。学会为参数提供清晰的说明使用Annotated描述参数含义、类型和示例。通过实验定义一个模拟查询公司内部员工薪资的假接口分别用模糊描述和详细描述观察模型何时决定调用它、参数是否正确。能够根据实际需求设计出易于被模型理解并正确调用的工具。二、详细实现步骤步骤 1准备基础环境与前几天类似我们使用 LangChain 和 DeepSeek。确保已安装所需库并初始化模型。新建tool_design_principles.pyimportosfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain_core.toolsimporttoolfromtypingimportAnnotated load_dotenv()llmChatOpenAI(modeldeepseek-chat,api_keyos.getenv(DEEPSEEK_API_KEY),base_urlhttps://api.deepseek.com,temperature0.1)步骤 2设计一个模拟的“员工薪资查询”工具我们模拟一个公司内部系统有一个查询员工薪资的函数但出于隐私考虑它只对特定角色开放例如 HR 或管理员。模型需要理解这个工具的功能和限制才能正确使用。我们定义两个版本的工具一个描述模糊一个描述详细。版本 A模糊描述tooldefget_salary_A(name:str)-str:查询薪资。# 模拟数据库salary_db{张三:25000,李四:18000,王五:22000}ifnameinsalary_db:returnf{name}的薪资是{salary_db[name]}元/月else:returnf未找到员工{name}版本 B详细描述tooldefget_salary_B(name:Annotated[str,员工姓名例如张三、李四])-str:查询公司内部员工的月薪。仅限 HR 或管理员使用普通用户无权查询。如果用户不是 HR 或管理员请不要调用此工具。输入员工姓名返回该员工的月薪数额。# 模拟数据库与版本 A 相同salary_db{张三:25000,李四:18000,王五:22000}ifnameinsalary_db:returnf{name}的薪资是{salary_db[name]}元/月else:returnf未找到员工{name}观察两个工具的描述差异版本 A 的 docstring 只有“查询薪资。”没有说明参数格式、适用对象、限制条件。版本 B 详细说明了功能、使用权限、参数含义并给出了示例。步骤 3将工具绑定到模型并测试我们分别测试模型在两种工具描述下的表现。设计一个场景用户问“张三的工资是多少”但用户没有说明自己是否是 HR。fromlangchain_core.messagesimportHumanMessage# 绑定工具 Allm_with_tool_Allm.bind_tools([get_salary_A])# 绑定工具 Bllm_with_tool_Bllm.bind_tools([get_salary_B])deftest_tool(llm_with_tools,user_input):messages[HumanMessage(contentuser_input)]responsellm_with_tools.invoke(messages)print(模型响应,response)ifresponse.tool_calls:fortcinresponse.tool_calls:print(f 请求调用工具{tc[name]}参数{tc[args]})else:print( 未调用工具直接回答,response.content)user_input张三的工资是多少print( 模糊描述工具 A )test_tool(llm_with_tool_A,user_input)print(\n 详细描述工具 B )test_tool(llm_with_tool_B,user_input)运行脚本观察输出差异。预期观察对于工具 A模型很可能直接调用get_salary_A因为它只知道“查询薪资”而用户的问题正好匹配模型不会考虑权限问题因为描述中没有提到。对于工具 B模型可能会犹豫甚至不调用工具因为它看到描述中说明“仅限 HR 或管理员”而当前用户没有表明身份于是可能会拒绝查询或询问用户是否具有权限。这正是我们想要的工具描述不仅能指导模型“何时调用”还能传达“何时不应该调用”的约束。步骤 4进一步实验参数描述的重要性我们再设计一个工具参数描述清晰与模糊的对比。例如查询天气模糊描述参数city没有说明详细描述则加上Annotated[str, 城市名称如北京、上海]。测试模型是否能正确填充参数。tooldefget_weather_vague(city:str)-str:查询天气。returnf{city}天气晴tooldefget_weather_detailed(city:Annotated[str,城市名称例如北京、上海])-str:查询指定城市的当前天气输入城市中文名称返回天气描述。returnf{city}天气晴测试用户输入“今天首都的天气怎么样”模型需要推断“首都”北京llm_vaguellm.bind_tools([get_weather_vague])llm_detailedllm.bind_tools([get_weather_detailed])print(模糊参数工具)test_tool(llm_vague,今天首都的天气怎么样)print(详细参数工具)test_tool(llm_detailed,今天首都的天气怎么样)通常详细描述工具会让模型更倾向于将“首都”转换为“北京”而模糊工具可能直接使用“首都”作为 city 参数导致工具无法识别。步骤 5最佳实践总结通过上述实验我们可以总结出编写高质量工具描述的原则功能明确一句话清楚说明工具做什么。使用场景说明在什么情况下应该调用它。限制条件如果工具只适用于特定用户、特定数据范围或特定格式务必写明。参数描述使用Annotated为每个参数提供类型、含义、格式示例必要时说明取值范围。输出格式说明返回值的格式帮助模型理解如何使用结果。错误处理如果工具可能失败描述中可以提及或者工具内部返回清晰错误信息。步骤 6练习改进一个工具将之前定义的search工具进行改进使其描述更符合最佳实践。原版tooldefsearch(query:str)-str:搜索信息输入关键词或问题返回相关答案。# 模拟搜索...改进版tooldefsearch_improved(query:Annotated[str,搜索关键词或完整问题例如北京天气 或 人工智能是什么])-str:在内部知识库中搜索信息。当你需要获取实时数据、事实性知识或你不确定的信息时使用此工具。返回一段相关的文本答案如果没有找到结果返回未找到相关信息。# 模拟搜索...比较模型在类似问题下的调用准确率。三、常见问题与调试Q1工具描述写得很长模型反而不用了→ 描述不是越长越好要精炼、重点突出。如果太长模型可能抓不住重点或者误解。建议用 1-3 句话描述核心功能和限制关键信息放在开头。可以用分点或强调符号。Q2参数描述用Annotated时是否需要写默认值→ 如果参数有默认值可以在函数签名中给出默认值模型会知道该参数可省略。同时用Annotated描述含义不必在描述中重复默认值。Q3模型还是错误地调用了受限工具怎么办→ 可以在工具内部进行权限校验返回“权限不足”错误。同时在系统提示词中再次强调权限规则。这样即使模型错误调用工具也能给出合理反馈模型可根据反馈调整。Q4如何处理工具名称和描述冲突→ 工具名称应简洁且有意义描述应补充细节。避免名称产生误导例如名称是get_weather就不要让它做查询股票的事。Q5能否在工具描述中加入示例→ 可以例如在 docstring 中写“示例输入 ‘北京’ 返回 ‘晴’”。这有助于模型理解参数格式但不要过度否则占用过多 Token。通常参数描述中的示例已经足够。Q6如何测试工具描述的质量→ 构建一组覆盖不同场景的测试用例统计模型调用工具的正确率、参数正确率。根据结果迭代描述。这是工程中的常规做法。四、今日总结与作业今天你完成了✅ 理解了工具描述对模型行为的重要影响。✅ 通过对比实验直观看到了模糊描述与详细描述导致的不同调用行为。✅ 掌握了编写高质量工具描述的原则和具体技巧。✅ 练习了如何改进现有工具的描述。今日作业必做设计一个名为book_meeting的工具用于预订会议室。要求功能根据日期、时间段、参会人数预订会议室。参数date日期格式 YYYY-MM-DD、start_time开始时间格式 HH:MM、duration时长小时、attendees参会人数。使用Annotated为每个参数提供详细描述并在 docstring 中说明使用场景、限制如最多 20 人和返回值格式。将工具绑定到模型测试用户输入“帮我订一个明天下午 2 点到 4 点的会议室大概 10 个人”观察模型是否能正确解析参数并调用工具。尝试故意在描述中省略一个重要限制例如不说明“最多 20 人”再看模型在用户要求 50 人会议时是否仍会调用工具。分析为什么限制描述很重要。明日预告我们将继续深入 Agent 的工程化学习如何让 Agent 使用真实世界的网络搜索工具如 DuckDuckGo并处理网络请求中的各种问题。有任何问题欢迎随时提问
阅读完成 · 觉得有帮助?
咨询建站