LangChain for Python: 基本使用场景与实现的实践

LangChain for Python: 基本使用场景与实现

目录

核心概念

LangChain是一个用于构建AI应用的框架,主要功能:

  • 连接语言模型与其他数据源
  • 管理对话上下文
  • 构建复杂的工作流

核心组件:

LLM Provider (e.g. OpenAI)
│
├── Prompt Templates
├── Memory
├── Chains
└── Agents/Tools

典型使用场景

1. 文档问答系统

加载文档
文本分割
向量化存储
用户提问
相似度检索
生成回答

2. 对话机器人

用户输入
记忆上下文
语言模型
响应输出

3. 数据增强ETL

原始数据
LangChain处理
结构化输出

实现流程(重点介绍场景1)

1. 安装

!pip install langchain

2. 基本操作,引入llm(tongyi qwen-turbo)


from langchain_community.llms import Tongyi
import os

# 检查环境变量
DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY')
if not DASHSCOPE_API_KEY:
    raise ValueError("请设置 DASHSCOPE_API_KEY 环境变量")

# 模型配置
# EMBEDDING_MODEL = "text-embedding-v1"
LLM_MODEL = "qwen-turbo"  # 可以根据需要调整模型
llm = Tongyi(
            model_name=LLM_MODEL,
            temperature=0.7,
            dashscope_api_key=DASHSCOPE_API_KEY
        )
llm.invoke("中国的首都在哪里?")
    '中国的首都是北京。'

3. 构建chain :提示+模型+输出解析器

# 创建提示模板
from langchain.prompts import ChatPromptTemplate
topic=""
prompt = ChatPromptTemplate.from_template("""
请基于用户输入的主题,编写一篇小红书营销短文。
主题:{topic}

回答:""")
from langchain_core.output_parsers import StrOutputParser
output_parser=StrOutputParser()
chain=prompt|llm|output_parser
chain.invoke({"topic":"大众ID4"})
    '✨城市探索新伙伴——大众ID.4,开启你的电动未来!🚗💨\n\n你是否厌倦了燃油车的高油耗?...'
  • 定义chain旧方法不建议使用
# from langchain.chains import LLMChain
# langChainDeprecationWarning: The class `LLMChain` was deprecated in LangChain 0.1.17 and will be removed in 1.0. Use :meth:`~RunnableSequence, e.g., `prompt | llm`` instead.
# chain = LLMChain(llm=llm, prompt=prompt)

  • chain=prompt|llm|output_parser 是管道拼接的功能,是以下三步的链接
prompt_value=prompt.invoke("人工智能将改变世界")
prompt_value
    ChatPromptValue(messages=[HumanMessage(content='\n请基于用户输入的主题,编写一篇小红书营销短文。\n主题:人工智能将改变世界\n\n回答:', additional_kwargs={}, response_metadata={})])
message= llm.invoke(prompt_value)
message
    '🌟【未来已来 | 人工智能将如何改变我们的生活?】🌟\n\n姐妹们!你有没有想过,有一天早晨醒来,...'
output_parser.invoke(message)
    '🌟【未来已来 | 人工智能将如何改变我们的生活?】🌟\n\n姐妹们!你有没有想过,有一天早晨醒来,...'

等同于:

chain=prompt|llm|output_parser
chain.invoke("人工智能将改变世界")
    '🌟【未来已来,人工智能将如何改变我们的生活?】🌟\n\n你是否曾幻想过像科幻电影里一样,...'

数据处理流程

Dict
Prompt Value
ChatMessage
String
input
Prompt Template
ChatModel
StrOutputParser
Result
组件说明
  1. Dict

    • 原始输入数据(字典格式)
  2. PromptTemplate

    • 将输入字典转换为标准提示模板
  3. PromptValue

    • 格式化后的提示值对象
  4. ChatModel

    • 语言模型处理核心
  5. ChatMessage

    • 模型生成的原始消息输出
  6. StrOutputParser

    • 输出解析器,功能包括:
      • 接受BaseOutput或BaseMessage作为输入
      • 将任何输入转换为字符串格式
  7. String

    • 标准化字符串输出
  8. Result

    • 最终处理结果

