前言

LangChain是一个开源框架,旨在简化基于大语言模型(LLM)的应用程序开发.它解决基于大语言模型从零开发Agent的工作量(比如: 对接 API、设计交互逻辑、处理数据存储).它提供了一套通用接口,把复杂的调用过程封装起来,大大降低了开发难度。更重要的是,LangChain 不仅能让语言模型连接外部的数据源,还能让它与环境进行交互,这意味着模型可以不再只是“回答问题”,而是能真正参与到任务执行中。

OpenAI

OpenAI 是开发 ChatGPT 的公司,全球领先的人工智能研究机构,致力于让通用人工智能(AGI)造福全人类。

通过OpenAI 官网获取KEY,再根据开发者平台的 API Reference 文档进行调用

## http
curl https://api.openai.com/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -d '{
    "model": "gpt-4.1", 
    "input": "Tell me a three sentence bedtime story about a unicorn."
  }'
## python
## 使用 python的虚拟环境(环境管理)
## python3 -m venv langchain_env (创建)
## source ./langchain_env/bin/activate (使用)
## pip install -U openai (安装openai依赖)

from openai import OpenAI
client = OpenAI(
    api_key='sk-...',
    base_url='https://api.openai.com'
)
response = client.responses.create(
  model="gpt-4.1",
  input="Tell me a three sentence bedtime story about a unicorn."
)
print(response)

提示词

大模型交互以文本为基础,但仅靠用户文本的描述,模型认知有限,输出可控性无法适应复杂应用场景。因此诞生了提示词工程去协助模型认知,控制输出适应复杂场景.提示词可以包含以下任意要素:

  • 指令:想要模型执行的特定任务或指令。
  • 上下文:包含外部信息或额外的上下文信息,引导语言模型更好地响应。
  • 输入数据:用户输入的内容或问题。
  • 输出指示:指定输出的类型或格式。

提示技术(Prompting Techniques)是与大型语言模型交互的核心方法,旨在通过精心设计输入文本来引导模型产生更准确、可靠的输出。包括: 少样本提示, 思维树 (ToT), 检索增强生成RAG,

response = client.responses.create(
    model="gpt-5-nano",
    instructions="你是一位地理老师",
    input="给我讲一下山"
)
## 山是相对于周围地形显著隆起、海拔较高、坡面较陡的地形单位。它们通常形成在地壳运动、岩石变质与风化侵蚀的共同作用下。
print(response.output_text)

response = client.responses.create(
    model="gpt-5-nano",
    instructions="你是一位数学老师",
    input="给我讲一下山"
)
## 高度场的概念:把地面的三维形状看成一个高度函数 z = f(x, y),平面上的任意点 (x, y) 对应一个海拔高度 z。
print(response.output_text)


response = client.responses.create(
    model="gpt-5-nano",
    input=[
         ## 相当于instructions
        {"role":"system", "content": "你是一位数学老师"},
        ## assistant表示历史交互的记录
        {"role":"assistant", "content":"例题5中的山是一个三角型, 高为5,底为10"},
        ## 用户的输入
        {"role":"user", "content":"给我讲一下山"}
    ]
)

##在例题5里,山指的是一个三角形。给定的条件是:
##- 底边长度 base = 10
##- 高 height = 5,即从顶点到底边所作的垂线的长度为5
## 常见的两点理解和做法:
print(response.output_text)

role‌:消息角色,包括user、assistant、system、developer

developer或system角色的指令优先级高于user角色的指令。带有assistant角色的消息被视为模型在先前交互中生成的内容。

Function Call (tool)

提示词除了上述按角色指令层级的方式之外,可以从外界获取数据,换个角度讲,模型可以借助工具来生成提示词.

在这里插入图片描述

  1. 开发者告诉大模型有get_weather的工具函数… 并询问天气情况
  2. 大模型,给出参数,并让开发者work去调用get_weather函数
  3. 开发者根据大模型给的参数去调用get_weather函数,并得出结果
  4. 开发者将结果消息给大模型
  5. 大模型给出最终答案
from openai import OpenAI
import json

client = OpenAI()

