Ollama: LangChain集成

LangChain 是 AI 应用的编排大师——模型是演员,Chain 是剧本,Agent 是导演。

💡 提示:LangChain 的核心是 Agent/Chain/Tool 三层架构——Chain 是固定流水线(Prompt→LLM→Parser),Tool 是可调用的外部能力(查询数据库、搜索文档),Agent 则是自主决策的调度器,动态选择调用哪些 Tool。90% 场景用 Chain 足够,需要动态决策时才用 Agent。

📋 前置知识:需要先掌握以下内容

1. 你将学到


2. 一个初创 CTO 的真实故事

(1) 痛点:每月手动分析 50 份指标报告

Alice 的 SaaS 公司有 50 个业务指标,每月需人工分析趋势并撰写报告。一个分析师花 3 天完成,且容易遗漏异常信号。

(2) 解法:LangChain Agent 自动分析

用 LangChain + Ollama 构建 AI Agent,自动读取指标数据、识别异常、生成分析报告:

PYTHON
from langchain_ollama import ChatOllama

llm = ChatOllama(model="qwen2.5", temperature=0.2)
result = llm.invoke("Analyze the 20% drop in MRR last month")

3. LangChain + Ollama 连接

💡 提示: ChatOllamabase_url 参数默认指向 http://localhost:11434。若 Ollama 部署在其他主机或 Docker 容器中,需显式设置 base_url="http://ollama:11434" 等对应地址。

(1) 安装与初始化

BASH
pip install langchain langchain-ollama langchain-community

(2) 两大核心组件

组件 类名 用途
Chat Model ChatOllama 对话生成
Embeddings OllamaEmbeddings 文本向量化
100%
flowchart TD
    A[LangChain App] --> B[ChatOllama<br/>qwen2.5 / llama3.2]
    A --> C[OllamaEmbeddings<br/>nomic-embed-text]
    B --> D[Ollama Server<br/>localhost:11434]
    C --> D
ChatOllama 参数 类型 默认值 说明
model str 模型名称
temperature float 0.8 随机性
base_url str http://localhost:11434 服务地址
num_ctx int 2048 上下文窗口

▶ 示例 1: ChatOllama 基础调用

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, SystemMessage

# Initialize ChatOllama
llm = ChatOllama(model="qwen2.5", temperature=0.3)

# Simple invocation
response = llm.invoke("What is RAG?")
print(response.content)

# With system message
response = llm.invoke([
    SystemMessage(content="You are a data analyst. Be concise."),
    HumanMessage(content="What causes MRR to drop?")
])
print(response.content)

输出:

TEXT 📖 仅展示
# 执行成功

4. Prompt Template + Chain

(1) 链式提示工程

Prompt Template 让提示词可参数化、可复用、可组合:

100%
flowchart LR
    A[Input Variables] --> B[PromptTemplate]
    B --> C[ChatOllama]
    C --> D[Output Parser]
    D --> E[Structured Result]
Chain 类型 说明 适用场景
LLMChain Prompt → LLM → Output 单步推理
SequentialChain 多 Chain 串联 多步分析
RouterChain 根据输入路由 分流处理

▶ 示例 2: Prompt Template + Chain

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

llm = ChatOllama(model="qwen2.5", temperature=0.3)

# Define prompt template
prompt = ChatPromptTemplate.from_messages([
    ("system", "You are a {role}. Be concise and professional."),
    ("human", "{input}")
])

# Build chain: prompt -> llm -> parser
chain = prompt | llm | StrOutputParser()

# Invoke with variables
result = chain.invoke({
    "role": "customer service agent for e-commerce",
    "input": "Customer wants to cancel order #12345"
})
print(result)

输出:

TEXT 📖 仅展示
# 执行成功

5. Output Parser 结构化输出

⚠️ 警告: 小模型(3B 参数以下)生成 JSON 结构不稳定,PydanticOutputParser 可能频繁解析失败。建议使用 8B+ 模型配合 format="json" 参数,并在代码中加入 try/except 重试逻辑。

(1) 常用 Output Parser

Parser 用途 输出格式
StrOutputParser 纯文本 string
JsonOutputParser JSON 对象 dict
PydanticOutputParser Pydantic 模型 typed object
CommaSeparatedListOutputParser 逗号分隔列表 list[str]

(2) Pydantic 结构化输出对比

