Langchain 浅出

Langchain 浅出

原本的计划是发一篇《langchain深入浅出》,但是太长了就切割成了两部份,先发了这篇浅出 中间还经历了大版本的更新╮(╯▽╰)╭但是有惊无险还是写完了。

作者:吴佳浩

最后更新:2025-11-27

适用版本:LangChain v1.0+

目录

  1. 什么是 LangChain
  2. 环境准备
  3. 核心概念
  4. 实战案例

什么是Langchain

这里我就不多话太多时间和大家扯淡了 一句话概括什么是langchain

LangChain 是把"模型、提示、工具、记忆"等模块按统一 Runnable 接口串成 pipeline,让开发者像搭积木一样快速搭建 LLM 应用的生产级框架。

核心优势

  • 模块化设计,易于组合和扩展
  • 支持多种 LLM 提供商(OpenAI、Anthropic、ollama本地模型等)
  • 丰富的预构建组件

核心概念深度解析

1. LangChain 的工作原理

%% LangChain v1 关键流程(Runnable 版) graph LR A[用户输入] --> B[ChatPromptTemplate] B --> C[RunnableWithMessageHistory] C --> D[Chat Model] D --> E[Output Parser] E --> F[结果]

关键流程(LangChain v1)

  1. 输入处理

    用户输入 → ChatPromptTemplate.invoke() → 生成消息列表。

  2. 历史注入(可选)
    RunnableWithMessageHistory 自动把之前对话拼进消息,再传给模型。

  3. 模型调用
    ChatModel.invoke(messages) → 返回 AIMessage

  4. 输出解析
    OutputParser.invoke(ai_message) → 结构化数据 / 字符串。

  5. 结果返回

    解析后的内容即为最终答案,同时历史被持久化,供下轮使用。

记忆管理:对话历史存储在 Memory 中供后续使用

环境准备

步骤 1:安装 Python

macOS
bash 复制代码
# 检查是否已安装 Python(推荐 3.8+)
python3 --version

# 如果未安装,使用 Homebrew 安装
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install python@3.12.11
Windows
powershell 复制代码
# 下载 Python 安装包
# 访问:https://www.python.org/downloads/
# 下载 Python 3.12.11+ 安装包
# 安装时勾选 "Add Python to PATH"

# 验证安装
python --version

步骤 2:创建项目目录

macOS
bash 复制代码
# 创建项目文件夹
mkdir langchain-demo
cd langchain-demo

# 创建虚拟环境
python3 -m venv venv

# 激活虚拟环境
source venv/bin/activate
Windows
powershell 复制代码
# 创建项目文件夹
mkdir langchain-demo
cd langchain-demo

# 创建虚拟环境
python -m venv venv

# 激活虚拟环境
.\venv\Scripts\activate

步骤 3:安装 LangChain

bash 复制代码
# 1. 核心骨架(必装)
pip install -U langchain==1.0.0 langchain-core

# 2. 模型/嵌入支持(按需选)
pip install langchain-openai          # OpenAI / Azure
pip install langchain-ollama          # Ollama 本地模型
pip install langchain-huggingface     # HuggingFace 模型/嵌入

# 3. 向量库(RAG 必装其一)
pip install chromadb                  # 本地文件型
# pip install faiss-cpu               # 另一轻量选择

# 4. 辅助工具
pip install python-dotenv             # 读 .env
pip install tiktoken                  # OpenAI token 计数 我主要是用本地的ollama暂时不用 有需要的酌情安装
pip install pydantic                  # 结构化输出/数据验证
pip install langgraph                 # 需要复杂 Agent 流程时再装

步骤 4:配置 API 密钥

创建 .env 文件来存储 API 密钥:

bash 复制代码
# 创建 .env 文件
touch .env  # macOS
# 或
type nul > .env  # Windows

.env 文件中添加:

plaintext 复制代码
OPENAI_API_KEY=你的_OpenAI_API_密钥
# 或使用其他 LLM 提供商
# ANTHROPIC_API_KEY=你的_Anthropic_API_密钥

注意这里你如果使用的是本地的ollama 那么则无需配置秘钥


人狠话不多 叫声浩哥

**上呆么(demo)**😄😄


完整项目结构

因为我这里有两套环境 Mac 7b & Windows就用30b所以会出现上下的demo 使用的模型出现些许的出入,这点在这里也做一个说明,防止看着些的朋友出现一些困惑。

还有别问我venv哪里来的 如果这你都不会那么建议你去看我的Python入门指南系列

bash 复制代码
langchain-demo/
├── venv/                      # 虚拟环境
├── .env                       # 环境变量配置
├── requirements.txt           # 依赖包列表
├── demo1_basic.py            # 案例1:基础调用
├── demo2_prompt_template.py  # 案例2:提示词模板
├── demo3_chains.py           # 案例3:链式调用
├── demo4_memory.py           # 案例4:对话记忆
├── demo5_document_qa.py      # 案例5:文档问答
├── demo6_agent.py            # 案例6:Agent代理
└── run_all_demos.py          # 运行所有示例

创建 requirements.txt 文件:

txt 复制代码
# LangChain v1 最小可用组合
langchain>=1.0.0           # 主包正式版
langchain-core>=1.0.0      # 核心协议(可省略,主包会拉最新)
langchain-openai>=1.0.0    # OpenAI 系列
langchain-ollama>=1.0.0    # 本地 Ollama
tiktoken>=0.7.0            # OpenAI token 计数
python-dotenv>=1.0.0       # 环境变量
chromadb>=0.5.0            # 向量数据库

安装所有依赖:

bash 复制代码
pip install -r requirements.txt

实战案例

案例 1:基础 LLM 调用

创建文件 demo1_basic.py

python 复制代码
"""
案例 1:基础的 LLM 调用
展示如何使用 LangChain 调用语言模型
"""
# 如果使用的OpenApideng相关的内容则使用以下的插件
# from langchain_openai import ChatOllama

 
# 如果使用的是ollama的话那么直接使用本插件 
from langchain_ollama import ChatOllama # 新
from dotenv import load_dotenv

# 加载环境变量 如果使用的本地的ollama 这里可以直接省略
load_dotenv() 

def basic_llm_call():
    """最简单的 LLM 调用示例"""
    
    # 初始化模型
    # temperature: 控制输出的随机性(0-1),0 表示确定性输出
    llm = ChatOllama(
        model="Qwen2.5:7b",
        temperature=0.7
    )
    
    # 直接调用模型
    response = llm.invoke("请用一句话介绍什么是人工智能")
    
    print("=" * 50)
    print("基础 LLM 调用结果:")
    print(response.content)
    print("=" * 50)

if __name__ == "__main__":
    basic_llm_call()

运行方式

bash 复制代码
python demo1_basic.py

输出结果:

bash 复制代码
Langchain深入浅出 % python demo_basic.py
==================================================
本地 Ollama (Qwen2.5:7b) 调用结果:
人工智能是指由机器或软件所表现出的智能行为。
==================================================

案例 2:使用提示词模板

创建文件 demo2_prompt_template.py

python 复制代码
from langchain_core.prompts import PromptTemplate,ChatPromptTemplate # 导入提示词模板类
from langchain_ollama import ChatOllama  # 导入Ollama聊天模型类

# 1.simple prompt template example
#   简单的提示词模版示例
#   功能:展示如何使用提示词模板生成营销文案
#   流程:
#   1. 创建提示词模板
#   2. 初始化语言模型
#   3. 填充模板参数
#   4. 调用模型生成响应