# 定义本地函数说明
tools = [
    {
        "type": "function",
        "name": "get_weather",
        "description": "经定城市天气情况",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {
                    "type": "string",
                    "description": "城市和国家,例如杭州",
                },
            },
            "required": ["city"],
        },
    },
]

def get_weather(city: str) -> str:
    """Get weather for a given city."""
    return f"It's always sunny in {city}!"

input_list = [
    {"role": "user", "content": "杭州的天气怎么样"}
]

# 1. 告诉大模型有get_weather的工具函数.. 并询问天气情况
response = client.responses.create(
    model="gpt-5",
    tools=tools,
    input=input_list,
)

## 2. 大模型,给出参数,并让开发者work去调用get_weather函数
## [ResponseReasoningItem(id='rs_09cef3f85e9ecb000069451edce56c8195b410333e3ff41ca4', summary=[], type='reasoning', content=None, encrypted_content=None, status=None), ResponseFunctionToolCall(arguments='{"city":"杭州"}', call_id='call_bN5WDxULC7V3MYqKAw6QOVAD', name='get_weather', type='function_call', id='fc_09cef3f85e9ecb000069451edeca488195a56567326674fd78', status='completed')]
print(response.output)


# 4-1, Save function call outputs for subsequent requests
input_list += response.output

for item in response.output:
    if item.type == "function_call":
        if item.name == "get_weather":
            # 3. 根据大模型给的参数去调用get_weather函数,并得出结果
            weather = get_weather(json.loads(item.arguments)['city'])
                        
            # Provide function call results to the model
            input_list.append({
                "type": "function_call_output",
                "call_id": item.call_id,
                "output": json.dumps({
                  "weather": weather
                })
            })


## 4. 将询问+结果+ 函数结果,消息给大模型
print("Final input:")
print(input_list)


response = client.responses.create(
    model="gpt-5",
    instructions="你是一个天气助手",
    tools=tools,
    input=input_list
)

# 5. 大模型给出最终答案
# 根据查询,杭州今天是晴天。需要温度、风力或未来几天的预报吗?
print("Final output:")
print(response.model_dump_json(indent=2))
print("\n" + response.output_text)

MCP

不同 LLM 平台的 function call API 实现差异较大。

例如,OpenAI 的函数调用方式与 Google 的不兼容,开发者在切换模型时需要重写代码,增加了适配成本。

MCP (Model Context Protocol,模型上下文协议)定义了应用程序和 AI 模型之间交换上下文信息的方式。这使得开发者能够以一致的方式将各种数据源、工具和功能连接到 AI 模型(一个中间协议层),就像 USB-C 让不同设备能够通过相同的接口连接一样。MCP 的目标是创建一个通用标准,使 AI 应用程序的开发和集成变得更加简单和统一。

MCP 就是以更标准的方式让 LLM Chat 使用不同工具.

基于python的FastMCP框架构server端, 以天气为例子

rom __future__ import annotations

import os
from datetime import datetime, timezone
from typing import Annotated

from fastmcp import FastMCP
from pydantic import BaseModel, Field

mcp = FastMCP("weather-server")

## 定义天气包括的字段
class WeatherReport(BaseModel):
    """Structured payload returned to the MCP client."""

    city: str = Field(description="City name echoed back to the caller.")
    condition: str = Field(description="Short description of current weather.")
    temperature_c: float = Field(description="Temperature in Celsius degrees.")
    humidity: int = Field(ge=0, le=100, description="Relative humidity percentage.")
    observed_at: datetime = Field(description="ISO 8601 timestamp in UTC.")


def _normalize_city(city: str) -> str:
    return city.strip().lower()


## Mock城市的天气数据
_MOCK_DATA: dict[str, WeatherReport] = {
    "hangzhou": WeatherReport(
        city="Hangzhou",
        condition="cloudy",
        temperature_c=18.5,
        humidity=72,
        observed_at=datetime(2025, 12, 20, 6, 0, tzinfo=timezone.utc),
    ),
    "san francisco": WeatherReport(
        city="San Francisco",
        condition="foggy",
        temperature_c=14.2,
        humidity=85,
        observed_at=datetime(2025, 12, 20, 6, 0, tzinfo=timezone.utc),
    ),
    "new york": WeatherReport(
        city="New York",
        condition="clear",
        temperature_c=5.1,
        humidity=60,
        observed_at=datetime(2025, 12, 20, 6, 0, tzinfo=timezone.utc),
    ),
}

