使用 Ollama 在本地运行相同的 OpenAI 聊天循环
使用 Ollama 在本地运行相同的 OpenAI 聊天循环:将 OpenAI Python SDK 指向 localhost,保留原有代码即可。无需 API 密钥,无需支付令牌费用,数据也不会外传。
来源: Part 5 — Run the Same Loop on Ollama (no API key, OpenAI dialect)
与托管服务进行聊天会产生费用,而且每个请求都会传输到其他人的数据中心。使用 Ollama 在自己的机器上运行开源模型则可以避免这两点问题。最棒的是,现有的基于 OpenAI 的聊天代码依然可用,因为只有地址发生了变化。
相同接口,不同机器
Ollama 是一种本地模型服务器。安装完成后,只需下载一次模型,其权重就会像 Docker 镜像那样被下载。之后服务器会在 localhost:11434 端口监听 HTTP 请求。方便之处在于,Ollama 故意模仿了 OpenAI 的 Chat Completions API:相同的 /v1/chat/completions 接口路径、相同的带角色标签的消息列表、相同的包含 choices[0].message.content 的响应格式,以及相同的使用计数器。
因此,将 OpenAI 的聊天循环迁移过来并非重写代码,而只是更换了运行地址。好处显而易见:无需 API 密钥,没有按令牌计费的费用,数据也不会离开机器;作为交换,你可以获得自家硬件的处理速度以及开源模型的质量,而非那些处于前沿水平的模型。对于需要数百次迭代才能完成学习的场景而言,这无疑是个非常划算的选择。
设置与单次交互
从 ollama.com 下载 Ollama,它只需一步即可完成安装,并在后台运行服务器。接着,下载一个小型模型——约 2 GB 大小的 llama3.2 是个不错的默认选择。Python 端无需做任何改动,因为标准的 openai 包只需指向其他地址即可:
from openai import OpenAI
# Part 2's SDK, different address
client = OpenAI(
base_url="http://localhost:11434/v1",
api_key="ollama", # required, unused
)
resp = client.chat.completions.create(
model="llama3.2",
messages=[
{
"role": "system",
"content": "You are a concise "
"assistant.",
},
{
"role": "user",
"content": "Where are you running "
"right now?",
},
],
temperature=0,
)
print(resp.choices[0].message.content)
有两个设置值得注意。将base_url设置为localhost会将所有流量从OpenAI引导走。api_key="ollama"这个参数看似没有意义,但实际上并非如此:SDK拒绝在没有密钥的情况下创建客户端,而Ollama本身会忽略任何传入的内容,因此任何非空文本都可以使用。最后,model必须是你已经下载过的模型名称。这里没有可供选择的定价层级,只有存储在磁盘上的模型,这些模型信息会通过ollama list显示出来。
历史循环保持不变
判断“是否使用相同配置”的一个好方法,就是看之前的ask()函数是否无需任何修改就能直接在Ollama上运行。事实确实如此,只有用于创建客户端的代码有所不同。
一段简短的对话可以证明这一点,从系统消息开始,然后逐步展开:
msgs = [{
"role": "system",
"content": "You are a concise assistant.",
}]
def ask(text: str) -> str:
msgs.append(
{"role": "user", "content": text}
)
resp = client.chat.completions.create(
model="llama3.2",
messages=msgs, # full history
temperature=0,
)
reply = resp.choices[0].message.content
msgs.append({
"role": "assistant",
"content": reply,
})
return reply
print(ask("Define a context window."))
print(ask("Now for a five-year-old."))
print(ask("Which answer was shorter?"))
第三个问题依然体现了历史机制,从托管版本中学到的所有内容都会被保留。服务器在多次调用之间不会记住任何信息。不断增长的msgs列表正是导致后续响应变慢的原因。这里不会产生费用,但你确实要为每秒的使用时间付费,而看着本地模型随着历史数据的积累逐渐变慢,能让人们以一种账单永远无法做到的方式真切感受到上下文处理的成本。
请据此调整预期。参数量约为30亿的模型明显不如GPT-4o或Claude那么出色。它可能会偏离系统提示的内容,或者在回答“两者中哪个更短”之类的问题时出错。这并非循环中的故障,而是30亿参数所对应的性能表现,亲身体验这种差距比阅读测试数据更能让人有所领悟。
运行示例
三个命令即可完成。第一个用于安装模型,第二个用于安装Python依赖项,第三个用于运行脚本:
# one-time: install from ollama.com, then
ollama pull llama3.2
pip install -r requirements.txt
python examples/part05_ollama.py
首先,该脚本会检查 Ollama 服务器是否在 localhost:11434 上响应。如果没有响应,脚本会给出安装和拉取模型的说明后退出。这相当于在 API 密钥缺失时立即报错的本地版本。之后,脚本会执行单轮对话和三轮对话,并记录令牌使用情况,因为 Ollama 也在相同的字段中报告使用情况。此方式无需密钥,也不会产生费用。此外,它也不会被用于持续集成环境,原因与托管示例不同:持续集成环境并不运行模型服务器。
出现故障时
- “模型未找到”的错误表示相应的标签尚未被拉取,此时请运行
ollama pull llama3.2。 - 连接错误则表示服务器未运行,可使用
ollama serve启动它,不过桌面版安装会自动启动服务器。
为何本地端点更值得使用
智能体实验会不断重复进行。检索流程需要重新构建,推理循环会为同一个问题多次调用模型,每次进行细微的调试调整后图结构工作流也需重新运行。每次运行都按标记数计费的话费用会不断累积,而免费的本地端点则能让您在无需关注费用的情况下进行实验。由于Ollama使用的是OpenAI的模型格式,只需更换基础URL和模型名称,任何示例都可以在两种环境中运行,无需其他改动。这样一来就能获得无限标记数的测试环境。
下一个显而易见的主题是RAG。模型无法了解您的文档内容,因此关键问题就在于哪些标记应该被纳入上下文窗口。
相关阅读
- 无状态聊天循环:在 Python 中手动调用 OpenAI API — 通过自行管理消息历史来使用 OpenAI Python SDK 构建多轮对话,并了解为何同样的循环是 LangChain 内存机制与智能体的基础。
- Ollama 之后的本地 AI:2026 年的运行时选择 — 为何 Ollama 是理想的入门工具,却不适合作为长期控制平台——以及 llama.cpp、LM Studio、vLLM 等相关工具在各个发展阶段的应用场景。