def simple_prompt_template():
    """\n\t简单的提示词模版示例\n\t功能:展示如何使用提示词模板生成营销文案\n\t流程:\n\t\t1. 创建提示词模板\n\t\t2. 初始化语言模型\n\t\t3. 填充模板参数\n\t\t4. 调用模型生成响应\n\t"""
    """简单的提示词模版示例"""
    # 创建提示词模版
    # {product}是占位符,可以动态替换
    myTemplate = """
    你是一名产品营销文案专家,请帮我为以下产品撰写一段吸引人的营销文案:
    产品名称:{product}
    产品描述:{description}
    产品特点:{features}
    请用轻松活泼的语气,字数控制在 100 字以内。
    """
    # 创建提示词模版对象
    prompt = PromptTemplate(
        input_variables=["product", "description", "features"],  # 定义模板中可替换的变量
        template=myTemplate  # 使用上面定义的模板字符串
    )
    # 初始化模型
    llm = ChatOllama(
        model="qwen2.5:7b",  # 指定使用的模型名称
        temperature=0.7,  # 设置温度参数,控制输出的随机性
    )
    
    # 填充提示词模版
    formatted_prompt = prompt.format(
        product="智能手环",  # 替换模板中的product变量
        description="年轻的运动爱好者",  # 替换模板中的description变量
        features="心率监测、睡眠追踪、防水设计"  # 替换模板中的features变量
    )
    print("=" * 50)  # 打印分隔线
    print("生成的提示词:")  # 打印提示信息
    print(formatted_prompt)  # 打印格式化后的提示词
    print("=" * 50)

    # 调用模型使用模型处理格式化后的提示词
    respone = llm.invoke(formatted_prompt)  


    print("\n模型响应:")  # 打印提示信息
    print(respone.content)  # 打印模型的响应内容
    print("=" * 50)  # 打印分隔线

# 2.对话式提示词模版
#   对话式提示词模版示例
#   功能:展示如何使用提示词模板进行对话式交互
#   流程:
#   1. 创建提示词模板
#   2. 初始化语言模型
#   3. 填充模板参数格式化
#   4. 调用模型生成响应
def chat_prompt_template():
    #创建对话模版
    #可以指定系统消息、人类消息等不同的角色
    chat_template = ChatPromptTemplate.from_messages([
        ("system", "你是一名资深的{role},拥有10年以上的从业经验"),
        ("human", "请帮我分析:{question}")
    ])

    # 初始化模型
    llm = ChatOllama(
        model="qwen2.5:7b",  # 指定使用的模型名称
        temperature=0.7,  # 设置温度参数,控制输出的随机性
    )

    # 填充提示词模版
    messages = chat_template.format_messages(
        role="Python工程师",  # 替换模板中的role变量
        question="如何优化Python代码的性能?"  # 替换模板中的topic变量
    )

    # 调用模型使用模型处理格式化后的提示词
    response = llm.invoke(messages)

    print("\n对话模板响应:")
    print(response.content)
    print("=" * 50)

# 判断是否为主程序运行,如果是,则调用simple_prompt_template函数,否则不执行
if __name__ == "__main__":
        simple_prompt_template()
        chat_prompt_template()

输出结果:

bash 复制代码
==================================================
生成的提示词:

    你是一名产品营销文案专家,请帮我为以下产品撰写一段吸引人的营销文案:
    产品名称:智能手环
    产品描述:年轻的运动爱好者
    产品特点:心率监测、睡眠追踪、防水设计
    请用轻松活泼的语气,字数控制在 100 字以内。
    
==================================================

模型响应:
想成为朋友圈里的运动小明星吗?来试试我们的智能手环吧!它专为年轻的运动爱好者打造,不仅有时尚外观,还有心率监测和睡眠追踪功能哦。防水设计让你无忧运动,记录每一次挥汗如雨的时刻。戴上它,开启你的活力人生!
==================================================

对话模板响应:
优化Python代码的性能是一个多方面的工作,通常需要考虑算法复杂度、数据结构选择以及特定库和工具的应用。下面是一些常见的优化策略:

### 1. 分析瓶颈

- **使用`cProfile`或`line_profiler`**:首先定位程序中的热点(即执行时间最长的部分)。这有助于确定优化的重点。
- **了解Python的性能特性**:例如,避免不必要的对象创建、减少函数调用次数等。

### 2. 选择合适的数据结构和算法

- 根据问题的具体情况选择最适合的数据结构。比如使用`collections.deque`代替列表进行频繁的添加和删除操作,或使用`heapq`来实现优先队列。
- 仔细考虑是否真的需要使用字典或集合,有时候列表可能足够且更快。

### 3. 使用内置函数

- Python库中的很多函数都是用C语言编写的,执行速度远快于Python代码。例如,使用`map()`、`filter()`等高阶函数代替循环。
- 利用`itertools`模块提供的高效迭代器工具,如`chain()`, `accumulate()`等。

### 4. 避免全局变量

- 全局变量在每次调用时都需要查找,这会降低程序的执行速度。尽量减少对全局变量的依赖。
  
### 5. 使用多线程或异步编程

- 如果你的任务是I/O密集型(如网络请求、文件读写等),可以考虑使用`asyncio`实现异步IO操作来提高效率。
- 对于CPU密集型的任务,可以利用`multiprocessing`模块创建进程来并行执行。

### 6. 编译Python代码

- 使用PyPy解释器可能会带来显著的速度提升。虽然标准的CPython通常已足够快,但在某些情况下使用PyPy可以实现更快的运行时。
- 利用Numba这样的工具将部分或全部Python函数编译成机器码。

### 7. 减少内存消耗

- 使用`numpy`、`pandas`等库处理大规模数据集往往比纯Python实现更高效,因为它们底层使用了C语言编写,并且进行了优化。
  
### 8. 内存管理与垃圾回收

- 确保正确地使用资源和管理对象生命周期。避免不必要的内存泄漏。

通过上述方法的综合应用,通常可以显著提高Python代码的执行速度和效率。不过需要注意的是,性能优化应当在确保程序功能的前提下进行,并且要衡量所付出的努力是否值得得到的性能提升。
==================================================

小结

维度 PromptTemplate ChatPromptTemplate
结构 单一段落字符串(无角色) 带角色的消息列表(系统 / 人类 / AI)
交互方式 传递纯文本 传递消息列表
适用场景 单轮任务、简单指令 多轮对话、需要角色设定的任务
模型理解方式 作为整体指令处理 按角色优先级和上下文处理

简单来说,PromptTemplate 是 "给模型一段话",ChatPromptTemplate 是 "给模型一段带角色的对话历史",后者更适合模拟真实交互场景。


案例 3:链式调用(Chain)

创建文件 demo3_chains.py

python 复制代码
"""
案例 3:链式调用(LangChain v1版本 新写法)
展示如何用 RunnableSequence 替代 LLMChain / SequentialChain
"""
#本地使用ollama 这里暂时注释
#from dotenv import load_dotenv
#load_dotenv()

from langchain_ollama import ChatOllama
from langchain_core.prompts import PromptTemplate
# from langchain.chains import LLMChain, SequentialChain #被版本删除使用下面的替代
from langchain_core.runnables import RunnableSequence, RunnablePassthrough # 新引入的类,用于替代 LLMChain / SequentialChain,实现链式调用



def simple_chain():
    """简单链式调用示例"""


    # 初始化模型
    llm = ChatOllama(
        model="qwen2.5:7b",
        temperature=0.7,
    )

    # 创建提示词模板
    prompt = PromptTemplate(
        input_variables=["topic"],
        template="请为以下主题写一个标题{topic}"
    )

    # 突出语法变化:用最精简的逻辑(输入→格式化→生成)展示新版 API 的核心语法,减少其他干扰。
    # 创建链式调用
    chain = prompt | llm




    # 运行链式调用
    result = chain.invoke({"topic": "人工智能"})

    print("=" * 50)
    print("链式调用结果:")
