当前位置: 首页 > news >正文

回头看基础,TemplatePrompt和MessagePrompt

最近想实现一个简单的功能:用户输入一个餐厅名关键词,agent调用高德地图api,拿到餐厅的一些关键信息,如准确店名、地址(文字地址+经纬度)、评分、人均、营业时间等,接下来agent将接口返回的数据整理,形成更精简的结构化json,存入数据库。只获取餐厅信息并存库是没太多业务价值的,第二步我会给这个agent提供更多全网搜索餐厅信息、评价等工具,让存储的信息不止包含基本信息,还要包含agent处理过的评价。不过第二步是后话了,今天先记录我在做第一步过程中遇到的问题,和我的思考。

我先封装了两个请求高德地图api接口的方法,它们属于一个RestaurantPoi类。

 1 import requests
 2 import os
 3 from dotenv import load_dotenv
 4 
 5 load_dotenv()
 6 
 7 class RestautantPoi:
 8     """
 9         提供餐厅地图位置等信息查询工具
10     """
11 
12     def get_city_info(self):
13         """
14             获取当前定位城市
15         """
16         url = os.getenv('IP_POSITION_URL')
17         try:
18             res = requests.get(url,params={'key': os.getenv('AMAP_API_KEY')})
19             res.raise_for_status()
20 
21             return res.json()
22         except Exception as e:
23             return None
24         
25     def amap_search(self, keyword, city=''):
26         """
27             根据餐厅关键词在地图上搜索店铺
28         """
29         if not city:
30             ip_city_info = self.get_city_info()
31             city = ip_city_info.get('adcode') if ip_city_info else ''
32         
33         url = os.getenv('SEARCH_RESTAURANT_URL')
34         params = {
35             'key': os.getenv('AMAP_API_KEY'),
36             'keywords': keyword,
37             'types': os.getenv('RESTAURANT_TYPE_CODE'),
38             'city': city
39         }
40         try:
41             res = requests.get(url, params=params)
42             res.raise_for_status()
43 
44             json = res.json()
45             if json.get('status') == 0:
46                 raise Exception(json.get('info'))
47             return json.get('pois')
48         except Exception as e:
49             print(f'搜索遇到错误{e}')
50             return None
View Code

然后,我定义了一个langchain_tool,在里面实例化RestaurantPoi类并调用查询方法。

 1 from langchain_core.tools import tool as langchain_tool
 2 from poi_api import RestautantPoi
 3 
 4 # 定义工具
 5 @langchain_tool
 6 def search_restaurant(query: str) -> list:
 7     """
 8     根据关键字搜索餐厅方法
 9     args:
10         query: str 餐厅名关键字
11     returns:
12         rest_info: list 餐厅信息列表
13     """
14     print(f'\n --- tools: 工具调用:search_restaurant,查询:{query} ---')
15     try:
16         poi_obj = RestautantPoi()
17         rests = poi_obj.amap_search(query)
18         if len(rests) > 0:
19             print('--- 工具调用结束 ---')
20             return rests
21         else:
22             raise Exception('没有获取到餐厅信息')
23     except Exception as e:
24         print(f'--- 餐厅搜索工具出错: {e}')
25         return []
View Code

接下来,定义一个agent,传入工具和prompt,期待它返回一个精简后的结构化json。

 1 from langchain_openai import ChatOpenAI
 2 from langchain_core.messages import SystemMessage
 3 from langchain.agents import create_agent
 4 
 5 tools = [search_restaurant]
 6     
 7 # 创建工具调用agent
 8 if llm:
 9     agent_prompt = SystemMessage("""
10     你是一个帮助用户搜索并整理餐厅信息的助手。
11     用户输入中会包含餐厅名关键词{keyword}。
12     而你需要使用工具,根据关键词搜索餐厅信息,并从中整理出最匹配的一家。
13     读取并整理餐厅信息,从名字、人均、评分、位置(经纬度)四个方面,进行格式化的输出。
14     仅输出json,不要进行多余文本输出。
15     --------
16     正常输出example:
17     {
18         'name': '云水谣云南菜',
19         'price': '¥79',
20         'rate': '4.2',
21         'location': '115.984339,40.474397'
22     }
23     ---------
24     部分信息未找到输出example:
25     {
26         'name': '无二和牛烧',
27         'price': '暂无',
28         'rate': '暂无',
29         'location': '115.984339,40.474397'
30     }
31     ----------
32     工具未找到合适餐厅输出example:
33     { }
34     """)
35 
36 agent = create_agent(
37     model=llm,
38     tools=tools,
39     system_prompt=agent_prompt)
40 
41 if __name__ == '__main__':
42     res = agent.invoke({"messages": [{"role": "user", "content": "帮我查一下离故宫最近的四季民福烤鸭店"}]})
43     print('------ Agent 回复: -------')
44     print(res)
View Code

补充一下llm的实例化:

1 try:
2     llm = ChatOpenAI(model='gpt-4o',temperature=0)
3     print(f'语言模型初始化成功')
4 except Exception as e:
5     print(f'语言模型初始化失败{e}')
6     llm = None
View Code

上面这段定义agent的代码有两个问题,虽然能跑起来,但结果和预期不同。

第一个是我对大模型function call的理解不够深入,已知大模型可以被理解成一个巨大的预测函数,函数的特性是一次调用一次输出,没有定义成递归的前提下,不会自己调用自己,也不会有两次输出。

那么我的prompt是怎么写的呢?我希望大模型先调用工具,拿到工具函数的返回后,再优化这个返回,输出精简json。

但是对于大模型来说,输出工具调用就完成这一次调用,后面工具调用的结果,它无感知了。正常的流程应该我来编排,将工具调用的结果合并前面的历史记录,再次传递给大模型,由模型进行处理。这是我这个工具调用初学者犯的一个小白错误。同时,负责判断意图并调用工具的agent(因为后续会增加更多的搜索工具)和负责信息整理优化的agent,应该分开作为两个独立功能的agent来设计,每个agent只负责自己份内的工作,这样理论上效果才最好。

我需要将prompt拆开,工具调用就只进行工具调用的提示;优化json就只进行json优化的提示。

那么第二个问题来了:我prompt中的'keyword'真的用到了吗?

我虽然使用了SystemMessage,并进行了模版插值,但agent是以

agent.invoke({"messages": [{"role": "user", "content": "帮我查一下离故宫最近的四季民福烤鸭店"}]})
的形式调用的,我混淆了TemplatePrompt和MessagePrompt!
 
http://www.jsqmd.com/news/57146/

相关文章:

  • 2025年碳纤木门制造商权威推荐榜单:套装门/实木门/无漆木门源头厂家精选
  • 2025年氯化镁阻化剂定制厂家权威推荐榜单:LH—Z01阻化剂‌/煤矿专用阻化剂‌/MSF—II阻化剂‌源头厂家精选
  • 2025商丘特色餐饮品牌口碑榜:商丘任广涛干锅鸭怎么样?
  • 【AP出版 | CPCI检索】第八届人文教育与社会科学国际学术会议(ICHESS 2025)
  • 10418_基于SSM的旅游管理系统
  • 2025年广州儿童黄埔军校夏令营学校权威推荐榜单:广州黄埔军校夏令营招生服务商/广州小学生黄埔军校军事夏令营培训/广州黄埔军校军事夏令营公司精选
  • 2025年耙式干燥设备制造厂权威推荐榜单:新型耙式干燥机‌/真空耙式干燥机‌/耙式干燥器‌源头厂家精选
  • 【IEEE出版 | EI检索】第二届机器学习、计算智能与模式识别国际学术会议(MLCIPR 2025)
  • 深度揭秘:湖南省网安基地——由“安服公司”开的网络安全培训班,到底是坑还是宝藏?​ - 指南
  • 百度不收录境外服务器是真是假?
  • SQL子查询完全指南:从零掌握嵌套查询的三种用法与最佳实践 - 详解
  • Rust自定义迭代器
  • 适合幼儿园开展的STEM课程品牌介绍及分析
  • 分库分表全面总结
  • 2025年深圳品牌策划公司推荐排行榜:深圳品牌策划公司能整合
  • 2025年中国十大网店代运营公司推荐:代运营哪家强?
  • 2025年户外橡胶地垫制造厂权威推荐榜单:减震橡胶地垫/公园橡胶地垫/复合橡胶地垫源头厂家精选
  • 靠谱的国际短信验证码平台,短信验证码服务商盘点,兼顾速度、安全与成本控制!
  • 【JPCS出版 | EI检索】第七届国际科技创新学术交流大会暨机械工程与自动化国际学术会议(MEA 2025)
  • 这个代码有什么用
  • 2025年日字扣生产厂家权威推荐榜单:箱包塑料配件‌/塑料制品‌/塑胶扣具‌源头厂家精选
  • 非接图标(适用于屏幕大小为240*320)
  • 2025年磷酸铁回转窑生产厂家权威推荐榜单:回转窑干燥设备‌/磷酸铁锂回转窑‌/大豆渣回转窑干燥机‌源头厂家精选
  • JavaScript基础笔记碎片-对象、数组、Map与Set
  • java17版本,用IDEA开发,在JavaFX中无法找到com.google.gson。
  • 2025手机配件到迪拜物流专线送仓TOP5权威推荐:甄选企业
  • Visual Studio Code 轻量不简陋!VS Code:零基础编程者的第一款「万能编辑器」安装+中文设置步骤
  • 推荐几家海外展会推广公司,五家效果不错的海外展会营销推广平台详细介绍
  • 2025年12月AI 编程代码生成效率实战推荐:技术性能与应用场景的全面分析
  • 我是皇帝