## 查找城市的天气
def _lookup_weather(city: str) -> WeatherReport:
    normalized = _normalize_city(city)
    if normalized in _MOCK_DATA:
        return _MOCK_DATA[normalized]

    return WeatherReport(
        city=city.strip() or "Unknown",
        condition="partly cloudy",
        temperature_c=22.0,
        humidity=55,
        observed_at=datetime.now(timezone.utc),
    )


@mcp.tool()
def get_weather(
    city: Annotated[str, Field(description="City name, e.g. Hangzhou or San Francisco")]
) -> WeatherReport:
    """Return a simple mock weather report for the requested city."""

    return _lookup_weather(city)

## 启动MCP服务
def main() -> None:
    transport = os.getenv("MCP_TRANSPORT", "http")
    host = os.getenv("MCP_HOST", "127.0.0.1")
    port = int(os.getenv("MCP_PORT", "8765"))
    mcp.run(transport=transport, host=host, port=port)


if __name__ == "__main__":
    main()

基于python的FastMCP框架构client端, 去测试服务的连通性

import asyncio
import os

from fastmcp import Client


async def main() -> None:
    server_url = os.getenv("MCP_SERVER_URL", "http://127.0.0.1:8765/mcp")
    city = os.getenv("TEST_CITY", "Hangzhou")

    client = Client(server_url)
    async with client:
        tools = await client.list_tools()
        ## 返回工具列表
        ## Tools: ['get_weather']
        print("Tools:", [t.name for t in tools])

        result = await client.call_tool("get_weather", {"city": city})
        payload = (
            result.structured_content
            or result.data
            or result.content
            or "(empty result)"
        )
        ## 参数为“Hangzhou”调用工具
        ## Result: {'city': 'Hangzhou', 'condition': 'cloudy', 'temperature_c': 18.5, 'humidity': 72, 'observed_at': '2025-12-20T06:00:00Z'}
        print("Result:", payload)

if __name__ == "__main__":
    asyncio.run(main())

基于openAi的tools-connectors-mcp, 让openAi接入我们自定义的MCP

from openai import OpenAI
import os

client = OpenAI()

## 这里的域名可让openai可以访问的到
MCP_SERVER_URL = os.getenv("MCP_SERVER_URL", "http://silly-ends-cough.loca.lt/mcp")
MCP_SERVER_LABEL = os.getenv("MCP_SERVER_LABEL", "weather-mcp")
MCP_SERVER_DESCRIPTION = os.getenv(
    "MCP_SERVER_DESCRIPTION", "Weather MCP server for city forecasts."
)
REQUIRE_APPROVAL = os.getenv("MCP_REQUIRE_APPROVAL", "never")

tools = [
    {
        "type": "mcp",
        "server_label": MCP_SERVER_LABEL,
        "server_description": MCP_SERVER_DESCRIPTION,
        "server_url": MCP_SERVER_URL,
        "require_approval": REQUIRE_APPROVAL,
    },
]

input_list = [
    {"role": "user", "content": "杭州的天气怎么样"}
]

response = client.responses.create(
    model="gpt-5",
    instructions="你是一个天气助手",
    tools=tools,
    input=input_list
)

## 输出内容 :
## 杭州现在多云,气温约22°C,湿度约55%。需要看未来几天的预报吗?
print("Final output:")
print(response.model_dump_json(indent=2))
print("\n" + response.output_text)

关于OpenAi 更多的工具的用法,请参数《Available tools

LangChain 框架

使用LangChain 框架的核心目标,是把不同的大语言模型(比如 ChatGPT、LLaMA 等)和各种外部资源(如 Google、Wikipedia、Notion、Wolfram 等)连接起来。它通过一套抽象组件和工具,帮我们处理好文本输入和输出之间的接口,让开发者可以更快地搭建原型系统和实际应用。

LangChain 的设计理念,可以用一个关键词来概括:链(Chain)。在这个框架里,语言模型和组件都可以像“积木”一样被串联起来,形成一条任务处理链,从而实现更复杂的功能。