4. 简单的文档问答实现

使用langchain的WebBaseLoader,VectorstoreIndexCreator,DashScopeEmbeddings和FAISS向量数据库实现简单的RAG功能

from langchain.document_loaders import WebBaseLoader
from langchain.indexes import VectorstoreIndexCreator
from langchain_community.embeddings import DashScopeEmbeddings  # 使用DashScope的嵌入模型
from langchain_community.llms import Tongyi
from langchain_community.vectorstores import FAISS  # 显式指定向量存储
import os
# 0. 设置必要的环境变量
# os.environ["DASHSCOPE_API_KEY"] = "your-dashscope-api-key"  # 您的DashScope API Key,已经设置过
os.environ["USER_AGENT"] = "MyApp/1.0"  # 解决USER_AGENT警告
DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY')
EMBEDDING_MODEL = "text-embedding-v2"
LLM_MODEL = "qwen-turbo"  # 可以根据需要调整模型
if not DASHSCOPE_API_KEY:
        raise ValueError("请设置 DASHSCOPE_API_KEY 环境变量")
# 1. 配llm
from langchain_community.llms import Tongyi
llm = Tongyi(
            model_name=LLM_MODEL,
            temperature=0.7,
            dashscope_api_key=DASHSCOPE_API_KEY
        )

# 2. 创建DashScope的embedding
embedding = DashScopeEmbeddings(
    model = EMBEDDING_MODEL,  # 推荐使用的模型
    dashscope_api_key = DASHSCOPE_API_KEY
)

# 3. 配置IndexCreator(解决内存存储警告和embedding缺失问题)
# index_creator = VectorstoreIndexCreator(
#     embedding=embedding,
#     llm=llm,
#     vectorstore_kwargs={"persist_directory": "db"}  # 可选:持久化存储路径
# )
# 3. 正确配置IndexCreator
index_creator = VectorstoreIndexCreator(
    vectorstore_cls=FAISS,  # 显式指定向量存储
    embedding=embedding,
    # 注意:这里不再直接传入llm
)
# 4. 加载网页数据
loader = WebBaseLoader("https://blog.csdn.net/alva_xu/article/details/147249709")
index = index_creator.from_loaders([loader])

# 5. 提问查询
query = "这篇文章的主要观点是什么?"
result = index.query(question=query, llm=llm)  # 必须传入llm参数
result
'这篇文章的主要观点是介绍和对比了自然语言处理中的三种重要技术:N-Gram、TF-IDF 和 Word Embedding。文章详细解释了每种技术的基本概念、工作原理、优缺点以及应用场景,并通过实际案例展示了如何结合这些技术来解决具体问题,例如基于酒店描述的推荐系统。此外,文章还总结了 Word Embedding 的核心思想和常见方法(如 Word2Vec、GloVe、BERT),并指出了它们的优点和局限性。整体目的是帮助读者理解这些技术的特点及其在实际应用中的价值。'

完整示例:知识库问答系统

1. 环境准备:

! pip install unstructured 
! pip install python-docx unstructured
! pip install nltk
! pip install --upgrade langchain-core langchain
手动下载NLTK数据(推荐)
  • 1.手动下载数据包,并解压:
    访问 https://github.com/nltk/nltk_data/tree/gh-pages/packages
    下载以下两个zip文件:
    tokenizers/punkt.zip
    tokenizers/punkt_tab.zip
    1. 手动安装:
import nltk
from nltk import data

# 指定自定义数据路径(可选)
custom_path = r'D:\cursorprj\langchain\ntlk_data'
nltk.data.path.append(custom_path)
from nltk.tokenize import sent_tokenize
text = "This is a test. This is another sentence."
sent_tokenize(text) # 应该输出句子列表



    ['This is a test.', 'This is another sentence.']

