构建可靠的代理系统并非易事。原型演示可能很快就能跑通,但要打造能支撑关键业务应用的可靠代理,则需要大量细致的工作。LangChain团队曾对代理构建者进行调查,结果显示“性能质量”是阻碍代理投入生产的最主要因素。那么,为什么代理有时表现不佳?根本原因在于LLM出错。而LLM出错通常有两个原因:模型本身不够强大,或者传递给模型的上下文不正确或不完整。根据经验,后者更为常见。
上下文的缺失可能源于多种情况:系统消息过短或不完整、用户输入模糊、无法访问正确的工具、工具描述不佳、未传入正确的上下文、工具响应格式混乱等。因此,构建可靠代理系统的核心难点在于确保LLM在每一步都能获得合适的上下文。这既包括控制进入LLM的确切内容,也包括运行适当的步骤来生成相关内容。任何框架如果让你更难控制传递给LLM的内容,那就是在给你添乱。
代理系统并不仅限于代理。Anthropic对代理的定义较为精确:代理系统包括工作流和代理。工作流是通过预定义代码路径编排LLM和工具的系统;代理则是LLM动态指导自身流程和工具使用,保持对任务完成方式的控制。Anthropic还将两者统称为“代理系统”,并指出生产环境中几乎所有的代理系统都是工作流和代理的结合。OpenAI的定义则较为模糊,称代理是“能独立为你完成任务的系统”,这更像是一种思想领导力,而非实用定义。
在实践中,我们更应关注系统的“代理性”程度,而非纠结于某物是否算作代理。正如吴恩达所言,用形容词“代理性”来思考,可以让我们以不同程度的代理性来审视系统,而不是非黑即白。工作流和代理并非互斥,而是连续光谱上的不同点。大多数生产系统位于两者之间。
构建代理系统时,需要考虑两个关键权衡:可预测性与代理性,以及低门槛与高天花板。随着系统代理性增强,其可预测性会降低。有时你需要系统可预测,以获取用户信任或满足监管要求。可靠性虽不完全等同于可预测性,但两者在实践中紧密相关。你需要根据应用场景决定在光谱上的位置。LangGraph允许你构建位于该曲线任意位置的应用,助你移动到理想点。
框架的门槛和天花板也值得考量。低门槛框架对初学者友好,易于上手;高门槛框架学习曲线陡峭,需要大量专业知识才能有效使用。低天花板框架能力有限,很快会超出其适用范围;高天花板框架则为高级用例提供广泛能力和灵活性。工作流框架通常天花板高但门槛也高,你需要编写大量代理逻辑;而代理框架往往门槛低但天花板也低。
LangGraph是一个事件驱动的编排框架,同时提供声明式和命令式API,并在底层框架之上构建了一系列代理抽象。它支持两种主要使用方式:声明式的基于图的语法,以及基于底层框架的代理抽象。LangGraph还支持函数式API和底层事件驱动API,并提供Python和TypeScript版本。代理系统可以表示为节点和边,节点代表工作单元,边代表转换。节点和边就是普通的Python或TypeScript代码,因此虽然图的结构以声明式表示,但图内逻辑是普通的命令式代码。边可以是固定的或条件的,路径可以完全动态。
LangGraph内置持久化层,支持容错、短期记忆和长期记忆,还支持“人在回路”模式,如中断、批准、恢复和时间旅行。它内置流式支持,可流式传输令牌、节点更新和任意事件。LangGraph与LangSmith无缝集成,便于调试、评估和可观测性。
总之,代理框架种类繁多,比较时需区分多个维度:工作流与代理、声明式与非声明式、代理抽象、多代理等。大多数框架只是提供代理抽象,而非真正的编排框架。理解这些维度有助于选择适合的工具。正如Anthropic所建议,构建LLM应用时应寻找最简单的解决方案,仅在需要时增加复杂性。有时甚至不需要构建代理系统。代理系统通常以延迟和成本换取更好的任务性能,需权衡是否值得。对于定义明确的任务,工作流提供可预测性和一致性;而在需要灵活性和模型驱动决策的场景,代理是更好的选择。