它的主要价值主要体现在以下几个方面:

  1. 组件化:LangChain 提供了许多和大语言模型相关的抽象组件,并且为每种组件提供了不同的实现方式。这些组件采用模块化设计,可以单独使用,也可以与 LangChain 的其他部分配合使用。换句话说,你可以“拿来即用”,不用从零造轮子。
  2. 现成的链式组装:LangChain 内置了一些“现成的链”,能够直接完成某些常见的高级任务,非常适合初学者快速上手。而对于更复杂的应用,开发者还可以在这些现成链的基础上做定制化,甚至从头构建新的链。
  3. 简化开发难度:通过组件化和现成链的结合,LangChain 大大降低了开发门槛。开发者不必陷在底层技术细节里,而是能把精力放在真正的业务逻辑和应用场景上。

此外,LangChain 还提供了6 种标准化、可扩展的接口,并且支持与外部系统对接:

  1. 模型输入/输出(Model I/O):和大语言模型进行交互的接口。
  2. 数据连接(Data Connection):和应用程序的数据打通。
  3. 链(Chain):把不同的调用步骤串联起来,形成一个处理流程。
  4. 记忆(Memory):在多次运行之间保存应用状态,让模型具备“记忆力”。
  5. 智能体(Agent):让模型像推理器一样,决定下一步要执行什么动作。
  6. 回调(Callback):记录或实时传输执行链中的中间步骤,方便调试和监控。

模型输入/输出

LangChain 中的模型输入/输出模块是与各种大语言模型进行交互的基本组件,是大语言模型
应用的核心元素。该模块的基本流程如图 所示,主要包含以下部分:Prompts、Language Models 及 Output Parsers。将用户的原始输入与模型和示例进行组合输入大语言模型,再根据大语言模型的返回结果进行输出或者结构化处理。
在这里插入图片描述

  • Prompts 部分的主要功能是提示词模板、提示词动态选择和输入管理。提示词是指输入模型的
    内容。该输入通常由模板、示例和用户输入组成。LangChain 提供了几个类和函数,使得构建和处理提示词更加容易。

    from langchain_core.prompts import PromptTemplate
    template = """
    You are a naming consultant for new companies.
    What is a good name for a company that makes {product}?
    """
    prompt = PromptTemplate.from_template(template)
    
    ## You are a naming consultant for new companies.
    ## What is a good name for a company that makes colorful socks?
    print(prompt.format(product="colorful socks"))
    

    LangChain 中提供了 Example Selector 以提供各种类型的选择,包括 LengthBasedExampleSelector、MaxMarginalRelevanceExampleSelector、SemanticSimilarityExampleSelector、NGramOverlapExampleSelector 等,可以提供按照
    句子长度、最大边际相关性、语义相似度、n-gram 覆盖率等多种指标进行选择的方式。

  • Language Models 部分提供了与大语言模型的接口,LangChain 提供了两种类型的模型接口和集成:LLM,接收文本字符串作为输入并返回文本字符串;Chat Model,由大语言模型支持,但接收聊天消息(Chat Message)列表作为输入并返回聊天消息。在 LangChain 中,LLM 指纯文本补全模型,接收字符串提示词作为输入,并输出字符串。

    from langchain_openai import ChatOpenAI
    from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
    chat  = ChatOpenAI(
        model_name="gpt-5.1",
        temperature=0
    )
    ## 给AI设置应该遵循的目标,并将历史对话发过去
    messages = [
    SystemMessage(content="You are a helpful assistant."),
    HumanMessage(content="Hi AI, how are you today?"),
    AIMessage(content="I'm great thank you. How can I help you?"),
    HumanMessage(content="I'd like to understand string theory.")
    ]
    res = chat.invoke(messages)
    print(res.content)
    

    HumanMessage 表示用户输入的消息,AIMessage 表示系统回复用户的消息,SystemMessage表示设置的 AI 应该遵循的目标。

  • Output Parsers 部分的目标是辅助开发者从大语言模型输出中获取比纯文本更结构化的信息。

    from langchain_openai import ChatOpenAI
    from langchain_core.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
    from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
    
    from langchain_core.output_parsers import PydanticOutputParser
    from pydantic import BaseModel, Field, field_validator
    from typing import List
    
    ## OPENAI 在 langchain里的包装
    chat  = ChatOpenAI(
        model_name="gpt-5.1",
        temperature=0
    )
    
    # 定义期望的数据结构
    class Joke(BaseModel):
        setup: str = Field(description="question to set up a joke")
        punchline: str = Field(description="answer to resolve the joke")
        
        # 使用Pydantic轻松添加自定义验证逻辑
        @field_validator('setup')
        def question_ends_with_question_mark(cls, field: str):
            if not field.endswith('?'):
                raise ValueError("Badly formed question!")
            return field
    
    # 设置解析器并将指令注入提示模板
    parser = PydanticOutputParser(pydantic_object=Joke)
    
    ## 根据模板,把期望的格式及问题的问题,做成一个模板
    prompt = PromptTemplate(
        template="Answer the user query. n{format_instructions} n{query} n",
        input_variables=["query"],
        partial_variables={"format_instructions": parser.get_format_instructions()}
    )
    joke_query = "Tell me a joke."
    _input = prompt.format_prompt(query=joke_query)
    
    ## 根据模板生成一个输入,告诉大模型按什么格式输出
    ## text='Answer the user query. nThe output should be formatted as a JSON instance that conforms to the JSON schema below.\n\nAs an example, for the schema {"properties": {"foo": {"title": "Foo", "description": "a list of strings", "type": "array", "items": {"type": "string"}}}, "required": ["foo"]}\nthe object {"foo": ["bar", "baz"]} is a well-formatted instance of the schema. The object {"properties": {"foo": ["bar", "baz"]}} is not well-formatted.\n\nHere is the output schema:\n```\n{"properties": {"setup": {"description": "question to set up a joke", "title": "Setup", "type": "string"}, "punchline": {"description": "answer to resolve the joke", "title": "Punchline", "type": "string"}}, "required": ["setup", "punchline"]}\n```nTell me a joke. n'
    print(_input)
    output = chat.invoke(_input.to_messages())
    parsed = parser.parse(output.content)
    ## 按定义期望的数据结构输出
    ## setup='Why did the developer go broke?' punchline='Because he used up all his cache.'
    print(parsed)
    

    PydanticOutputParser 允许用户指定任意的 JSON 模式,并通过构建指令的方式与用户输入结合,使得大语言模型输出符合指定模式的 JSON 结果。