#    content='"探索未来:人工智能的技术进步与应用前景"' additional_kwargs={} response_metadata={'model': 'qwen2.5:7b', 'created_at': '2025-11-20T08:12:53.783476Z', 'done': True, 'done_reason': 'stop', 'total_duration': 5279829084, 'load_duration': 836230125, 'prompt_eval_count': 37, 'prompt_eval_duration': 4001584375, 'eval_count': 12, 'eval_duration': 439842917, 'logprobs': None, 'model_name': 'qwen2.5:7b', 'model_provider': 'ollama'} id='lc_run--3fa4a36d-9887-4a5d-af20-1daa48daf5ff-0' usage_metadata={'input_tokens': 37, 'output_tokens': 12, 'total_tokens': 49}
    print(result.content)
    print("=" * 50)




def sequential_chain():
    """顺序链示例(新版 Runnable API,实现与 SequentialChain 等价)"""
    # 初始化模型
    llm = ChatOllama(
        model="qwen2.5:7b",
        temperature=0.7,
    )

    # Step 1: 生成标题
    title_prompt = PromptTemplate(
        input_variables=["topic"],
        template="请为以下主题写一个标题:{topic}"
    )
    title_chain = title_prompt | llm

    # Step 2: 生成大纲
    outline_prompt = PromptTemplate(
        input_variables=["title"],
        template="请根据以下标题写一段简介:{title}"
    )
    outline_chain = outline_prompt | llm

    # Step 3: 生成开头
    intro_prompt = PromptTemplate(
        input_variables=["title", "outline"],
        template="""
        文章标题:{title}
        文章大纲:{outline}
        请根据以上信息,写一段引人入胜的开头(100字左右)  
        """ 
    )
    intro_chain = intro_prompt | llm

    # 创建顺序链式调用
    # 创建顺序链式调用
    # 注意:RunnableSequence 不接受 steps 参数,应使用 | 运算符连接
    # RunnablePassthrough	无修改透传输入	输出 = 输入(数据完全不变)
    # RunnablePassthrough.assign()	透传输入 + 新增 / 更新字段	输出 = 原有输入 + 新字段(增量扩展)
    overall_chain = (
        RunnablePassthrough() #这一步纯多余就是单纯的用一下 当做了解吧  Ai是永远猜不透人类的脑回路的 只有人类才能写出这样的代码既没用也无害哈哈哈哈
        |RunnablePassthrough.assign(title=title_chain)
        | RunnablePassthrough.assign(outline=(lambda x :{"title":x["title"].content}) | outline_chain) # 透传输入 + 新增 / 更新字段, 
        | RunnablePassthrough.assign(introduction=(lambda x :{"title":x["title"].content,"outline":x["outline"].content}) | intro_chain)# 透传输入 + 新增 / 更新字段
    )

    # 运行顺序链式调用
    result = overall_chain.invoke({"topic": "量子计算的实际用例"})

    print("\n" + "=" * 50)
    print("顺序链执行结果:")
    print("\n标题:\n", result["title"].content)
    print("\n大纲:\n", result["outline"].content)
    print("\n开头段落:\n", result["introduction"].content)
    print("=" * 50)




if __name__ == "__main__":
        simple_chain()
        sequential_chain()

补充

LangChain 中构建顺序链主要有三种方式,核心逻辑等价但写法不同:

  1. |运算符 :最简洁,直接串联组件(如r1 | r2 | r3),LangChain 推荐用法;
  2. RunnableSequence(组件1, 组件2) :显式通过位置参数构建,与|运算符功能一致;
  3. RunnableSequence.from_list([组件]):通过列表定义步骤,适合步骤较多时集中管理。

三者本质都是实现组件的顺序执行,仅语法形式不同,可根据代码可读性和场景需求选择。

版本 2:直接传入位置参数

python 复制代码
from langchain_core.runnables import RunnableSequence, RunnablePassthrough

# 定义各步骤组件
step1 = RunnablePassthrough.assign(title=title_chain)  # 新增title字段
step2 = RunnablePassthrough.assign(
    outline=(lambda x: {"title": x["title"].content}) | outline_chain
)  # 新增outline字段
step3 = RunnablePassthrough.assign(
    introduction=(lambda x: {"title": x["title"].content, "outline": x["outline"].content}) | intro_chain
)  # 新增introduction字段

# 用RunnableSequence串联步骤(直接传位置参数)
overall_chain = RunnableSequence(step1, step2, step3)

版本 3:用from_list()方法(更直观)

python 复制代码
from langchain_core.runnables import RunnableSequence, RunnablePassthrough

# 定义步骤列表
steps = [
    RunnablePassthrough.assign(title=title_chain),
    RunnablePassthrough.assign(
        outline=(lambda x: {"title": x["title"].content}) | outline_chain
    ),
    RunnablePassthrough.assign(
        introduction=(lambda x: {"title": x["title"].content, "outline": x["outline"].content}) | intro_chain
    )
]

# 用from_list()创建RunnableSequence
overall_chain = RunnableSequence.from_list(steps)

输出结果:

bash 复制代码
==================================================
链式调用结果:
"探索未来:人工智能的技术进步与应用前景"
==================================================

==================================================
顺序链执行结果:

标题:
 量子计算的现实应用案例探究

大纲:
 量子计算作为一种前沿技术,利用量子力学原理进行信息处理和计算,具有超越传统计算机的强大潜力。本研究旨在探讨量子计算在现实世界中的具体应用案例,分析其如何解决实际问题并带来创新解决方案。

通过深入剖析不同行业领域的应用场景,如药物发现、金融建模、优化算法等,我们可以更清晰地看到量子计算技术的潜力和挑战。例如,在医药研发中,利用量子计算机模拟分子结构和反应过程,可以加速新药开发流程;在金融服务领域,量子计算能够处理复杂的风险分析与投资组合优化问题。

此外,本研究还将介绍当前实现这些应用的技术进展、面临的障碍及未来发展方向。通过对案例的详细解析,不仅有助于深化对量子计算技术的理解,也为相关领域的研究人员和从业者提供有价值的参考信息。

开头段落:
 在当今科技日新月异的时代,量子计算作为一种颠覆性的前沿技术,正逐渐揭开其神秘面纱。不同于传统计算机基于二进制原理的工作方式,量子计算机利用量子力学中的叠加态和纠缠态特性,实现了前所未有的信息处理速度与能力。从加速药物研发到优化金融投资组合,量子计算正在为解决复杂现实问题提供创新解决方案。本文将深入探讨这些应用案例,揭示其背后的技术奥秘与挑战,引领我们进入一个充满无限可能的新时代。

流程理解 刚开始看稍微稍微有点抽象 不过理一就清晰多了

graph TD A["输入:{'topic': '量子计算的实际用例'}"] --> B["RunnablePassthrough.assign(title=title_chain)"] %% Step1:生成title B --> C["title_chain执行:title_prompt + llm"] C --> D["输出title结果(带.content属性)"] D --> B1["上下文更新:{'topic': ..., 'title': 结果对象}"] %% Step2:生成outline B1 --> E["RunnablePassthrough.assign(outline=lambda+outline_chain)"] E --> F["lambda提取:{'title': x['title'].content}"] F --> G["outline_chain执行:outline_prompt + llm"] G --> H["输出outline结果(带.content属性)"] H --> E1["上下文更新:{'topic': ..., 'title': ..., 'outline': 结果对象}"] %% Step3:生成introduction E1 --> I["RunnablePassthrough.assign(introduction=lambda+intro_chain)"] I --> J["lambda提取:{'title': x['title'].content, 'outline': x['outline'].content}"] J --> K["intro_chain执行:intro_prompt + llm"] K --> L["输出introduction结果(带.content属性)"] L --> M["最终上下文:{'topic': ..., 'title': ..., 'outline': ..., 'introduction': ...}"] %% 结果输出 M --> N["打印结果:title.content / outline.content / introduction.content"]

