一般来说,LLM 模型无法主动更新自己的知识,其知识范围包括训练时的知识和提示上下文提供的附加信息。
事实幻觉:大模型以错误虚构的提示上下文胡编乱造
解决方法可以让 LLM 在本地知识库、外部搜索等检索,确认真实再进行输出。本地知识库和外部搜索引擎称为外部工具
LangChain 通过代理调用外部工具。代理可以认为是对外部工具的接口和调用的封装
- 根据输入决定使用什么外部工具
- 将一个外部工具的输出作为另一个外部工具的输入
与链相比,代理可以不硬编码操作序列,而是由大模型自主选择与外部工具的交互
ReAct
ReAct 即推理(Reasoning)+行动(Acting),LLM 通过生成推理痕迹和特定行动实现更大的协同作用
- Reasoning:观察当前环境和状态,生成推理轨迹
- Acting:指导大模型采取下一步的行动,与外部工具交互收集信息,或给出最终答案
ReAct 会记录每一步的推理过程以提高可信度。LangChain 通过代理 Proxy 使用 ReAct。
- 加载外部工具依赖(如搜索工具
SerpAPI,数学工具llm-math) - 使用
load_tools(['serpapi', 'llm-math'], llm=llm)加载工具 - 使用工具链初始化代理:
initialize_agent(<tools>, <llm>, <agent>, <verbose>)tools:前面load_tools创建的对象agent:代理类型,如AgentType.ZERO_SHOT_REACT_DESCRIPTION,STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION等
SerpAPI需要注册申请 Key,并设置os.environ["SERPAPI_API_KEY"]环境变量
组件
LangChain 代理主要由以下几种组件组成:
- 代理:Agent,用于决定下一步行为,由 LLM+提示组成
- 代理性格,角色等
- 任务背景,更多与任务相关的上下文等
- 提示策略,如 ReAct 等
- 工具:Tools,代理可以调用的函数,以及对工具的正确描述
- 工具包:Toolkits,一组用于完成特定目标的工具集合,如
Office365 - 代理执行器:AgentExecutor,代理运行的环境、引擎,调用代理并执行代理操作,处理工具不存在、工具出错、输出问题、决策观察和日志等功能
Plan
通过调试查看 AgentExecutor 运行过程,思考 - 观察 - 行动提示词如下:
- 告诉 LLM 尽可能好的解答问题,并可以使用工具
- 描述提供的工具
- 指导模型的推导格式
- Question:问题
- Thought:思考
- Action:行动
- 以上过程可以重复多次
- 开始,描述问题
每次 Q-A-T 过程,LLM 都会推进任务进度,直到任务完成,LLM 直到结果(AgentFinish)为止
Structured Tool Chat
结构化工具对话代理:允许更复杂、多方面的交互,通过结构化工具箱调用多个工具
- 文件管理工具集:支持文件系统操作
- Web 浏览器工具集:官方的 PlayWright 浏览器工具包,允许代理访问网站
PlayWright
开源自动化框架,模拟用户操作网页自动化网页交互和测试,支持 Chrome、Firefox、Safari 多种浏览器
pip install playwright安装playwrightplaywright install安装浏览器- 测试访问
使用结构化工具对话代理
结构化工具对话代理的 AgentType 为 STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION,PlayWrightBrowserToolkit 工具集提供 PlayWright 支持
Self-Ask with Search
利用追问+中间答案辅助大模型寻找事实性问题的过渡性答案,引出最终答案,其 AgentType 为 SELF_ASK_WITH_SEARCH
多跳问题:Multi-hop question,为了得到最终答案,需要进行多步推理或多次查询。这种问题不能直接通过单一的查询或信息源得到答案,而是需要跨越多个信息点,或者从多个数据来源进行组合和整合。
Self-Ask with Search 代理主要用于解决多跳问题。
- 工具集合:包含解决问题的搜索工具,可以用来查询和验证多个信息点
- 逐步逼近:根据第一个问题的答案,提出进一步的问题,直到得到最终答案
- 自我提问与搜索:代理可以自己提问并搜索答案
- 决策链:代理通过一个决策链来执行任务,使其可以跟踪和处理复杂的多跳问题
Plan and execute
Plan and execute 通过首先计划要做什么,然后执行子任务来实现目标。
首先,制定一个计划,并将整个任务划分为更小的子任务;然后按照该计划执行子任务。
- 计划由一个大语言模型代理(负责推理)完成。
- 执行由另一个大语言模型代理(负责调用工具)完成。