用pycharm执行以下py程序, 下载NLTK到C:\Users\Administrator\AppData\Roaming\nltk_data
# import nltk
# nltk.download('punkt')       # 基础分词数据(必须)
# nltk.download('stopwords')   # 停用词(可选)
# nltk.download('averaged_perceptron_tagger')  # 词性标注(可选)
# nltk.download('wordnet')     # 词库(可选)
# nltk.download('averaged_perceptron_tagger_eng')
#测试
from nltk.tokenize import sent_tokenize
text = "This is a test. This is another sentence."
sent_tokenize(text) # 应该输出句子列表
    ['This is a test.', 'This is another sentence.']

2. 正式代码:

# 1. 准备数据
from langchain.document_loaders import (
    DirectoryLoader,
    TextLoader,
    UnstructuredWordDocumentLoader  # 处理doc文件
)


# 加载txt文件
txt_loader = DirectoryLoader(
    directory,
    glob="**/*.txt",
    loader_cls=TextLoader,
    show_progress=True
)

# 加载doc/docx文件
doc_loader = DirectoryLoader(
    directory,
    glob="**/*.doc*",  # 匹配.doc和.docx
    loader_cls=UnstructuredWordDocumentLoader,
    show_progress=True
)

# 合并所有文档
documents = txt_loader.load() + doc_loader.load()

documents


# 2. 分割文本
from langchain.text_splitter import RecursiveCharacterTextSplitter

directory = "./docs"  # 替换为你的文档目录路径
chunk_size = 500                     # 每个chunk的字符数
chunk_overlap = 50    # chunk之间的重叠字符数
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=chunk_size,
    chunk_overlap=chunk_overlap,
    separators=["\n\n", "\n", "。", "!", "?", ";", "……"],
    length_function=len,
    is_separator_regex=False
)
chunks = text_splitter.split_documents(documents)
chunks
print(f"\n共处理 {len(documents)} 个文档")
print(f"生成 {len(chunks)} 个文本块\n")
for i, chunk in enumerate(chunks[:3]):  # 显示前3个chunk
    print(f"Chunk {i+1}:")
    print("-"*40)
    print(chunk.page_content[:200] + "...")
    print(f"来源: {chunk.metadata['source']}")
    print("="*40 + "\n")


    共处理 3 个文档
    生成 62 个文本块
    
    Chunk 1:
    ----------------------------------------
    上海市数字经济发展“十四五”规划 
     ...
    ========================================
    
    Chunk 2:
    ----------------------------------------

    ...
    来源: docs\上海市数字经济发展.txt
    ========================================
    
    Chunk 3:
    ----------------------------------------
     ...
    来源: docs\上海市数字经济发展.txt
    ========================================
# 3. 实现知识库查询


from langchain_community.embeddings import DashScopeEmbeddings  # 使用DashScope的嵌入模型
from langchain_community.llms import Tongyi
from langchain_community.vectorstores import FAISS  # 显式指定向量存储
import os
# 0. 设置必要的环境变量
# os.environ["DASHSCOPE_API_KEY"] = "your-dashscope-api-key"  # 您的DashScope API Key,已经设置过
os.environ["USER_AGENT"] = "MyApp/1.0"  # 解决USER_AGENT警告
DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY')
EMBEDDING_MODEL = "text-embedding-v2"
LLM_MODEL = "qwen-turbo"  # 可以根据需要调整模型
if not DASHSCOPE_API_KEY:
        raise ValueError("请设置 DASHSCOPE_API_KEY 环境变量")
# 1. 配llm
from langchain_community.llms import Tongyi
llm = Tongyi(
            model_name=LLM_MODEL,
            temperature=0.7,
            dashscope_api_key=DASHSCOPE_API_KEY
        )

# 2. 创建DashScope的embedding

embedding = DashScopeEmbeddings(
    model = EMBEDDING_MODEL,  # 推荐使用的模型
    dashscope_api_key = DASHSCOPE_API_KEY
)
# 3.创建向量数据库
db = FAISS.from_documents(chunks, embedding)

2.1 不对prompt进行设置,用默认的prompt