案例 4:对话记忆(Memory)

在写这个demo的时候版本更新了langchain 正式的迈入了1.x的时代,随之后来的变化也是巨大的就好像我们下面的这个示例

旧版 Agent 依赖固定的硬编码循环(AgentExecutor),难以处理复杂的分支和多步任务。

LangChain v1 的目标是构建生产级、可定制的自主智能体,这要求流程具备状态管理和非线性决策能力

因此,LangGraph 作为底层的状态机运行时 ,取代了旧的执行器,赋予 Agent 流程自定义的柔性

伪代码公式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> v 1 _ A g e n t ≡ G r a p h ( State → Tool Output Node Logic Next Step ) v1_Agent ≡ 图 ( 当前状态 → 工具输出 决策函数 下一节点 ) v1\_Agent \equiv Graph(\text{State} \xrightarrow[\text{Tool Output}]{\text{Node Logic}} \text{Next Step}) \text{v1\_Agent} \equiv \text{图}(\text{当前状态} \xrightarrow[\text{工具输出}]{\text{决策函数}} \text{下一节点}) </math>v1_Agent≡Graph(StateNode Logic Tool OutputNext Step)v1_Agent≡图(当前状态决策函数 工具输出下一节点)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> v1_Agent ≡ 图 ( 当前状态 → 工具输出 决策函数 下一节点 ) \text{v1\_Agent} \equiv \text{图}(\text{当前状态} \xrightarrow[\text{工具输出}]{\text{决策函数}} \text{下一节点}) </math>v1_Agent≡图(当前状态决策函数 工具输出下一节点)


创建文件 demo4_memory.py: 下面的demo将会分为两个函数一个是以前的方法旨在用来比较以前和现在的区别。

python 复制代码
"""
案例 4:对话记忆
展示如何让 AI 记住之前的对话内容

 这里不再说明为何没有引入 openai 库,请参考 README.md 中的说明 以及dotenv 文件配置说明
"""
from langchain_ollama import ChatOllama
from langchain_classic.chains import ConversationChain
from langchain_classic.memory import ConversationBufferMemory # 对话记忆

from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
from langchain.agents import create_agent# from dotenv import load_dotenv
# load_dotenv()

def  conversation_with_memory():
    """带有对话记忆的聊天示例"""

    # 初始化模型
    llm = ChatOllama(
        model="qwen3-coder:30b",
        temperature=0.7,
    )

    # 创建记忆组件
    # CoversationBufferMemory 会保存对话的历史记录,并在每次调用模型时将其作为上下文传递
    memory = ConversationBufferMemory()

    # 创建对话链
    conversation = ConversationChain(
        llm=llm,
        memory=memory,
        verbose = True # 是否打印详细日志
     )
    print("=" * 50)
    print("开始多轮对话(带记忆):")
    print("=" * 50)
    # 第一次对话
    response1 =conversation.invoke(input="你好,我是Alben,是一名资深程序员")
    print(f"\n用户:你好,我是Alben,是一名资深程序员")
    print(f"AI:{response1}\n")
    


    # 第二次对话
    response2 = conversation.invoke(input="我最近在研究AI,想了解一下AI的发展趋势")
    print(f"\n用户:我最近在研究AI,想了解一下AI的发展趋势")
    print(f"AI:{response2}\n")

    #第三次对话:检查记忆是否生效
    response3 = conversation.invoke(input="你还记得我的名字吗?我最近在研究什么")

    print(f"用户:你还记得我的名字吗?我最近在研究什么")
    print(f"AI:{response3}\n")


    print("=" * 50)
    print(memory.buffer) # 打印对话历史
    print("=" * 50)


# 写法太旧了 不能用了
def conversation_with_summary_memory():
    """使用摘要记忆的对话"""
    
    # 初始化模型
    llm = ChatOllama(
        model="qwen3-coder:30b",
        temperature=0.7,
    )
    

    #自动总结对话历史ConversationSummaryMemory
    # memory.buffer 可以获取对话历史,但会自动进行总结,
    #适合长对话,可以节省token

    memory = ConversationSummaryMemory()



    # 创建对话链
    conversation = ConversationChain(
        llm=llm,
        verbose = True # 是否打印详细日志
     )
    print("=" * 50)
    print("开始多轮对话(不带记忆):")
    print("=" * 50)
    # 模拟多轮对话
    conversation.predict(input="我今天去了公园,看到了很多花。")
    conversation.predict(input="公园里还有一个湖,湖面上有很多鸭子。")
    conversation.predict(input="我在公园待了两个小时,感觉很放松。") 
        # 查看摘要
    print("\n对话摘要:")
    print(memory.buffer)
    print("=" * 50)

def conversation_v1_modern():
    """LangChain v1 标准写法 (使用 LangGraph)"""
    
    # 1. 初始化模型
    llm = ChatOllama(model="qwen3-coder:30b", temperature=0.7)

    # 2. 初始化记忆保存器 (Checkpointer)
    # v1 不再区分 "Buffer" 还是 "Summary",它直接把状态存到这里
    memory = MemorySaver()

    # 3. 创建 Agent (或者简单的图)
    # create_agent 自带了消息管理循环
    agent = create_agent(model=llm, tools=[], checkpointer=memory)

    # 4. 设定线程 ID (类似于用户 ID,用于区分不同对话的记忆)
    config = {"configurable": {"thread_id": "user_001"}}

    print("=" * 50)
    print("开始 LangGraph 对话 (自动持久化):")
    print("=" * 50)

    # 5. 第一轮
    input_msg = "我今天去了公园,看到了很多花。"
    print(f"User: {input_msg}")
    # invoke 会自动读取 thread_id 对应的历史,拼接到 prompt 中
    for event in agent.stream({"messages": [HumanMessage(content=input_msg)]}, config=config):
        if "agent" in event:
            print(f"AI: {event['agent']['messages'][-1].content}")

    # 6. 第二轮 (它会自动记得上一轮)
    input_msg = "我刚才说我在哪里?"
    print(f"\nUser: {input_msg}")
    for event in agent.stream({"messages": [HumanMessage(content=input_msg)]}, config=config):
        if "agent" in event:
            print(f"AI: {event['agent']['messages'][-1].content}")
            
    # 7. 查看当前保存的状态 (相当于旧版的 memory.buffer)
    snapshot = agent.get_state(config)
    print("\n[当前记忆状态]:")
    # 这里保存了完整的对话历史列表
    print(len(snapshot.values['messages']), "条消息记录")

if __name__ == "__main__":
        conversation_with_memory()
        # conversation_with_summary_memory()
        conversation_v1_modern()

输出结果:

bash 复制代码
==================================================
开始多轮对话(带记忆):
==================================================


> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not 
know the answer to a question, it truthfully says it does not know.

Current conversation:

Human: 你好,我是Alben,是一名资深程序员
AI:

> Finished chain.