数据连接

许多大语言模型应用需要使用用户特定的数据,这些数据不是模型训练集的一部分。为了支
持上述应用的构建,LangChain 数据连接模块通过以下方式提供组件来加载、转换、存储和查询数据:Document loaders、Document transformers、Text embedding models、Vector stores 及 Retrievers。
在这里插入图片描述

from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_openai import OpenAIEmbeddings

## 加库文档
loader = TextLoader('./index.md')
documents = loader.load()

## 将文档分块
## TextSplitter 会顺序读取文档,在遇到 100 个字符(或遇到你设定的分隔符后超过 100)时切断
## 后一块与前一块之间重叠的字符数为2 个字符
text_splitter = CharacterTextSplitter(chunk_size=10, chunk_overlap=2)
texts = text_splitter.split_documents(documents)

## 加载到向量存储中
embeddings = OpenAIEmbeddings( 
    openai_api_key=''
    )
db = FAISS.from_documents(texts, embeddings)

## 进行相似性搜索, 取top 2
retriever = db.as_retriever(search_kwargs={"k":2})
query = "Linux"
docs = retriever.invoke(query)
for idx, doc in enumerate(docs, start=1):
    source = doc.metadata.get("source")
    preview = doc.page_content[:200].replace("\n", " ")
    print("Result #{idx} | source={source}\n{snippet}\n".format(
        idx=idx,
        source=source,
        snippet=preview,
    ))

更多的文档加载器请参考《document loaders

虽然独立使用大语言模型能够应对一些简单任务,但对于更加复杂的需求,可能需要将多个
大语言模型进行链式组合,或与其他组件进行链式调用。LangChain 为这种“链式”应用提供了
Chain 接口,并将该接口定义得非常通用。

from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_core.output_parsers import StrOutputParser