# 4. 创建问答链
from langchain.chains import RetrievalQA
    
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=db.as_retriever(search_kwargs={"k": 3}),  # # 控制返回的文档数量为3
)
qa_chain
# prompt.input_variables
# db.as_retriever(search_kwargs={"k": 3})
# 5. 提问
question = "知识库中有哪些内容?"
result = qa_chain.invoke({"query": question})
result
result输出内容
    {'query': '知识库中有哪些内容?',
     'result': '根据提供的信息,知识库中包含以下内容:\n\n1. **数字内容相关**:\n   - 数字内容产业的新业态新模式。\n  ...'}
2.2 自定义Prompt的方式
# 6. 创建prompt
from langchain.prompts import PromptTemplate

template = """根据以下上下文信息回答问题:
{context}

问题:{question}
回答:
请用中文简洁回答,若不知道答案请如实说明。"""

QA_PROMPT = PromptTemplate(
    input_variables=["context", "question"],  # 必须包含这两个变量
    template=template
)

# 7. 创建问答链
from langchain.chains import RetrievalQA
    
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",
    retriever=db.as_retriever(search_kwargs={"k": 3}),  # # 控制返回的文档数量为3
    chain_type_kwargs={
        "prompt": QA_PROMPT,
        "document_variable_name": "context"  # 必须与模板变量名一致,context 的值是自动从检索器(retriever)获取并注入到 prompt 
    },
    return_source_documents=True  # 返回参考文档
)
# qa_chain
# prompt.input_variables
db.as_retriever(search_kwargs={"k": 3})



    VectorStoreRetriever(tags=['FAISS', 'DashScopeEmbeddings'], vectorstore=<langchain_community.vectorstores.faiss.FAISS object at 0x000001E9C87AA780>, search_kwargs={'k': 3})
# 8. 提问
# 问答循环
print("\n系统已准备就绪,可以开始提问了。输入'退出'结束对话。")
while True:
    question = input("\n请输入问题:")
    if question.lower() == '退出':
        break
        
    # 生成回答
    result = qa_chain.invoke({"query": question}) 
    # print(result)
    # 输出结果
    print("答案:", result["result"])
    print("\n参考文档:")
    for doc in result["source_documents"]:
        print(f"- {doc.page_content[:100]}...")  # 显示文档前100字符

运行情况
系统已准备就绪,可以开始提问了。输入'退出'结束对话。

请输入问题: 请问浦发银行客户经理违反规定要扣几分?
答案: 根据上下文信息,如果浦发银行客户经理在工作中有不廉洁自律的情况,每发现一次扣50分。其他违反规定的情况需具体分析,例如资产质量考核和逾期处理等,都有相应的扣分标准。若不知道具体违规类型,则无法确定扣分分数。

参考文档:
- 7、在工作中有不廉洁自律情况的每发现一次扣 50 分。

(二)个人资产质量考核:

当季考核收息率 97%以上为合格,每降 1 个百分点扣 2 分;不

良资产零为合格,每超一个个百分点扣 1 分。...
- 第八章 管理与奖惩

第十八条 个金客户经理管理机构为分行客户经理管理委员会。管理委员会组成人员:行长或主管业务副行长,个人业务部、人力资源部、风险管理部负责人。

第十九条 客户经理申报的各种信息必...
- 助理客户经理待遇按照人事部门对主办科员以下人员的待遇标准;客户经理待遇按照人事部门对主办科员的待遇标准;高级客户经理待遇按照人事部门对付科级的待遇标准;资深客户经理待遇按照人事部门对正科级的待遇标准。...