用户:你好,我是Alben,是一名资深程序员
AI:{'input': '你好,我是Alben,是一名资深程序员', 'history': '', 'response': '你好Alben!很高兴认识你这位资深程序员!作为一名资深程序员,你一定有很多丰富的编程经
验和技巧吧。我很好奇你主要专注于哪些编程语言和技术领域呢?是偏向后端开发、前端开发,还是其他特定的技术方向?我作为AI助手,虽然在很多编程相关的话题上都有所了解,但
很期待听听你作为资深程序员的实际经验和见解。'}



> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not 
know the answer to a question, it truthfully says it does not know.

Current conversation:
Human: 你好,我是Alben,是一名资深程序员
AI: 你好Alben!很高兴认识你这位资深程序员!作为一名资深程序员,你一定有很多丰富的编程经验和技巧吧。我很好奇你主要专注于哪些编程语言和技术领域呢?是偏向后端开发、前
端开发,还是其他特定的技术方向?我作为AI助手,虽然在很多编程相关的话题上都有所了解,但很期待听听你作为资深程序员的实际经验和见解。
Human: 我最近在研究AI,想了解一下AI的发展趋势
AI:

> Finished chain.

用户:我最近在研究AI,想了解一下AI的发展趋势
AI:{'input': '我最近在研究AI,想了解一下AI的发展趋势', 'history': 'Human: 你好,我是Alben,是一名资深程序员\nAI: 你好Alben!很高兴认识你这位资深程序员!作为一名资
深程序员,你一定有很多丰富的编程经验和技巧吧。我很好奇你主要专注于哪些编程语言和技术领域呢?是偏向后端开发、前端开发,还是其他特定的技术方向?我作为AI助手,虽然在 
很多编程相关的话题上都有所了解,但很期待听听你作为资深程序员的实际经验和见解。', 'response': '很高兴你对AI发展趋势感兴趣,Alben!作为资深程序员,你对AI的关注非常及
时,因为AI正在深刻改变整个编程和开发领域。\n\n从我了解到的信息来看,AI发展趋势主要集中在几个方面:\n\n**技术层面**:\n- 大语言模型持续进化,推理能力和多模态处理能 
力不断提升\n- AutoML和AIGC(AI生成内容)技术快速发展\n- 边缘AI计算和模型压缩技术日趋成熟\n\n**应用层面**:\n- AI在代码生成、自动化测试、智能调试等方面应用越来越广 
泛\n- 企业级AI应用从试点走向规模化部署\n- AI与各行业深度融合,比如医疗、金融、制造等\n\n**对开发者的影响**:\n- 编程工具和IDE正在集成更多AI辅助功能\n- 低代码/无代 
码平台借助AI技术快速普及\n- 开发者需要掌握AI相关的技能,如模型微调、Prompt工程等\n\n作为程序员,你认为AI技术的哪个方面最值得重点关注?或者你已经在哪些具体场景中尝 
试过AI应用了?'}



> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not 
know the answer to a question, it truthfully says it does not know.

Current conversation:
Human: 你好,我是Alben,是一名资深程序员
AI: 你好Alben!很高兴认识你这位资深程序员!作为一名资深程序员,你一定有很多丰富的编程经验和技巧吧。我很好奇你主要专注于哪些编程语言和技术领域呢?是偏向后端开发、前
端开发,还是其他特定的技术方向?我作为AI助手,虽然在很多编程相关的话题上都有所了解,但很期待听听你作为资深程序员的实际经验和见解。
Human: 我最近在研究AI,想了解一下AI的发展趋势
AI: 很高兴你对AI发展趋势感兴趣,Alben!作为资深程序员,你对AI的关注非常及时,因为AI正在深刻改变整个编程和开发领域。

从我了解到的信息来看,AI发展趋势主要集中在几个方面:

**技术层面**:
- 大语言模型持续进化,推理能力和多模态处理能力不断提升
- AutoML和AIGC(AI生成内容)技术快速发展
- 边缘AI计算和模型压缩技术日趋成熟

**应用层面**:
- AI在代码生成、自动化测试、智能调试等方面应用越来越广泛
- 企业级AI应用从试点走向规模化部署
- AI与各行业深度融合,比如医疗、金融、制造等

**对开发者的影响**:
- 编程工具和IDE正在集成更多AI辅助功能
- 低代码/无代码平台借助AI技术快速普及
- 开发者需要掌握AI相关的技能,如模型微调、Prompt工程等

作为程序员,你认为AI技术的哪个方面最值得重点关注?或者你已经在哪些具体场景中尝试过AI应用了?
Human: 你还记得我的名字吗?我最近在研究什么
AI:

> Finished chain.
用户:你还记得我的名字吗?我最近在研究什么
AI:{'input': '你还记得我的名字吗?我最近在研究什么', 'history': 'Human: 你好,我是Alben,是一名资深程序员\nAI: 你好Alben!很高兴认识你这位资深程序员!作为一名资深
程序员,你一定有很多丰富的编程经验和技巧吧。我很好奇你主要专注于哪些编程语言和技术领域呢?是偏向后端开发、前端开发,还是其他特定的技术方向?我作为AI助手,虽然在很 
多编程相关的话题上都有所了解,但很期待听听你作为资深程序员的实际经验和见解。\nHuman: 我最近在研究AI,想了解一下AI的发展趋势\nAI: 很高兴你对AI发展趋势感兴趣,Alben 
!作为资深程序员,你对AI的关注非常及时,因为AI正在深刻改变整个编程和开发领域。\n\n从我了解到的信息来看,AI发展趋势主要集中在几个方面:\n\n**技术层面**:\n- 大语言 
模型持续进化,推理能力和多模态处理能力不断提升\n- AutoML和AIGC(AI生成内容)技术快速发展\n- 边缘AI计算和模型压缩技术日趋成熟\n\n**应用层面**:\n- AI在代码生成、自 
动化测试、智能调试等方面应用越来越广泛\n- 企业级AI应用从试点走向规模化部署\n- AI与各行业深度融合,比如医疗、金融、制造等\n\n**对开发者的影响**:\n- 编程工具和IDE正
在集成更多AI辅助功能\n- 低代码/无代码平台借助AI技术快速普及\n- 开发者需要掌握AI相关的技能,如模型微调、Prompt工程等\n\n作为程序员,你认为AI技术的哪个方面最值得重点
关注?或者你已经在哪些具体场景中尝试过AI应用了?', 'response': '是的,我当然记得你的名字!你叫Alben,而且我清楚地记得你最近在研究AI。你刚才还跟我分享了你对AI发展趋
势的兴趣,还提到作为资深程序员,你对AI技术的各个层面都很关注,包括大语言模型、AutoML、AIGC、边缘AI计算等技术发展,以及AI在代码生成、自动化测试、智能调试等方面的应 
用。\n\n你之前还提到,你对AI对开发者影响的方面特别感兴趣,比如编程工具集成AI辅助功能、低代码/无代码平台的发展,以及开发者需要掌握的AI相关技能等。\n\n你当时还问我,
作为程序员,你觉得AI技术的哪个方面最值得重点关注?我印象很深呢!'}

==================================================
Human: 你好,我是Alben,是一名资深程序员
AI: 你好Alben!很高兴认识你这位资深程序员!作为一名资深程序员,你一定有很多丰富的编程经验和技巧吧。我很好奇你主要专注于哪些编程语言和技术领域呢?是偏向后端开发、前
端开发,还是其他特定的技术方向?我作为AI助手,虽然在很多编程相关的话题上都有所了解,但很期待听听你作为资深程序员的实际经验和见解。
Human: 我最近在研究AI,想了解一下AI的发展趋势
AI: 很高兴你对AI发展趋势感兴趣,Alben!作为资深程序员,你对AI的关注非常及时,因为AI正在深刻改变整个编程和开发领域。

从我了解到的信息来看,AI发展趋势主要集中在几个方面:

**技术层面**:
- 大语言模型持续进化,推理能力和多模态处理能力不断提升
- AutoML和AIGC(AI生成内容)技术快速发展
- 边缘AI计算和模型压缩技术日趋成熟

**应用层面**:
- AI在代码生成、自动化测试、智能调试等方面应用越来越广泛
- 企业级AI应用从试点走向规模化部署
- AI与各行业深度融合,比如医疗、金融、制造等

**对开发者的影响**:
- 编程工具和IDE正在集成更多AI辅助功能
- 低代码/无代码平台借助AI技术快速普及
- 开发者需要掌握AI相关的技能,如模型微调、Prompt工程等

作为程序员,你认为AI技术的哪个方面最值得重点关注?或者你已经在哪些具体场景中尝试过AI应用了?
Human: 你还记得我的名字吗?我最近在研究什么
AI: 是的,我当然记得你的名字!你叫Alben,而且我清楚地记得你最近在研究AI。你刚才还跟我分享了你对AI发展趋势的兴趣,还提到作为资深程序员,你对AI技术的各个层面都很关注
,包括大语言模型、AutoML、AIGC、边缘AI计算等技术发展,以及AI在代码生成、自动化测试、智能调试等方面的应用。

你之前还提到,你对AI对开发者影响的方面特别感兴趣,比如编程工具集成AI辅助功能、低代码/无代码平台的发展,以及开发者需要掌握的AI相关技能等。

你当时还问我,作为程序员,你觉得AI技术的哪个方面最值得重点关注?我印象很深呢!
==================================================
==================================================
开始 LangGraph 对话 (自动持久化):
==================================================
User: 我今天去了公园,看到了很多花。

User: 我刚才说我在哪里?

[当前记忆状态]:
4 条消息记录

进阶示例

案例 5:文档问答系统

该 Demo 是一个 LangChain v1 LCEL 的标准 RAG 实现,使用 Ollama 进行本地部署。有些小前提

必要的安装包

为了运行这个本地 RAG 系统,您需要安装以下 Python 包,并确保本地 Ollama 服务已启动且模型已拉取:

bash 复制代码
# 核心 LCEL 依赖通常随其他包安装,但我们明确列出所需功能包:
pip install -U langchain-ollama langchain-community langchain-text-splitters
pip install -U chroma-db 

Ollama 模型准备 (命令行操作)

确保您的 Ollama 服务正在运行,并拉取了以下模型:

  1. 嵌入模型 (Embedding Model): 用于向量化文档。

    Bash

    bash 复制代码
    ollama pull nomic-embed-text
  2. 聊天模型 (Chat Model): 用于问答生成。

    Bash

    bash 复制代码
    ollama pull qwen2.5:7b
    有条件的
    ollma pull qwen3-coder:30b

    因为我这里有两套环境 Mac 7b Windows就用30b所以会出现上下的demo 使用的模型出现些许的出入,这点在这里也做一个说明,防止看着些的朋友出现一些困惑。


创建文件 demo5_document_qa.py

python 复制代码
"""
案例 5:文档问答系统 (Ollama 纯本地 RAG 版本)
Embedding 和 Chat 模型均使用 Ollama。

请确保已在 Ollama 中拉取了嵌入模型 (如 nomic-embed-text)。
运行命令示例:ollama pull nomic-embed-text
"""
import os
# from dotenv import load_dotenv # ❌ 不再需要,因为没有外部 API Key
# import os # 保留,用于文件操作

# V1 核心组件导入 (来自 langchain_core)
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser

# V1 专用包导入 (修正了 text_splitter 的路径)
from langchain_text_splitters import RecursiveCharacterTextSplitter 

# V1 社区/技术组件导入
from langchain_ollama import ChatOllama, OllamaEmbeddings # ✅ 新增 OllamaEmbeddings 
# from langchain_openai import OpenAIEmbeddings # ❌ 不再需要

from langchain_community.vectorstores import Chroma 
from langchain_community.document_loaders import TextLoader

# load_dotenv() # ❌ 不再需要加载 .env 文件

# --- 辅助函数:格式化文档 (取代 chain_type="stuff") ---
def format_docs(docs):
    """将检索到的文档列表格式化为一个单独的字符串,用于注入 Prompt。"""
    return "\n\n".join(doc.page_content for doc in docs)

# --- 辅助函数:创建示例文档 ---
def create_sample_document():
    # ... (函数体与内容保持不变)
    content = """
    Python 是一种高级编程语言,由 Guido van Rossum 于 1991 年首次发布。
    Python 的设计哲学强调代码的可读性和简洁的语法,使用缩进来表示代码块。
    
    Python 具有以下特点:
    1. 简单易学:Python 的语法简洁明了,适合初学者。
    2. 功能强大:拥有丰富的标准库和第三方库。
    3. 跨平台:可以在 Windows、macOS、Linux 等操作系统上运行。
    4. 解释型语言:无需编译,可以直接运行。
    5. 面向对象:支持面向对象编程范式。
    
    Python 的应用领域非常广泛:
    - Web 开发:使用 Django、Flask 等框架
    - 数据科学:使用 NumPy、Pandas、Matplotlib 等库
    - 人工智能:使用 TensorFlow、PyTorch 等框架
    - 自动化运维:使用 Ansible、Fabric 等工具
    - 爬虫开发:使用 Scrapy、BeautifulSoup 等库
    
    Python 的版本历史:
    - Python 2.x:2000 年发布,2020 年停止维护
    - Python 3.x:2008 年发布,是当前主流版本
    """
    
    doc_path = "python_intro.txt"
    with open(doc_path, "w", encoding="utf-8") as f:
        f.write(content)
    
    return doc_path

# --- 核心 RAG 逻辑函数 (v1 LCEL) ---
def document_qa_system_v1():
    
    print("=" * 50)
    print("创建文档问答系统 (Ollama 纯本地版)...")
    print("=" * 50)
    
    # 步骤 1-2:创建、加载、分割文档
    doc_path = create_sample_document()
    loader = TextLoader(doc_path, encoding="utf-8")
    documents = loader.load()
    text_splitter = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=50)
    texts = text_splitter.split_documents(documents)
    print(f"✓ 已分割文档,共 {len(texts)} 个片段")
    
    # 步骤 3:创建向量存储和检索器
    # 🌟 关键修改:使用 OllamaEmbeddings
    # 请确保 'nomic-embed-text' (或你选择的任何 Ollama 嵌入模型) 已拉取
    embeddings = OllamaEmbeddings(model="nomic-embed-text") 
    
    vectorstore = Chroma.from_documents(documents=texts, embedding=embeddings)
    retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
    print("✓ 已创建向量存储和检索器 (使用 Ollama Embedding)")
    
    # 步骤 4:定义 LLM 和 Prompt
    llm = ChatOllama(model="qwen3-coder:30b", temperature=0) # Ollama Chat Model 保持不变
    
    prompt = ChatPromptTemplate.from_template("""
        你是一个专业的问答助手,请基于提供的上下文 (Context) 来回答问题 (Question)。
        如果上下文中没有足够的信息,请说明你无法找到相关信息。
        
        ---
        Context:
        {context}
        ---
        
        Question: {question}
        """)

    # 步骤 5-7:构建 LCEL Chain 和执行逻辑 (保持不变)
    
    rag_chain_core = (
        RunnablePassthrough.assign(
            context=lambda x: x["context"]
        )
        | prompt
        | llm
        | StrOutputParser()
    )

    def get_source_and_answer(query: str):
        source_documents = retriever.invoke(query)
        chain_input = {
            "question": query,
            "context": format_docs(source_documents)
        }
        result = rag_chain_core.invoke(chain_input)
        return {
            "query": query,
            "result": result,
            "source_documents": source_documents,
        }
        
    print("✓ 已创建 LCEL RAG 包装函数")

    # 进行问答
    print("\n" + "=" * 50)
    print("开始问答:")
    print("=" * 50)
    
    questions = [
        "Python 是谁发明的?",
        "Python 有哪些特点?",
        "Python 可以用于哪些领域?",
        "Python 2 什么时候停止维护的?"
    ]
    
    for question in questions:
        print(f"\n问题:{question}")
        result = get_source_and_answer(question)
        print(f"答案:{result['result']}")
        
        print("\n引用的文档片段:")
        for i, doc in enumerate(result['source_documents'], 1):
            print(f"  片段 {i}:{doc.page_content[:100]}...")
        print("-" * 50)
        
    # 清理临时文件
    os.remove(doc_path)
    print("\n✓ 已清理临时文件")

if __name__ == "__main__":
    document_qa_system_v1()

输出结果:

bash 复制代码
==================================================
创建文档问答系统 (Ollama 纯本地版)...
==================================================
✓ 已分割文档,共 4 个片段
✓ 已创建向量存储和检索器 (使用 Ollama Embedding)
✓ 已创建 LCEL RAG 包装函数

==================================================
开始问答:
==================================================

问题:Python 是谁发明的?
答案:根据提供的上下文信息,Python 是由 Guido van Rossum 发明的。他在 1991 年首次发布了这门编程语言。

引用的文档片段:
  片段 1:Python 是一种高级编程语言,由 Guido van Rossum 于 1991 年首次发布。
    Python 的设计哲学强调代码的可读性和简洁的语法,使用缩进来表示代码块。    
    
  ...
  片段 2:- 爬虫开发:使用 Scrapy、BeautifulSoup 等库
    
    Python 的版本历史:
    - Python 2.x:2000 年发布,2020 年停止维护
    - ...
  片段 3:2. 功能强大:拥有丰富的标准库和第三方库。
    3. 跨平台:可以在 Windows、macOS、Linux 等操作系统上运行。
    4. 解释型语言:无需编译,可以直接运行。
    5....
--------------------------------------------------

问题:Python 有哪些特点?
答案:根据提供的上下文,Python 具有以下特点:

1. **简单易学**:Python 的语法简洁明了,适合初学者。
2. **功能强大**:拥有丰富的标准库和第三方库。
3. **跨平台**:可以在 Windows、macOS、Linux 等操作系统上运行。
4. **解释型语言**:无需编译,可以直接运行。
5. **面向对象**:支持面向对象编程范式。
6. **代码可读性强**:强调代码的可读性和简洁的语法,使用缩进来表示代码块。

这些特点使得 Python 成为一门既易于学习又功能强大的编程语言。

引用的文档片段:
  片段 1:Python 是一种高级编程语言,由 Guido van Rossum 于 1991 年首次发布。
    Python 的设计哲学强调代码的可读性和简洁的语法,使用缩进来表示代码块。

  ...
  片段 2:- 爬虫开发:使用 Scrapy、BeautifulSoup 等库

    Python 的版本历史:
    - Python 2.x:2000 年发布,2020 年停止维护
    - ...
  片段 3:2. 功能强大:拥有丰富的标准库和第三方库。
    3. 跨平台:可以在 Windows、macOS、Linux 等操作系统上运行。
    4. 解释型语言:无需编译,可以直接运行。
    5....
--------------------------------------------------

问题:Python 可以用于哪些领域?
答案:根据提供的上下文信息,Python 可以用于以下领域:

1. **Web 开发**:使用 Django、Flask 等框架
2. **爬虫开发**:使用 Scrapy、BeautifulSoup 等库

此外,虽然上下文中没有明确提到,但根据 Python 的特点(如功能强大、跨平台、解释型语言、面向对象等),它还可以应用于:
- 数据分析和科学计算
- 人工智能和机器学习
- 自动化脚本
- 软件开发
- 网络编程等

不过,基于上下文直接提供的信息,主要提到了 Web 开发和爬虫开发这两个领域。

引用的文档片段:
  片段 1:Python 是一种高级编程语言,由 Guido van Rossum 于 1991 年首次发布。
    Python 的设计哲学强调代码的可读性和简洁的语法,使用缩进来表示代码块。

  ...
  片段 2:- 爬虫开发:使用 Scrapy、BeautifulSoup 等库

    Python 的版本历史:
    - Python 2.x:2000 年发布,2020 年停止维护
    - ...
  片段 3:2. 功能强大:拥有丰富的标准库和第三方库。
    3. 跨平台:可以在 Windows、macOS、Linux 等操作系统上运行。
    4. 解释型语言:无需编译,可以直接运行。
    5....
--------------------------------------------------

问题:Python 2 什么时候停止维护的?
答案:根据提供的上下文,Python 2.x 版本于 **2020 年停止维护**。

引用的文档片段:
  片段 1:Python 是一种高级编程语言,由 Guido van Rossum 于 1991 年首次发布。
    Python 的设计哲学强调代码的可读性和简洁的语法,使用缩进来表示代码块。

  ...
  片段 2:- 爬虫开发:使用 Scrapy、BeautifulSoup 等库

    Python 的版本历史:
    - Python 2.x:2000 年发布,2020 年停止维护
    - ...
  片段 3:2. 功能强大:拥有丰富的标准库和第三方库。
    3. 跨平台:可以在 Windows、macOS、Linux 等操作系统上运行。
    4. 解释型语言:无需编译,可以直接运行。
    5....
--------------------------------------------------

✓ 已清理临时文件
📝 代码结构和流程说明
  1. 数据准备 (Data Preparation):
    • 使用 TextLoader 加载本地文件。
    • 使用 RecursiveCharacterTextSplitter 将大文档分割成小片段 (texts),确保上下文不会丢失。
    • 使用 OllamaEmbeddings 将这些片段转换为向量,并存储到 Chroma 数据库。
  2. RAG 链定义 (LCEL Chain Definition):
    • rag_chain_core 定义了问答的逻辑流:先接收输入-> 结合 Prompt ->调用 LLM -> 解析输出。
    • get_source_and_answer 是一个包装函数,负责执行 检索 (retriever.invoke(query)),然后将检索结果(context)和原始问题一起传入核心 LCEL Chain 中生成答案。
graph TD subgraph Prepare["准备阶段 (仅运行一次)"] A[文档内容] --> B(文本分割器); B --> C(OllamaEmbeddings); C --> D[Chroma 向量数据库]; end subgraph Execute["运行阶段 (每轮问答)"] Q[用户问题 Query] --> |1. 转换为向量| R(Retriever 检索器); R --> F{获取 K 个最相关的文档片段}; Q --> G[原始问题]; F --> H[格式化函数 format_docs]; H --> I{Context 上下文}; I & G --> J[ChatPromptTemplate]; J --> K(ChatOllama LLM); K --> L[StrOutputParser]; L --> M[最终答案 Answer]; end
总结:

通过以上的实践,你就已经完成了一个最基础的的本地RAG了。如果你也在学习那么是不是也会觉得有点意思。


案例 6:使用 Agent(代理)

首先了解一下工作的流程:

%% ReAct 循环(LangChain v1 最小版) flowchart TD A[用户提问] --> B[create_agent 入口] B --> C{ReAct Prompt\n+ 工具描述} C --> D[LLM 生成 Thought\n+ Action] D --> E[工具调用] E --> F[Observation] F --> G{足够信息?} G -->|否| D G -->|是| H[LLM 生成 Final Answer] H --> I[结果输出]

创建文件 demo6_agent.py

python 复制代码
"""
案例 6:Agent(代理)展示如何让 AI 自主使用工具完成任务 (LangChain v1 最终版)

特点:
1. 纯本地 Agent,使用 Ollama qwen3-coder:30b 模型。
2. 采用简洁的 LangChain v1 LCEL 风格:create_agent 后直接 invoke(),无需 AgentExecutor。
"""
# ----------------------------------------------------
# 导入修正与核心组件
# ----------------------------------------------------
from langchain_ollama import ChatOllama             # 从 Ollama 包中导入聊天模型
from langchain.agents import create_agent           # V1 Agent 核心工厂函数,用于创建 Agent Runnable
from langchain_core.tools import tool               # 用于装饰 Python 函数,将其注册为 LLM 可用的工具
from langchain_core.messages import HumanMessage    # 用于格式化用户输入,符合 V1 Agent 的标准输入格式
import math                                         # 供计算器工具使用的标准数学库
# ----------------------------------------------------
# 非 Ollama 环境相关内容 (已注释)
# from dotenv import load_dotenv 
# load_dotenv() # 如果使用 OpenAI 等需要 API Key 的服务,此处用于加载环境变量
# ----------------------------------------------------

# --- 1. 工具定义:使用 @tool 装饰器实现自定义工具 ---
# 实现工具的意义在于,让 LLM 可以调用这些函数,完成特定的任务,补齐 LLM 的能力短板。

@tool
def calculator(expression: str) -> str:
    """用于执行数学计算。输入应该是一个数学表达式,例如:'2 + 2' 或 'math.sqrt(16)'"""
    # 这个 Docstring 会被 Agent 读取,作为工具的使用说明
    try:
        # eval的作用是执行字符串形式的表达式,并返回结果
        # expression是传入的字符串形式的变量
        # 限制命名空间:{'__builtins__': None} 禁用所有内置函数,
        # 仅允许访问 'math' 库,以提高 eval 的安全性(虽然仍需谨慎)
        result = eval(expression, {"__builtins__": None, "math": math}) 
        return f"计算结果:{result}"
    except Exception as e:
        return f"计算错误:{str(e)}"

@tool
def get_weather(city: str) -> str:
    """用于查询城市的天气情况。输入应该是一个城市名称,例如:'北京'"""
    # 这是一个模拟工具。在实际应用中,此函数体应该包含对外部天气 API 的调用逻辑。
    weather_data = {
        "北京": "晴天,气温 20°C",
        "上海": "多云,气温 25°C",
        "深圳": "雨天,气温 28°C"
    }
    return weather_data.get(city, f"抱歉,没有 {city} 的天气数据")

# --- 2. Agent 逻辑 ---

def agent_example_v1():
    """Agent 示例 (LangChain v1 最小可运行版本)"""
        
    print("=" * 50)
    print("创建 Agent(LangChain v1 LCEL 最小版)...")
    print("=" * 50)
        
    # 初始化 LLM 模型
    # 确保 Ollama 服务正在运行,并且 qwen3-coder:30b 模型已通过 ollama pull 拉取
    llm = ChatOllama(model="qwen3-coder:30b", temperature=0) 
        
    # 定义工具列表:将所有用 @tool 装饰的函数收集起来
    tools = [calculator, get_weather] 
        
    # ③ V1 核心:创建 Agent Runnable
    # create_agent 内部会生成一个 ReAct 模式的 Prompt,并将 tools 注册给 LLM。
    # 它返回一个 Runnable 对象,可直接调用。
    agent = create_agent(llm, tools)
        
    print("✓ Agent Runnable 已创建\n")
        
    # 测试用例
    test_cases = [
        "帮我计算 15 的平方根是多少",
        "北京今天天气怎么样?",
        "上海的天气如何,温度适合外出吗?",
        "请计算 (25 + 75) * 2 的结果"
    ]
        
    for i, query in enumerate(test_cases, 1):
        print("=" * 50)
        print(f"测试 {i}:{query}")
        print("=" * 50)
                
        try:
            # 🌟 V1 调用:直接 invoke Runnable
            # 输入格式:{"messages": [HumanMessage(content=query)]}
            # Agent 会根据这个输入开始它的 ReAct 循环(思考->调用工具->观察->再次思考)
            result = agent.invoke(
                {"messages": [HumanMessage(content=query)]}
            )
            
            # 最终答案:Agent 的输出是一个包含多轮思考和消息的字典。
            # 最终的答案(用户的回复)位于 messages 列表的最后一条消息中。
            answer = result["messages"][-1].content
            print(f"\n最终答案:{answer}\n") 
            
        except Exception as e:
            # 捕获执行过程中的错误,例如 Ollama 服务中断或 LLM 解析失败
            print(f"\n执行出错:{str(e)}\n")

if __name__ == "__main__":
    agent_example_v1()

输出结果:

bash 复制代码
==================================================
创建 Agent(LangChain v1 LCEL 最小版)...
==================================================
✓ Agent Runnable 已创建

==================================================
测试 1:帮我计算 15 的平方根是多少
==================================================

最终答案:15 的平方根约等于 3.873。

==================================================
测试 2:北京今天天气怎么样?
==================================================

最终答案:北京今天天气晴朗,气温为 20°C。

==================================================
测试 3:上海的天气如何,温度适合外出吗?
==================================================

最终答案:上海目前天气多云,气温为25°C。这样的温度比较舒适,适合外出活动。不过建议携带一件薄外套,以防天气变化或早晚温差较大。

==================================================
测试 4:请计算 (25 + 75) * 2 的结果
==================================================

最终答案:计算结果为 200。

源码速览

  • @tool:把普通函数变成 LLM 可调用的 Action
  • create_agent:封装 ReAct Prompt,返回 Runnable
  • invoke({"messages": [...]}):v1 标准输入,最后一条消息即最终答案

小结

demo6 用最少的代码展示了 LangChain v1 的 ReAct Agent 全貌:本地模型、自定义工具、即创即跑,复制即可体验"让 AI 自己动脑子"。


运行所有示例

创建文件 run_all_demos.py

python 复制代码
"""
运行所有示例
"""

import subprocess
import sys

def run_demo(demo_name):
    """运行单个示例"""
    print("\n" + "=" * 70)
    print(f"运行 {demo_name}")
    print("=" * 70 + "\n")
    
    try:
        subprocess.run([sys.executable, demo_name], check=True)
    except subprocess.CalledProcessError as e:
        print(f"运行 {demo_name} 时出错:{e}")
    except FileNotFoundError:
        print(f"找不到文件:{demo_name}")

def main():
    demos = [
        "demo1_basic.py",
        "demo2_prompt_template.py",
        "demo3_chains.py",
        "demo4_memory.py",
        "demo5_document_qa.py",
        "demo6_agent.py"
    ]
    
    print("开始运行所有 LangChain 示例...")
    
    for demo in demos:
        run_demo(demo)
    
    print("\n" + "=" * 70)
    print("所有示例运行完成!")
    print("=" * 70)

if __name__ == "__main__":
    main()

总结

通过上面的的六个demo 相信你对langchin已经有了一个基本的认识了,为了节约很多同学的学习成本。

如果你的本地只有一台Mac 建议你使用ollama qwen2.5:7b 基本轻松无法压力。

那么如果你的预算比较充足或者你的本地的配置比较高 可以尝试和我使用同样的本地模型qwen3-coder:30b。

6 个 demo 覆盖核心:调用 → 链 → 记忆 → RAG → Agent

下一篇我们讲《langchin深入》

相关推荐
smj2302_796826521 小时前
解决leetcode第3753题范围内总波动值II
python·算法·leetcode
mortimer2 小时前
破局视频翻译【最后一公里】––从语音克隆到口型对齐的完整工程思路
python·github·aigc
山顶夕景4 小时前
【RL】Does RLVR enable LLMs to self-improve?
深度学习·llm·强化学习·rlvr
门框研究员4 小时前
解锁Python的强大能力:深入理解描述符
python
子不语1805 小时前
Python——函数
开发语言·python
daidaidaiyu5 小时前
一文入门 LangChain 开发
python·ai
JJ1M86 小时前
用 Python 快速搭建一个支持 HTTPS、CORS 和断点续传的文件服务器
服务器·python·https
汤姆yu6 小时前
基于python大数据的小说数据可视化及预测系统
大数据·python·信息可视化
x***J3487 小时前
Python多线程爬虫
开发语言·爬虫·python