chat  = ChatOpenAI(
    model_name="gpt-5.1",
    temperature=0.9
)
human_message_prompt = HumanMessagePromptTemplate(
    prompt=PromptTemplate(
        template=" {city} is sunny",
        input_variables=["city"],
    )
)
chat_prompt_template = ChatPromptTemplate.from_messages([human_message_prompt])
# 链式组合(使用 | 运算符)
chain = chat_prompt_template | chat | StrOutputParser()
# 调用
result = chain.invoke("杭州的天气怎么样")
print(result)

创建一个链,接收用户输入,使用 PromptTemplate 对其进行格式化,然后将格式化后的提示词传递给大语言模型。除了上例中的 LLMChain,LangChain 中的链还包含 RouterChain、SimpleSequentialChain、SequentialChain、TransformChain 等。

  • RouterChain 可以根据输入数据的某些属性/特征值,选择调用哪个子链(Subchain)。
  • SimpleSequentialChain 是最简单的序列链形式,其中的每个步骤具有单一的输入/输出,上一个步骤的输出是下一个步骤的输入。
  • SequentialChain 是连续链的更一般的形式,允许多个输入/输出。
  • TransformChain 可以引入自定义转换函数,对输入进行处理后再输出
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_core.output_parsers import StrOutputParser


# 这是一个LLMChain,根据一部剧目的标题来撰写简介
llm1  = ChatOpenAI(
    model_name="gpt-5.1",
    temperature=0.7,
)
template = """你是一位写着,请你以 {title} 为题,写一个简介."""
prompt_template1 = PromptTemplate(input_variables=["title"], template=template)

# 这是一个LLMChain,根据剧目简介来撰写评论
llm  = ChatOpenAI(
    model_name="gpt-5.1",
    temperature=0.7
)
template = """你是一位评论, 请你以{synopsis} 为主题,发表评论 """
prompt_template = PromptTemplate(input_variables=["synopsis"], template=template)

# 这是总体链,按顺序运行这两个链
overall_chain = prompt_template1 | llm1 |  StrOutputParser() | prompt_template | llm |  StrOutputParser()
# 运行总体链
result = overall_chain.invoke("人工智能")
print(result)

记忆

大多数大语言模型应用都使用对话方式与用户交互。对话中的一个关键环节是能够引用和参
考之前对话中的信息。对于对话系统来说,最基础的要求是能够直接访问一些过去的消息。在更复杂的系统中还需要一个能够不断更新的事件模型,其能够维护有关实体及其关系的信息。在LangChain 中,这种能存储过去交互信息的能力被称为“记忆”。
在这里插入图片描述
记忆系统需要支持两个基本操作:读取和写入。每个链都根据输入定义了核心执行逻辑,其中一些输入直接来自用户,但有些输入可以来源于记忆。在接收到初始用户输入,但执行核心逻辑之前,链将从记忆系统中读取内容并增强用户输入。在核心逻辑执行完毕并返回答复之前,链会将这一轮的输入和输出都保存到记忆系统中,以便在将来使用它们。

from langchain_openai import ChatOpenAI
from langchain_core.prompts import MessagesPlaceholder, ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_core.messages import AIMessage, HumanMessage, SystemMessage
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个天气的助手"),
    MessagesPlaceholder(variable_name="history"),
    ("human", "{input}")
])
llm = ChatOpenAI(
    model_name="gpt-5.1",
    temperature=0.7
)
chain = (prompt| llm)

# 会话存储(支持多用户)
session_store = {}
def get_session_history(session_id: str):
    if session_id not in session_store:
        session_store[session_id] = ChatMessageHistory()
    return session_store[session_id]


## 给chain包装记忆
chain_with_history = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="history"
)


print("=== 用户1 ===")
config_user1 = {"configurable": {"session_id": "user_001"}}

r1 = chain_with_history.invoke(
    {"input": "杭州市今天天气是晴天"},
    config=config_user1
)
print(r1.content)

r2 = chain_with_history.invoke(
    {"input": "杭州今天天气怎么样"},
    config=config_user1
)
## 你刚才说杭州市今天天气是晴天,所以今天杭州是晴天,适合出门活动。  
print(r2.content)  

智能体