请输入问题:
↑↓ for history. Search history with c-↑/c-↓
<think>嗯,用户之前问过关于Agent Reasoning和Planning的关系,现在他们想了解这两种技术用什么框架实现,特别是LangGraph和LangChain是否有相关的接口,并且要求详细的代码示例。首先,我需要确定用户可能对这两个框架的熟悉程度,他们可能已经有一定的AI开发基础,尤其是使用LangChain和LangGraph来构建智能体应用。 用户的问题可以分为两部分:框架实现和具体库中的接口。我需要先解释常见的框架,比如LangChain、LangGraph、AutoGPT等,然后深入LangChain和LangGraph中的具体实现。用户可能希望了解如何在这些框架中构建推理和规划模块,以及具体的代码示例。 接下来,我需要考虑LangChain和LangGraph的关系。LangChain是一个用于构建基于语言模型应用的框架,而LangGraph是它的扩展,支持更复杂的流程,比如多智能体协作或循环图结构。用户可能想知道如何在这两个库中实现规划和推理的逻辑,例如通过自定义节点和边来构建工作流。 在代码示例方面,需要展示如何使用LangGraph创建规划模块,比如任务分解,以及推理模块,比如动态调整策略。可能需要使用到PlanningAgent和ReasoningAgent类,并通过LangGraph的图结构来连接它们。同时,要注意代码的简洁性和可读性,可能需要添加注释说明每个部分的作用。 另外,用户可能对实际应用场景感兴趣,比如电商客服中的任务分解和回复生成。需要确保示例贴近实际,方便用户理解。同时,要提到LangChain中的现有工具,比如LLMChain、AgentExecutor,以及如何LangGraph结合使用。 最后,需要验证代码是否正确,比如检查LangGraph的版本是否支持add_node和add_edge等函数,确保示例代码能够运行。可能还需要提及使用不同模型(如OpenAI或本地模型)时的配置差异,以及如何处理依赖和安装问题。</think>以下是关于**Agent Reasoning****Planning**的框架实现方法,以及在`LangGraph`和`LangChain`中的具体接口代码示例解析: --- ### 一、主流实现框架概述 | **技术方向** | **常用框架** | **核心能力** | |-------------------|-----------------------------|------------------------------------------| | 符号推理+规划 | PDDL工具链(如FastDownward)| 基于逻辑规则的规划问题求解 | | 概率推理+规划 | Pyro/POMDPs.jl | 处理不确定性的贝叶斯规划 | | 分层任务网络(HTN) | SHOP2/JSHOP3 | 面向复杂任务的分层分解 | | 强化学习规划 | Stable Baselines/RLLib | 通过试错学习最优策略 | | **语言模型驱动** | **LangChain + LangGraph** | 基于LLM的推理规划流水线构建 | --- ### 二、LangChainLangGraph中的实现 #### 1. **核心接口设计** - **LangChain** 提供基础组件: - `LLMChain`:语言模型调用管道 - `AgentExecutor`:动作执行引擎 - `Tool`:规划中的原子操作单元 - **LangGraph** 扩展为图结构: - `StateGraph`:定义节点状态流转 - `Node`:封装推理或规划模块 - `Edge`:条件跳转逻辑 #### 2. **典型代码结构** ```python from langchain_core.runnables import RunnablePassthrough from langgraph.graph import StateGraph, END # 定义状态类型 class AgentState(TypedDict): input: str reasoning_log: list plan: list # 初始化图 graph = StateGraph(AgentState) ``` --- ### 三、具体实现模块代码示例 #### 模块1:规划器(Planner)实现 **功能**:将用户目标分解为可执行步骤 ```python from langchain.chains import LLMChain from langchain.prompts import ChatPromptTemplate # 规划提示模板 PLANNER_PROMPT = ChatPromptTemplate.from_template(""" 目标:{input} 已知工具:{tools} 请生成JSON格式的步骤列表,包含'step'和'tool'字段: """) # 规划节点函数 def planner_node(state: AgentState): tools = ["搜索", "计算器", "数据库查询"] chain = PLANNER_PROMPT | model.bind(response_format={"type": "json_object"}) plan = chain.invoke({"input": state["input"], "tools": tools}) return {"plan": plan} # 将规划节点加入图 graph.add_node("planner", planner_node) ``` #### 模块2:推理器(Reasoner)实现 **功能**:动态调整规划并处理异常 ```python def reasoner_node(state: AgentState): current_step = state["plan"].pop(0) context = f"当前步骤:{current_step}\n历史记录:{state['reasoning_log']}" # 使用ReAct模式推理 react_prompt = """分析当前步骤可行性: - 所需资源是否满足? - 是否存在冲突? 最后返回'proceed'或'update_plan'""" decision = model.invoke(context + react_prompt) if "update_plan" in decision: # 触发规划重生成 new_plan = planner_node(state) return {"plan": new_plan["plan"], "reasoning_log": state["reasoning_log"] + [decision]} else: return {"reasoning_log": state["reasoning_log"] + [decision]} graph.add_node("reasoner", reasoner_node) ``` #### 模块3:执行器(Executor)实现 **功能**:调用具体工具执行规划步骤 ```python from langchain.tools import Tool tools = [ Tool(name="搜索", func=web_search), Tool(name="计算器", func=math_calculator) ] def executor_node(state: AgentState): current_step = state["plan"][0] tool = next(t for t in tools if t.name == current_step["tool"]) result = tool.run(current_step["params"]) return { "plan": state["plan"][1:], "result": state.get("result", []) + [result] } graph.add_node("executor", executor_node) ``` --- ### 四、完整工作流组装 #### 1. 定义状态转移逻辑 ```python # 初始路径:规划 → 推理 → 执行 graph.add_edge("planner", "reasoner") graph.add_edge("reasoner", "executor") # 循环执行直到计划完成 graph.add_conditional_edges( "executor", lambda state: END if len(state["plan"]) == 0 else "reasoner", {True: END, False: "reasoner"} ) # 设置入口点 graph.set_entry_point("planner") ``` #### 2. 编译并运行 ```python app = graph.compile() result = app.invoke({ "input": "预测明年Q1的销售额,需考虑市场增长率", "reasoning_log": [], "plan": [] }) print(result["result"]) # 输出最终执行结果 ``` --- ### 五、关键LangChain/LangGraph接口解析 | **组件** | **类/方法** | **在推理/规划中的作用** | |--------------------|---------------------------|--------------------------------------| | 状态管理 | `StateGraph` | 维护规划执行上下文 | | 条件分支 | `add_conditional_edges()` | 实现推理触发的动态路径调整 | | 工具集成 | `Tool`+ `@tool`装饰器 | 将API、函数等封装为规划原子操作 | | 流控制 | `RunnableBranch` | 根据推理结果选择后续节点 | | 记忆机制 | `BaseMemory` | 存储历史推理日志用于反思优化 | --- ### 六、典型应用场景示例(电商客服) #### 1. 规划阶段 ```json // LangGraph生成的规划输出 { "plan": [ {"step": "验证用户身份", "tool": "数据库查询"}, {"step": "检索订单历史", "tool": "搜索"}, {"step": "计算退货期限", "tool": "计算器"} ] } ``` #### 2. 推理阶段 ```python # 当检测到用户情绪负面时的推理调整 def emotional_reasoning(state): sentiment = analyze_sentiment(state["input"]) if sentiment < 0.3: return {"plan": insert_step(state["plan"], "安抚用户情绪", index=0)} graph.add_node("emotional_check", emotional_reasoning) ``` --- ### 七、性能优化技巧 1. **规划缓存**:对常见目标预生成规划模板 ```python from langchain.cache import SQLiteCache import hashlib def cached_planner(state): key = hashlib.sha256(state["input"].encode()).hexdigest() if key in cache: return cache[key] else: plan = planner_node(state) cache[key] = plan return plan ``` 2. **并行推理**:利用LangGraph的异步支持 ```python async def async_reasoner(state): await asyncio.gather( check_resources(state), validate_dependencies(state) ) ``` --- ### 总结 通过**LangGraph**的有状态图编排**LangChain**的模块化工具集成,开发者可以高效构建包含推理规划能力的智能体系统。关键设计模式包括: - 使用**StateGraph**维护规划上下文 - 通过**条件边**实现动态推理跳转 - 将**LLMChain**封装为专用推理节点 - 利用**Tool**抽象化规划动作单元 最新实践表明,结合LangChain Expression Language(LCEL)可进一步提升复杂规划流程的可维护性。开发者应根据具体场景在规划精度(符号方法)灵活性(神经网络方法)之间权衡选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

alpha xu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值