Chroma-LangChain-Agent-完整问答实践案例

import os
from dotenv import load_dotenv
load_dotenv()
True
from langchain_core.documents import Document
from langchain.document_loaders import TextLoader, UnstructuredMarkdownLoader, PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.chat_models import ChatOpenAI
from langchain.chains import RetrievalQA
from langgraph.graph import StateGraph, END
import chromadb

全局配置 & 初始化

DOCS_PATH = "docs/"
CHROMA_COLLECTION_NAME = "doc_collection_1"
CHROMA_PERSIST_DIR = "data/"
CHROMA_SETTINGS = {
   
   
    "chroma_api_impl": "rest",
    "chroma_server_host": "localhost",
    "chroma_server_http_port": "8000",
}
# 初始化OpenAI Embeddings,使用text-embedding-ada-002
embeddings = OpenAIEmbeddings(model="text-embedding-ada-002")

# 初始化OpenAI大模型 GPT-4o-mini
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)

# 文档切片器
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=100)

一、构建函数

1. 加载文档(txt, md, pdf)

def load_documents(path: str):
    """
    加载指定目录下所有支持格式的文档(txt, md, pdf),
    并为每个文档添加文件名作为 metadata,方便后续追踪和操作。

    参数:
        path (str): 目标目录路径。

    返回:
        List[Document]: 加载的所有文档对象列表,每个文档包含文本内容及 metadata。
    """
    print(f"[1] 开始加载目录 {
     
     path} 下所有支持的文档...")
    
    docs = []  # 用于存储加载的所有文档对象
    
    # 遍历目录及子目录中的所有文件
    for root, _, files in os.walk(path):
        for f in files:
            filepath = os.path.join(root, f)  # 组成文件完整路径

            print("文件:",filepath)
            
            # 根据文件后缀选择对应的加载器
            if f.endswith(".txt"):
                loader = TextLoader(filepath, encoding="utf-8")  # 加载文本文件
            elif f.endswith(".md"):
                loader = UnstructuredMarkdownLoader(filepath)   # 加载Markdown文件
            elif f.endswith(".pdf"):
                loader = PyPDFLoader(filepath)                  # 加载PDF文件
            else:
                # 不支持的文件格式,跳过处理
                print(f"跳过不支持的文件格式: {
     
     f}")
                continue
            
            # 使用选定加载器加载文档,返回一个文档列表
            loaded_docs = loader.load()
            print(f"加载文件 {
     
     f
<think>我们被要求解释Langchain Chain、Langchain Agent和LangGraph之间的区别。根据引用内容,我们可以这样分析: 1. **Langchain Chain**:是LangChain中的基本构建块,用于将多个组件(如模型、提示、其他链)连接起来形成线性工作流。它按照预定义的顺序执行任务,适合确定性任务(如RAG流程)。引用[3]提到Router Chain是Chain的一种,用于根据输入将任务路由到不同的子链[^3]。 2. **Langchain Agent**:代理(Agent)是更高级的抽象,能够根据输入动态决定调用哪些工具(如搜索、计算、API等)。它通过循环的“思考-行动”过程处理复杂任务,但成本不可预测(引用[2])[^2]。Agent适合需要动态决策的场景。 3. **LangGraph**:是LangChain生态系统中的新成员,专注于构建有状态的、基于图的执行流程。它允许节点之间有任意连接,支持循环、分支和并行处理。引用[1]强调LangGraph完全集成到LangChain生态中,可利用LangSmith进行观测[^1]。引用[2]指出LangGraph在处理复杂状态(如多轮对话)时更灵活[^2]。 ### 核心区别总结: | **特性** | **LangChain Chain** | **LangChain Agent** | **LangGraph** | |------------------------|----------------------------|----------------------------|----------------------------| | **架构** | 线性顺序执行 | 代理循环(思考-行动) | 有状态图(节点+边) | | **决策能力** | 固定流程 | 动态选择工具 | 支持循环、分支、并行 | | **适用场景** | 确定性任务(如RAG) | 需要动态工具调用的任务 | 复杂状态管理(如多轮对话) | | **状态管理** | 无状态(每次执行独立) | 有状态(通过记忆机制) | 内置状态管理 | | **与LangChain集成** | 核心组件 | 核心组件 | 完全集成(LangSmith等)[^1]| | **复杂度** | 低(简单链)到中(组合链) | 中到高(依赖工具调用) | 高(需设计图结构) | ### 详细说明: 1. **LangChain Chain**: - 设计思想:通过组合预定义组件(如LLM调用、数据检索)形成**线性流程**。例如,一个典型的RAG链包括:检索文档 → 生成提示 → 调用LLM → 输出结果。 - 优势:执行高效、成本可控。 - 局限:缺乏灵活性,无法根据中间结果动态调整流程。 - 典型应用:引用[3]中的Router Chain,它根据输入将任务分配给不同的子链(如“数学问题”路由到数学链,“历史问题”路由到历史链)[^3]。 2. **LangChain Agent**: - 设计思想:代理通过**ReAct模式**(Reasoning and Acting)循环执行:解析输入 → 选择工具 → 执行工具 → 分析结果 → 决定下一步[^2]。 - 优势:动态适应复杂场景(如多工具协作)。 - 局限:工具调用次数不可预测,可能增加延迟和成本。 - 示例:用户查询“特斯拉老板的年龄”,代理可能先搜索“特斯拉老板是谁”,再搜索“埃隆·马斯克的年龄”。 3. **LangGraph**: - 设计思想:将工作流建模为**有向图**,节点代表操作(如调用LLM、工具),边定义状态流转逻辑。支持循环(如持续对话直到满足条件)和分支(如错误重试)[^1][^2]。 - 优势:处理**长期运行、有状态的任务**(如客服机器人)。 - 关键特性:状态(State)在节点间传递,可存储中间结果。 - 集成优势:无缝使用LangChain工具和LangSmith监控。 ### 何时选择? - **用Chain**:任务流程固定且无需动态决策(如文档摘要、翻译)。 - **用Agent**:需要动态调用外部工具(如实时搜索、API集成)。 - **用LangGraph**:任务涉及复杂状态流转(如多轮审批、游戏AI)或需要并行/重试逻辑[^2]。 ### 代码示例对比 #### LangChain Chain(线性RAG流程): ```python from langchain.chains import RetrievalQA from langchain_community.vectorstores import Chroma # 固定流程:检索 → 生成 qa_chain = RetrievalQA.from_chain_type( llm=ChatOpenAI(), retriever=Chroma.from_texts(["特斯拉老板是埃隆·马斯克"]).as_retriever() ) result = qa_chain.invoke("特斯拉老板是谁?") # 输出固定答案 ``` #### LangChain Agent(动态工具调用): ```python from langchain.agents import AgentExecutor, create_openai_tools_agent # 代理决定何时调用搜索工具 agent = create_openai_tools_agent(ChatOpenAI(), [TavilySearchTools()]) agent_executor = AgentExecutor(agent=agent, tools=tools) result = agent_executor.invoke("特斯拉老板的年龄?") # 可能调用两次搜索工具 ``` #### LangGraph(有状态对话): ```python from langgraph.graph import StateGraph # 定义状态和节点 class AgentState(TypedDict): input: str history: list[str] def llm_node(state: AgentState): return {"response": ChatOpenAI().invoke(state["input"])} # 构建图 → 支持循环 graph = StateGraph(AgentState) graph.add_node("llm", llm_node) graph.add_edge("llm", END) # 可添加条件分支 app = graph.compile() ``` --- ### 总结 - **Chain**:线性管道,高效处理确定性任务。 - **Agent**:动态代理,灵活调用工具解决开放性问题。 - **LangGraph**:图引擎,管理复杂状态和流程(如循环对话)[^1][^2]。 --- §§相关问题§§ 1. 如何根据任务复杂度选择Chain、Agent或LangGraph? 2. LangGraph在哪些场景下比传统Agent更有优势? 3. 如何将现有的LangChain Chain迁移到LangGraph? [^1]: Autogen 和 LangGraph 之间的另一个关键区别是 LangGraph 完全集成到 LangChain 生态系统中... [^2]: 一文彻底搞懂LangChain 和 LangGraph该怎么选?何时选?... [^3]: 【AI大模型学习路线】第三阶段之RAGLangChain——第十五章(LangChain与Chain组件)Router Chain详解...</think>### LangChain Chain、LangChain Agent 与 LangGraph 的区别详解 以下是三者的核心区别对比,基于引用内容整理: | **特性** | **LangChain Chain** | **LangChain Agent** | **LangGraph** | |-------------------------|----------------------------------------|----------------------------------------|----------------------------------------| | **架构核心** | 线性执行流程 | 动态工具调用循环 | 有状态图结构(节点+边) | | **决策机制** | 预定义顺序执行 | 基于LLM的实时工具选择 | 支持循环/分支/并行处理[^2] | | **状态管理** | 无状态(每次执行独立) | 有限状态(通过记忆机制) | 内置状态管理(跨节点传递) | | **适用场景** | 确定性任务(如RAG)[^3] | 动态工具调用(如搜索/计算) | 复杂工作流(如多轮对话/审批) | | **错误处理** | 简单异常捕获 | 有限重试逻辑 | 内置重试和错误路由[^2] | | **与LangChain集成** | 核心组件 | 核心组件 | 完全集成生态(含LangSmith)[^1] | | **典型组件** | `SequentialChain`, `RouterChain`[^3] | `ReAct Agent`, `OpenAI Functions` | 状态图(StateGraph) | --- ### 详细解析 #### 1. **LangChain Chain:线性执行引擎** - **设计思想**:通过预定义组件(LLM、工具、提示模板)构建**确定性工作流** - **核心特征**: - 固定执行顺序:`输入 → 组件A → 组件B → 输出` - 支持条件路由:如`RouterChain`根据输入选择子链[^3] - 适用场景: ```python # 示例:顺序链(文档摘要 → 翻译) chain = SequentialChain( chains=[summary_chain, translate_chain], input_variables=["document"] ) ``` - **局限**:无法动态调整流程,缺乏复杂状态管理 #### 2. **LangChain Agent:动态决策代理** - **设计思想**:基于LLM的**思考-行动循环**(ReAct模式) - **核心特征**: - 动态工具选择:根据输入实时调用工具(搜索/API/计算) - 记忆机制:维护短期对话历史 - 执行流程: ```mermaid graph LR A[用户输入] --> B{LLM决策} B -->|选择工具| C[工具执行] C --> D{是否完成?} D -->|否| B D -->|是| E[输出结果] ``` - **优势**:处理开放性问题(如“特斯拉老板的年龄?”需先查身份再查年龄) - **局限**:复杂状态处理困难,循环逻辑实现复杂[^2] #### 3. **LangGraph:图工作流引擎** - **设计思想**:**有向图结构**管理状态流转 - **核心突破**: - 节点(Node):执行单元(LLM/工具/条件判断) - 边(Edge):定义状态转移逻辑 - 状态(State):跨节点传递数据 - **关键能力**: - 循环处理:`聊天机器人`持续对话直到满足退出条件 - 并行执行:同时调用多个API - 错误重试:自动路由失败任务[^2] - **代码示例**: ```python from langgraph.graph import StateGraph class AgentState(TypedDict): user_query: str search_results: list # 构建图 graph = StateGraph(AgentState) graph.add_node("search", search_tool) graph.add_node("llm", llm_processor) graph.add_edge("search", "llm") # 搜索完成后转LLM处理 graph.set_entry_point("search") ``` --- ### 何时选择? | **场景** | **推荐方案** | **原因** | |---------------------------|---------------------|---------------------------------------| | 固定流程(如文档处理) | Chain | 高效且成本可控 | | 需动态工具调用 | Agent | 实时决策能力强大 | | 多轮对话/复杂审批流 | LangGraph | 状态管理和循环支持完善[^2] | | 需要LangSmith监控 | LangGraph | 深度集成可观测性工具[^1] | > 关键洞察:LangGraph不是替代Chain/Agent,而是**扩展**——它可封装Chain和Agent作为节点,构建更复杂的工作流[^2]。 --- ### 典型应用案例 1. **Chain**: - RAG流水线:`检索 → 生成 → 格式化输出`[^3] - 分类路由:`RouterChain`将数学问题/历史问题分发给专用链 2. **Agent**: - 实时数据分析:调用搜索引擎 + 计算工具 + 图表生成API - 客服机器人:根据问题类型选择知识库/订单系统工具 3. **LangGraph**: - 保险理赔系统: ``` 用户提交 → 文件审核 → (通过)支付 | (失败)转人工 → 通知用户 ``` - 多角色协作:销售Agent、技术Agent、审批Agent通过状态图协同[^2] ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值