首次通过API与大型语言模型交互时,可能会感到一种突破。仅需几行代码,便能生成类人文本、回答复杂问题或总结长文档。然而,从这些初步、令人印象深刻的展示,转向构建一个完整、可用的应用时,会遇到一系列重复出现的工程难题。单独的LLM调用是无状态的,且与其他系统脱节,这对大多数实际应用场景来说是一个明显的局限。应用开发中的常见问题当您开始构建由LLM驱动的应用时,很快就会遇到一些不止是简单地向模型发送提示的难题:管理上下文与历史记录: LLM API是无状态的。每次API调用都是独立的,没有对先前交互的记忆。为了构建聊天机器人或任何会话界面,您必须手动管理对话历史。这包括存储旧消息,决定哪些与当前轮次相关,并将它们格式化到提示中,同时还要注意模型有限的上下文窗口。连接外部数据: 预训练LLM的知识在训练时即已确定。它不知道您的私人文档、公司数据库或其知识截止日期后发生的事件。要构建一个能够回答关于特定专有信息的应用,您需要实现一个数据流,从某个来源获取相关数据并将其作为上下文提供给LLM。这种模式,即检索增强生成(RAG),需要大量前期工作,包括加载、拆分和存储数据以便高效检索。协调多个步骤: 许多复杂的任务无法通过一次LLM调用完成。设想一个为公司撰写报告的应用。此过程可能包含以下几步:在网上查找关于公司的最新新闻。总结主要发现。访问金融API获取最新股价。将所有这些信息汇编成最终报告。协调这些步骤,将一个输出作为下一个输入,并处理潜在错误,需要编写复杂且通常脆弱的协调逻辑。与API和工具交互: 为了执行发送电子邮件、查询数据库或查看天气等操作,LLM需要访问外部工具。您需要编写代码,让模型选择工具、为该工具的API格式化正确的输入、执行它,然后处理结果。这形成了一个推理循环,模型在此循环中规划并执行一系列操作。统一方法的必要性如果没有框架,每个开发者都不得不从头编写定制的“胶水代码”来解决这些问题。这会导致大量重复工作,并使得应用难以维护和扩展。每次您想更换LLM,或从一个向量数据库切换到另一个时,都必须重写大部分集成代码。正是在这里,像LangChain这样的框架变得不可或缺。它提供了一套标准化的组件和接口,可处理LLM应用开发中常见且重复的任务。您无需编写自定义代码来管理对话历史,而是可以使用内置组件来处理对话状态。您无需从头构建RAG数据流,而是可以利用LangChain的文档加载器、文本拆分器和检索器来组合它。digraph G { rankdir=TB; splines=ortho; node [shape=box, style="rounded,filled", fontname="Arial", fontsize=10]; edge [fontname="Arial", fontsize=9]; subgraph cluster_0 { label = "无框架的应用逻辑"; bgcolor="#f8f9fa"; style="rounded"; user_query [label="用户请求", fillcolor="#bac8ff"]; glue_code1 [label="自定义Python脚本\n(提示格式化,API调用)", shape=parallelogram, fillcolor="#ffc9c9"]; llm_api [label="LLM API", shape=cylinder, fillcolor="#b2f2bb"]; db [label="数据库", shape=cylinder, fillcolor="#ffec99"]; glue_code2 [label="自定义Python脚本\n(数据获取,解析)", shape=parallelogram, fillcolor="#ffc9c9"]; memory_store [label="JSON文件\n(历史记录)", shape=folder, fillcolor="#fcc2d7"]; glue_code3 [label="自定义Python脚本\n(内存管理)", shape=parallelogram, fillcolor="#ffc9c9"]; user_query -> glue_code1; glue_code1 -> llm_api; user_query -> glue_code2; glue_code2 -> db; db -> glue_code1; user_query -> glue_code3; glue_code3 -> memory_store; memory_store -> glue_code1; } subgraph cluster_1 { label = "使用LangChain的应用逻辑"; bgcolor="#f8f9fa"; style="rounded"; user_query_lc [label="用户请求", fillcolor="#bac8ff"]; prompt_template [label="提示\n模板", fillcolor="#a5d8ff"]; model_lc [label="模型", fillcolor="#b2f2bb"]; retriever_lc [label="检索器", fillcolor="#ffec99"]; memory_lc [label="记忆", fillcolor="#fcc2d7"]; chain_lc [label="LangChain 链\n(协调)", fillcolor="#d0bfff", width=2]; user_query_lc -> chain_lc; chain_lc -> prompt_template; chain_lc -> model_lc; chain_lc -> retriever_lc; chain_lc -> memory_lc; prompt_template -> model_lc [style=dashed, arrowhead=none]; retriever_lc -> model_lc [style=dashed, arrowhead=none]; memory_lc -> model_lc [style=dashed, arrowhead=none]; } }应用架构对比。没有框架时,开发者需要编写大量自定义胶水代码。而有了LangChain,通过组合模块化、标准化的组件,开发变得更简单。LangChain提供了从这些模块化部分构建应用所需的抽象。它充当一个协调层,让您专注于应用独特的逻辑,而非底层工作。这不仅加快了开发速度,还使您的应用更可靠、更易于调整,因为您可以轻松替换组件。通过为感知数据的智能系统提供通用结构,LangChain为从简单原型到可投入生产的应用提供了一条清晰的途径。