智能体的核心思想是使用大语言模型来选择要执行的一系列动作。在链中,操作序列是硬编
码在代码中的。在智能体中,需要将大语言模型用作推理引擎,以确定要采取哪些动作,以及以何种顺序采取这些动作。智能体通过将大语言模型与动作列表结合,自动选择最佳的动作序列,从而实现自动化决策和行动。

from langchain_openai import ChatOpenAI
from langchain_community.tools import Tool
from langchain.agents import create_agent
# 1. 初始化工具
tools = [
    Tool(
        name="calculator",
        func=lambda x: str(eval(x)),
        description="用于数学计算"
    ),
    Tool(
        name="search",
        func=lambda x: f"搜索结果:{x}",
        description="用于搜索信息"
    )
]

# 2. 初始化 LLM
chat = ChatOpenAI(
    model_name="gpt-5.1",
    temperature=0
)

# 3. 创建 Agent, 会自动根据 LLM 类型选择思考和行动的框架
agent = create_agent(
    model=chat,
    tools=tools
)


# 4. 执行
# 最后一个 AIMessage,  content='25 * 4 = 100  \n\n搜索结果:100
result = agent.invoke(
    {"messages": [{"role": "user", "content": "计算 25 * 4 然后搜索结果"}]}
)
print(result)

RAG 实践

使用 LangChain 可以快速构建一个基础的 RAG 系统

import bs4
from langchain_openai import ChatOpenAI
from langchain.agents import AgentState, create_agent
from langchain_community.document_loaders import WebBaseLoader
from langchain.messages import MessageLikeRepresentation
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_openai import OpenAIEmbeddings
from langchain.tools import tool

# Load and chunk contents of the blog
loader = WebBaseLoader(
    web_paths=("https://lilianweng.github.io/posts/2023-06-23-agent/",),
    bs_kwargs=dict(
        parse_only=bs4.SoupStrainer(
            class_=("post-content", "post-title", "post-header")
        )
    ),
)
docs = loader.load()
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
all_splits = text_splitter.split_documents(docs)

# Index chunks
embeddings = OpenAIEmbeddings(
    model="text-embedding-3-large"
)
vector_store = InMemoryVectorStore(embeddings)
_ = vector_store.add_documents(documents=all_splits)

# Construct a tool for retrieving context
@tool(response_format="content_and_artifact")
def retrieve_context(query: str):
    """Retrieve information to help answer a query."""
    retrieved_docs = vector_store.similarity_search(query, k=2)
    serialized = "\n\n".join(
        (f"Source: {doc.metadata}\nContent: {doc.page_content}")
        for doc in retrieved_docs
    )
    return serialized, retrieved_docs


model = ChatOpenAI(
    model_name="gpt-5.1",
    temperature=0
)
tools = [retrieve_context]
# If desired, specify custom instructions
prompt = (
    "You have access to a tool that retrieves context from a blog post. "
    "Use the tool to help answer user queries."
)
agent = create_agent(model, tools, system_prompt=prompt)


query = "What is task decomposition?"
for step in agent.stream(
    {"messages": [{"role": "user", "content": query}]},
    stream_mode="values",
):
   step["messages"][-1].pretty_print()

在Agent 式 RAG 架构中,我们允许 LLM 自主决定是否生成工具调用来帮助回答用户查询。这是一个很好的通用解决方案, 相比于 chain RAG的架构也存在一些权衡取舍:

  • Agent:慢但聪明, 会自动多次检索,可能做出意外决策,但能自动适应不同问题
  • Chain: 快但固定, 只检索一次,流程完全可预测,但无法应对意外情况

更新速度

langchain的更新速度能跟的上各API产商吗?

总体上能跟上,但存在时间差和覆盖度问题。

  • 能跟上的:主流大厂商(OpenAI、Anthropic、Google)
  • 有延迟的:中小厂商、新功能
  • 难覆盖的:小众API、国内厂商细节

实际应对策略怎么样 ?

分层使用

  1. 使用成熟功能 → 完全依赖LangChain
  2. 使用新功能 → 混合使用(LangChain + 官方SDK混合)
  3. 小众API → 自己封装

站在巨人的肩膀上

大规模语言模型:从理论到实践
大规模语言模型:从理论到实践代码部分
大模型智能体LangChain 框架介绍
提示工程指南
OpenAI Platform
langchain-doc教程
LangChain-Python

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