方式 优点 缺点
format=json 简单 无类型校验
JsonOutputParser 有 schema 提示 解析可能失败
PydanticOutputParser 完整类型校验 依赖模型遵循 schema

▶ 示例 3: Pydantic 结构化输出

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from pydantic import BaseModel, Field

# Define output schema
class CustomerIntent(BaseModel):
    intent: str = Field(description="Customer intent category")
    confidence: float = Field(description="Confidence score 0-1")
    order_number: str | None = Field(description="Order number if mentioned")

# Create parser
parser = PydanticOutputParser(pydantic_object=CustomerIntent)

# Build chain with format instructions
llm = ChatOllama(model="qwen2.5", temperature=0.1, format="json")
prompt = ChatPromptTemplate.from_messages([
    ("system", "Classify the customer intent.\n{format_instructions}"),
    ("human", "{query}")
])

chain = prompt | llm | parser

# Invoke
result = chain.invoke({
    "query": "I want to track my order #88765",
    "format_instructions": parser.get_format_instructions()
})
print(f"Intent: {result.intent}")
print(f"Confidence: {result.confidence}")
print(f"Order: {result.order_number}")

输出:

TEXT 📖 仅展示
# 执行成功

6. Tool-calling Agent

⚠️ 注意:Agent 可能产生不稳定输出——本地模型的推理循环可能出现"死循环"(反复调用同一工具)或"幻觉工具调用"(调用不存在的工具)。务必设置 max_iterations=3-5 限制循环次数,并用 temperature=0 提高确定性。3B 模型的 Agent 能力有限,建议 8B+。

💡 提示: Ollama 本地模型的 Function Calling 能力不如 GPT-4 稳定。推荐使用 ReAct Agent + @tool 装饰器模式替代原生 Function Calling,兼容性更好,且 temperature=0 可提高工具调用的确定性。

(1) Agent 架构

100%
flowchart TD
    A[User Input] --> B[Agent]
    B --> C{Need Tool?}
    C -->|Yes| D[Call Tool]
    D --> E[Tool Result]
    E --> B
    C -->|No| F[Final Answer]
Agent 类型 说明 适用场景
ReAct Agent 推理+行动循环 需调用工具的复杂任务
Structured Chat 结构化工具调用 多工具多参数
OpenAI Functions 函数调用模式 Ollama 部分支持

(2) 工具定义模式

定义方式 说明 示例
@tool 装饰器 简单工具 @tool def func(...)
StructuredTool 带描述工具 StructuredTool.from_function(...)
Pydantic + BaseTool 强类型工具 class MyTool(BaseTool)

▶ 示例 4: ReAct Agent 实战

PYTHON
from langchain_ollama import ChatOllama
from langchain_core.tools import tool
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate

# Define tools
@tool
def get_order_status(order_id: str) -> str:
    """Get the status of an order by its ID."""
    # Simulated database lookup
    orders = {
        "12345": "Shipped, arriving in 2 days",
        "88765": "Processing, shipping tomorrow",
        "99999": "Delivered on 2024-01-15"
    }
    return orders.get(order_id, f"Order {order_id} not found")

@tool
def check_product_stock(product_name: str) -> str:
    """Check if a product is in stock."""
    stock = {
        "wireless headphones": "In stock: 45 units",
        "laptop stand": "Out of stock, restock in 3 days",
        "usb cable": "In stock: 200 units"
    }
    return stock.get(product_name.lower(), f"Product '{product_name}' not found")

# Build agent
llm = ChatOllama(model="qwen2.5", temperature=0)
tools = [get_order_status, check_product_stock]

prompt = PromptTemplate.from_template(
    """Answer the following question. You have access to these tools:
{tools}

Use this format:
Question: the input question
Thought: what to do
Action: tool name (one of [{tool_names}])
Action Input: tool input
Observation: tool output
... (repeat Thought/Action/Action Input/Observation)
Thought: I know the final answer
Final Answer: the final answer

Question: {input}
{agent_scratchpad}"""
)

agent = create_react_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

# Run agent
result = agent_executor.invoke({
    "input": "What is the status of order 88765?"
})
print(result["output"])

输出:

TEXT 📖 仅展示
# 函数定义成功

7. 综合示例:Alice 的 SaaS 指标分析 Agent

ℹ️ 信息: LangChain 的 AgentExecutor 默认 max_iterations=15,但本地模型推理较慢,建议设为 3-5 防止无限循环。同时设置 verbose=True 便于观察 Agent 的推理过程。

