引言:为什么要本地运行 LLM?
随着 Llama 3、Mistral 和 Qwen 等开源模型越来越强,很多开发者开始寻找替代 OpenAI API 的方案。本地运行 LLM 不仅完全免费,还能保护数据隐私,且不受速率限制(Rate Limit)。
而在本地运行方案中,Ollama 凭借其极致的易用性成为了事实上的标准。
今天,我们将深入探讨如何将 Ollama 接入目前最强大的两个编排框架:LangChain(用于构建基础应用)和 LangGraph(用于构建复杂的 Stateful Agent)。
🚀 准备工作
在开始写代码之前,我们需要确保环境就绪。
安装 Ollama: 前往 Ollama 官网 下载安装包。安装完成后,在终端拉取一个模型(以 Llama 3 为例):
ollama pull llama3
确保终端能运行 ollama list 并看到模型。
安装 Python 依赖: 我们将使用 LangChain 官方最新的集成库
langchain-ollama(比旧版的 community 库更稳定):pip install langchain-ollama langgraph
第一部分:LangChain 基础配置
在 LangChain 中,核心组件是 ChatOllama。它适配了标准的 Chat Model 接口,支持 System/User 消息格式。
1. 基础对话与流式输出
本地模型相比云端 API,速度可能会稍慢,因此流式输出 (Streaming) 对于用户体验至关重要。
from langchain_ollama import ChatOllama
from langchain_core.messages import HumanMessage, SystemMessage
# 初始化模型
# base_url 默认是 localhost:11434,Docker 用户需注意修改
llm = ChatOllama(
model="llama3",
temperature=0,
)
print("--- 基础调用 ---")
messages = [
SystemMessage(content="你是一个精通 Python 的技术专家。"),
HumanMessage(content="用一句话解释什么是递归。")
]
print(llm.invoke(messages).content)
print("\n--- 流式输出 (提升体验) ---")
for chunk in llm.stream("写一个快速排序的 Python 函数"):
print(chunk.content, end="", flush=True)2. 配置嵌入模型 (Embeddings)
如果你在做 RAG(知识库问答),千万不要用 llama3 做嵌入,效果不好且慢。推荐使用专门的嵌入模型,如 nomic-embed-text。
ollama pull nomic-embed-textfrom langchain_ollama import OllamaEmbeddings
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vector = embeddings.embed_query("LangChain 是一个很棒的框架")
print(f"向量生成成功,维度: {len(vector)}")第二部分:LangGraph 进阶配置
LangGraph 的核心是图(Graph)和状态(State)。我们需要将 Ollama 封装在图的节点(Node)中。
实战:构建一个带有记忆的本地聊天机器人
这个例子展示了如何让 Ollama 记住上下文。
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_ollama import ChatOllama
from langchain_core.messages import BaseMessage
# 1. 定义状态:使用 add_messages 自动追加历史记录
class State(TypedDict):
messages: Annotated[list[BaseMessage], add_messages]
# 2. 初始化模型
llm = ChatOllama(model="llama3", temperature=0.5)
# 3. 定义节点函数
def chatbot_node(state: State):
return {"messages": [llm.invoke(state["messages"])]}
# 4. 编排图结构
workflow = StateGraph(State)
workflow.add_node("chatbot", chatbot_node) # 添加节点
workflow.add_edge(START, "chatbot") # 起点 -> 聊天
workflow.add_edge("chatbot", END) # 聊天 -> 结束
app = workflow.compile()
# 5. 运行(带记忆功能的配置)
config = {"configurable": {"thread_id": "user_001"}}
# 第一轮
print(app.invoke({"messages": [("user", "你好,我叫 Alice")]}, config=config)["messages"][-1].content)
# 第二轮(测试它是否记得名字)
print(app.invoke({"messages": [("user", "我叫什么?")]}, config=config)["messages"][-1].content)第三部分:高阶技巧 —— Tool Calling (工具调用)
这是 LangGraph 区别于普通脚本的最强功能。注意:请务必使用 llama3.1 或更高版本,因为老版本对工具调用的支持较差。
from langchain_ollama import ChatOllama
from langchain_core.tools import tool
# 1. 定义工具
@tool
def get_stock_price(symbol: str):
"""查询股票价格"""
if symbol == "AAPL": return "150.00"
return "未知"
# 2. 绑定工具 (Bind Tools)
# 这一步让模型“知道”它可以调用哪些函数
llm = ChatOllama(model="llama3.1")
llm_with_tools = llm.bind_tools([get_stock_price])
# 3. 测试
query = "苹果公司的股价是多少?"
response = llm_with_tools.invoke(query)
if response.tool_calls:
print(f"🎉 模型成功决定调用工具: {response.tool_calls}")
# 输出示例: [{'name': 'get_stock_price', 'args': {'symbol': 'AAPL'}...}]
else:
print("模型未调用工具")⚠️ 避坑指南 (Common Pitfalls)
在配置过程中,你可能会遇到以下问题,这里有解决方案:
Docker 连接报错: 如果你在 Docker 容器中运行 LangChain,而 Ollama 跑在宿主机上,代码里的
localhost是通不的。- 解决: 设置
base_url="http://host.docker.internal:11434"。
- 解决: 设置
长文档报错 (Context Window): Ollama 默认上下文窗口通常是 2048 或 4096 token。如果你做长文档分析,模型会“失忆”或报错。
解决: 初始化时显式增加窗口大小:
ChatOllama(model="llama3", num_ctx=8192) # 扩大到 8k
工具调用失败: 模型总是直接回复文本,而不调用工具。
- 解决: 确认模型版本是
llama3.1(8b/70b)、mistral或qwen2.5。普通的llama3不支持 Native Tool Calling。
- 解决: 确认模型版本是
结语
通过 langchain-ollama 和 langgraph,我们已经在本地搭建起了一套不输于商业 API 的开发环境。
- ChatOllama 帮你解决了最基础的对话和推理。
- LangGraph 帮你管理了复杂的对话状态和记忆。
- Ollama 帮你省去了昂贵的 API 账单。
现在,你可以尝试将你的 RAG 应用或智能助理完全迁移到本地运行了!🚀
版权属于:soarli
本文链接:https://blog.soarli.top/archives/785.html
转载时须注明出处及本声明。