提示词工程,本质上就是通过精心设计向AI提问的方式,来获得更精准更符合预期的回答。
模型本身没有记忆。
例如在 ChatGPT 用户端,聊天框发送内容,并不会直接发给LLM,而是发向了OpenAI的服务器,服务器会做一些处理,缓存对话的历史内容, OpenAI在背后怎么把历史内容发给LLM处理,那就是它们的事了,很大程度影响产品好不好用。
背后产品服务端为我们自动把对话内历史内容喂给LLM,在用户看来就像有了记忆一样。
上面方式,一来一回的聊天功能没有什么问题。
但是问题越来越复杂了,AI Agent除了传递消息、维护历史之外,来拥有工具箱里面有一些它自己定义的工具。
例如 用户问 附近有什么受欢迎的餐厅,LLM收到后响应给Agent 目前的位置经纬度多少,Agent维护历史消息
附近有什么受欢迎的餐厅
目前的位置经纬度多少Agent调用工具箱功能,把位置加到历史对话内容中,然后将 历史对话 都发给LLM。
LLM继续响应 Agent 调用 GoogleMap 搜索,Agent将搜到内容再加到历史对话,历史对话再到LLM, LLM响应,可能AI会根据GoogleMap的餐厅信息进行一些排序,然后用户就看到了一些内容。
更复杂的功能,可能这种交互过程非常非常漫长。
用户能影响到的基本就是最开始的提示词,后面这些交互都是Agent和LLM来回交互,ToolCall、ToolResponse、ToolCall、ToolResponse、……
LLM面对一个越来越长的,充斥着各种中间信息的上下文,用户又没办法及时纠正Agent与LLM交互的行为时。行动方向很容易就跑偏。
如何通过一套程序化的规则,来自动管理和修改这个上下文,确保AI在漫长的自主行动中,始终符合用户的最初要求,这就是上下文工程要解决的核心问题。
上下文到底怎么管理,目前没有一个公认的完美方案。
业界目前有几种常见的作法:
System prompt
1. 分解任务
2. 写任务清单
3. 按清单执行
4. 更新笔记让AI自己精简上下文,记录必要信息,LLM ToolCall让Agent记录笔记文件。
Agent再发内容给LLM时,把笔记文件内容塞到 历史内容的开头和末尾。
问题的根源本质是上下文过长,另一个优化的方向就是让它变短。
最直接的做法就是直接丢掉太老的消息。
Agent可以把 上下文发给LLM,让其对历史消息进行一定的精简提炼,保留关键信息。
Agent就能维护精简后的上下文内容。
LLM响应 ToolResponse 可能非常长,比如包含了一篇上万字的文章,Agent把ToolResponse的内容处理后, 存到一个临时的向量数据库里面。类似RAG。Agent然后替换ToolResponse内容 比如 内容已经存入数据库,提供了一个Tool你可以检索。 这样AI只要查找自己感兴趣的片段就可以了。
例如LLM ToolCall Agent浏览网页内容,Agent可以只提炼网页中的有效信息,而不是直接把 HTML 网页返回的信息加到历史消息后直接返回给 LLM,一定程度能减少冗余信息。
目的只有一个,在人类用户无法实时干预AI行动的时候,确保AI模型始终都记得自己最初的任务是什么。
目前各家产品都一直在迭代,各一段时间就会有变化。