PYTHON
# ============================================
# Comprehensive: SaaS metrics analysis agent
# Uses LangChain + Ollama for automated analysis
# ============================================

from langchain_ollama import ChatOllama
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain.agents import AgentExecutor, create_react_agent
from langchain_core.prompts import PromptTemplate
import json

# Simulated metrics database
METRICS_DB = {
    "mrr": {"current": 85000, "previous": 106250, "change": -20},
    "churn_rate": {"current": 8.5, "previous": 5.2, "change": 63},
    "arr": {"current": 1020000, "previous": 1275000, "change": -20},
    "active_users": {"current": 12500, "previous": 11800, "change": 6},
    "cac": {"current": 250, "previous": 180, "change": 39},
    "ltv": {"current": 2400, "previous": 3200, "change": -25}
}

@tool
def get_metric(metric_name: str) -> str:
    """Get a SaaS metric value. Available: mrr, churn_rate, arr, active_users, cac, ltv."""
    data = METRICS_DB.get(metric_name.lower())
    if data:
        return json.dumps(data)
    return f"Metric '{metric_name}' not found. Available: {list(METRICS_DB.keys())}"

@tool
def compare_metrics(metric1: str, metric2: str) -> str:
    """Compare two metrics and identify correlations."""
    m1 = METRICS_DB.get(metric1.lower())
    m2 = METRICS_DB.get(metric2.lower())
    if not m1 or not m2:
        return "One or both metrics not found."
    return json.dumps({
        "metric1": {"name": metric1, **m1},
        "metric2": {"name": metric2, **m2},
        "correlation_note": "Both metrics show negative trends"
    })

# Build analysis agent
llm = ChatOllama(model="qwen2.5", temperature=0.2)
tools = [get_metric, compare_metrics]

prompt = PromptTemplate.from_template(
    """You are a SaaS metrics analyst. Analyze data and provide insights.
Available tools: {tools}

Format:
Question: the input
Thought: what to do
Action: tool name from [{tool_names}]
Action Input: tool input
Observation: tool output
... (repeat as needed)
Thought: I have enough information
Final Answer: detailed analysis with actionable recommendations

Question: {input}
{agent_scratchpad}"""
)

agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True, max_iterations=5)

# Run analysis
if __name__ == "__main__":
    result = executor.invoke({
        "input": "MRR dropped 20% last month. Analyze the key metrics and identify likely causes with recommendations."
    })
    print("\n=== Analysis Report ===")
    print(result["output"])

❓ 常见问题

Q langchain-ollama 和 langchain-community 有什么区别?
A 是官方 Ollama 集成包,包含 ChatOllama 和 OllamaEmbeddings。 也包含旧版集成,但推荐用官方包。
Q Agent 的工具调用不稳定怎么办?
A 降低 temperature 到 0,确保工具描述清晰,使用 format=json 强制结构化输出。小模型(3B)Agent 能力有限,建议 8B+。
Q LangChain 的 Chain 和 Agent 怎么选?
A 固定流程用 Chain(Prompt → LLM → Parser),动态决策用 Agent(自主选择工具和步骤)。90% 场景 Chain 足够。
Q PydanticOutputParser 解析失败怎么办?
A 加 强制 JSON 输出。加 在 prompt 中明确格式。失败时回退到 JsonOutputParser。
Q Ollama 模型支持 Function Calling 吗?
A 部分支持。qwen2.5 和 llama3.1 有一定 Function Calling 能力,但不如 GPT-4 稳定。建议用 ReAct Agent + tool 装饰器替代。
Q 如何调试 Agent 的推理过程?
A 设置 查看 Agent 的 Thought/Action/Observation 循环。LangSmith( tracelangchain.com)可可视化完整执行链。

📖 小节


📝 作业

  1. 基础题(难度⭐):用 ChatOllama + PromptTemplate 构建一个 Chain,实现客服意图分类(输出 JSON 格式)。
  2. 进阶题(难度⭐⭐):创建一个带 2 个工具(查询订单 + 查库存)的 ReAct Agent,测试 3 个不同问题的工具调用。
  3. 挑战题(难度⭐⭐⭐):为 Alice 构建 SaaS 指标分析 Agent——包含至少 4 个工具(获取指标、对比指标、生成图表描述、发送告警),输出结构化分析报告。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