ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Agent学习之二 LLM 基础 API 调用实战:从零开始使用 Ollama 本地模型对接 TaoToken

Agent学习之二 LLM 基础 API 调用实战:从零开始使用 Ollama 本地模型对接 TaoToken 1. 本地 Ollama 模型接入 TaoToken 统一 Key 通道实战Agent 开发者的 LLM 基础 API 调用很多人在学 Agent 开发时都会卡在同一个地方本地 Ollama 跑得好好的云端模型也各有各的 Key写着写着代码里全是if model xxx的分支判断。我试过最省事的做法是把本地 Ollama 和云端模型都收敛到同一个 OpenAI 兼容入口用一套 Base URL 一个 Key 管理所有调用。这篇就聚焦这件事本地 Ollama 模型通过 OpenAI 兼容接口接入 TaoToken 统一 Key/API 通道从环境变量到 curl 验证再到 Python 调用全部给可复制的片段。先说清楚这套方案能做什么。Ollama 本身在11434端口暴露了一个 OpenAI 兼容的/v1接口TaoToken 提供统一的 API 通道https://taotoken.net/api两者都是 OpenAI 协议。这意味着你可以在 Agent 代码里只维护一个 client通过切换base_url和model就能在本地小模型和云端大模型之间来回切。适合谁正在写 Agent、需要频繁对比本地与云端模型效果、又不想在代码里堆一堆 SDK 的开发者。核心检索词先摆出来Ollama 本地模型接入、OpenAI 兼容接口、TaoToken 统一 Key、Agent LLM API 调用。这四个词贯穿全文你按这个思路读下去就能落地。环境准备不复杂。Ollama 装好后确认服务在跑ollama list能看到你拉下来的模型比如qwen2.5:3b、llama3.2:3b。TaoToken 这边去控制台拿一个 API Key模型 ID 用文档里列出的名称。两边的 Base URL 分别是http://localhost:11434/v1和https://taotoken.net/api。注意后者不带任何多余路径OpenAI SDK 会自动拼/v1/chat/completions。这里有个容易踩的坑Ollama 的 OpenAI 兼容层对api_key不做校验你填ollama或者任意字符串都能过但 TaoToken 这边 Key 是真实校验的401 基本就是 Key 错了或者没带Bearer前缀。所以统一 client 的时候本地和云端的 Key 要分开传不能图省事共用一个。下面进入具体配置。我会先给 TaoToken 的前置准备再给可复制的配置片段然后是 curl 和 Python 两套验证最后把常见报错逐个拆开。2. TaoToken 前置准备与 Ollama 环境变量配置统一 Base URL 与 API Key 管理这一节解决的是通道问题。你要让本地 Ollama 和云端模型走同一套调用逻辑前提是两边的接入信息都准备好并且用环境变量管理别硬编码在代码里。TaoToken 这边先去控制台创建 API Key。地址是https://taotoken.net/console登录后在 API Keys 页面新建一个复制出来形如sk-xxxxxxxx。模型 ID 在文档页https://taotoken.net/doc能查到常见的有gpt-4o-mini、claude-haiku-4-5这类。Base URL 固定用https://taotoken.net/api不要自己加/v1SDK 会处理。Ollama 这边默认监听127.0.0.1:11434。如果你希望局域网内其他机器也能调需要设置OLLAMA_HOST0.0.0.0:11434。Windows 下在系统环境变量里加macOS/Linux 下写进 shell 配置。改完重启 Ollama 服务生效。环境变量建议这样组织本地和云端分开命名避免混淆# 本地 Ollama export OLLAMA_BASE_URLhttp://localhost:11434/v1 export OLLAMA_API_KEYollama # TaoToken 统一通道 export TAOTOKEN_BASE_URLhttps://taotoken.net/api export TAOTOKEN_API_KEYsk-你的真实KeyWindows PowerShell 里对应的是$env:TAOTOKEN_API_KEYsk-xxx写进用户环境变量更持久。这里的关键点是两个 Base URL 都是 OpenAI 兼容的所以后面 Python 代码里可以用同一个OpenAI类只是实例化两次。为什么不用一个 client 搞定因为api_key不同。Ollama 不校验TaoToken 校验。如果你把 TaoToken 的 Key 传给本地 Ollama本地照样能跑但反过来把ollama传给 TaoToken 就会 401。所以老老实实建两个 client或者写一个工厂函数按provider返回对应 client。还有一个细节Ollama 的 OpenAI 兼容层对extra_body里的thinking参数支持不稳定。如果你用的是推理模型比如带 reasoning 输出的thinking: False不一定能完全关掉推理过程输出里可能混着reasoning字段。这个后面排障章节会细说。配置片段给一个.env风格的方便你直接复制# .env OLLAMA_BASE_URLhttp://localhost:11434/v1 OLLAMA_API_KEYollama TAOTOKEN_BASE_URLhttps://taotoken.net/api TAOTOKEN_API_KEYsk-替换成你的Key TAOTOKEN_MODELgpt-4o-mini OLLAMA_MODELqwen2.5:3b用python-dotenv加载或者直接export。这样你的 Agent 代码里读环境变量就行换机器、换 Key 都不用改代码。前置准备到这就够了。接下来给可复制的配置片段包括 JSON 和 Python 两种形式确保路径和原文一致。3. 可复制配置片段JSON 与 Python 双份 settings 直接落地这一节给的是能直接粘贴运行的配置。我按配置文件 代码初始化两块来你按需取用。先给一份 JSON 配置适合放在项目根目录当llm_config.json{ providers: { ollama_local: { base_url: http://localhost:11434/v1, api_key: ollama, default_model: qwen2.5:3b }, taotoken: { base_url: https://taotoken.net/api, api_key: sk-替换成你的Key, default_model: gpt-4o-mini } }, default_provider: ollama_local }这份 JSON 的好处是你的 Agent 代码可以按provider名字取配置切换模型只改default_provider一个字段。注意api_key这里我写了占位符实际项目里建议从环境变量注入别把真实 Key 提交到 Git。再给 Python 侧的初始化代码用工厂模式返回 clientimport os from openai import OpenAI def get_client(provider: str ollama_local) - OpenAI: if provider ollama_local: return OpenAI( base_urlos.environ.get(OLLAMA_BASE_URL, http://localhost:11434/v1), api_keyos.environ.get(OLLAMA_API_KEY, ollama), ) elif provider taotoken: return OpenAI( base_urlos.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api), api_keyos.environ[TAOTOKEN_API_KEY], ) raise ValueError(f未知 provider: {provider}) def get_model(provider: str ollama_local) - str: if provider ollama_local: return os.environ.get(OLLAMA_MODEL, qwen2.5:3b) return os.environ.get(TAOTOKEN_MODEL, gpt-4o-mini)这段代码的关键点base_url和api_key都从环境变量读get_model单独抽出来因为同一个 provider 下你可能想换不同模型。这样你的 Agent 主逻辑里只需要client get_client(taotoken) model get_model(taotoken) resp client.chat.completions.create( modelmodel, messages[{role: user, content: 你好}], )如果你用 Cline 或者 Claude Code 这类工具配置项对应的是三件套Base URL、API Key、Model ID。以 Cline 的 MCP 配置为例写进settings.json的片段是{ mcpServers: { taotoken: { command: npx, args: [-y, taotoken/mcp-server], env: { TAOTOKEN_BASE_URL: https://taotoken.net/api, TAOTOKEN_API_KEY: sk-替换成你的Key, TAOTOKEN_MODEL: gpt-4o-mini } } } }注意这里三件套齐全Base URL 是https://taotoken.net/apiKey 是sk-开头Model ID 是gpt-4o-mini。少任何一个都会连不上。Codex 的auth.json同理字段名可能是base_url、api_key、model按工具文档填。配置片段到这就齐了。接下来验证请求先 curl 再 Python确保通道真的通。4. 验证请求curl 与 Python 调用 Ollama 和 TaoToken 的成功返回验证分两步走。先 curl 本地 Ollama确认 OpenAI 兼容层正常再 curl TaoToken确认 Key 和通道没问题最后用 Python 跑一遍完整调用。先看本地 Ollama 的 curlcurl http://localhost:11434/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer ollama \ -d { model: qwen2.5:3b, messages: [{role: user, content: 用一句话介绍你自己}], max_tokens: 100 }预期返回是一个标准 OpenAI 格式的 JSONchoices[0].message.content里有模型回复usage里有prompt_tokens和completion_tokens。如果返回Connection refused说明 Ollama 没跑先ollama serve。如果返回 404检查路径是不是/v1/chat/completions别漏了/v1。再看 TaoToken 的 curlcurl https://taotoken.net/api/v1/chat/completions \ -H Content-Type: application/json \ -H Authorization: Bearer sk-你的Key \ -d { model: gpt-4o-mini, messages: [{role: user, content: 用一句话介绍你自己}], max_tokens: 100 }注意这里路径是https://taotoken.net/api/v1/chat/completions因为 curl 不会自动补/v1而 OpenAI SDK 会。这是很多人第一次调 TaoToken 时踩的坑用 SDK 时 Base URL 写https://taotoken.net/api用 curl 时要手动加/v1。返回 200 且choices有内容就说明通道通了。返回 401 就是 Key 问题检查有没有Bearer前缀、Key 有没有复制全。Python 验证代码两个 provider 都跑一遍import os from openai import OpenAI def call(provider: str, base_url: str, api_key: str, model: str): client OpenAI(base_urlbase_url, api_keyapi_key) resp client.chat.completions.create( modelmodel, max_tokens100, messages[{role: user, content: 用一句话介绍你自己}], ) text resp.choices[0].message.content print(f[{provider}] {text}) print(f[{provider}] usage: {resp.usage}) return resp # 本地 Ollama call( ollama_local, os.environ.get(OLLAMA_BASE_URL, http://localhost:11434/v1), os.environ.get(OLLAMA_API_KEY, ollama), os.environ.get(OLLAMA_MODEL, qwen2.5:3b), ) # TaoToken call( taotoken, os.environ.get(TAOTOKEN_BASE_URL, https://taotoken.net/api), os.environ[TAOTOKEN_API_KEY], os.environ.get(TAOTOKEN_MODEL, gpt-4o-mini), )跑通后你会看到两行输出本地模型和云端模型各回一句。usage字段里能看到 token 消耗本地是 0 成本云端按量计费。这一步成功意味着你的 Agent 代码可以放心用统一 client 了。有个细节Ollama 的usage字段在某些版本里可能缺失或者为 0这是兼容层的实现差异不影响调用。如果你需要精确统计本地 token得用 Ollama 原生 API 的/api/generate端点那个返回里有prompt_eval_count和eval_count。验证通过后把这段代码封装成你 Agent 的llm_client.py后面所有调用都走它。5. 常见报错排查401、local proxy failed、reading choices、OAuth 逐个拆解这一节按真实报错来。我把接入过程中最容易撞上的四类错误列出来每个给现象、原因、解法。第一类401 Unauthorized。现象是调用 TaoToken 返回{error: {message: Invalid API key, type: invalid_request_error}}。原因通常是三个Key 没带Bearer前缀、Key 复制时漏了字符、Key 已经过期或被删。解法是重新去控制台复制确认 curl 里Authorization: Bearer sk-xxx格式正确。如果你用 SDK检查api_key参数有没有传对别把ollama传给了 TaoToken 的 client。第二类local proxy failed。这个报错通常出现在你用了某个本地代理工具或者环境变量里设了HTTP_PROXY/HTTPS_PROXY导致请求被劫持到一个不存在的本地端口。现象是APIConnectionError: Connection error或者local proxy failed。解法是检查环境变量临时清掉unset HTTP_PROXY unset HTTPS_PROXY unset ALL_PROXY然后重试。如果你确实需要走代理确保代理地址和端口正确别指向一个没启动的服务。注意这里说的是正常的网络代理配置不是让你去搞什么特殊通道纯粹是排查环境变量污染。第三类reading choices 相关报错。典型信息是KeyError: choices或者TypeError: NoneType object is not subscriptable发生在你访问resp.choices[0]的时候。原因是返回体里根本没有choices字段通常是上游返回了错误 JSON但 SDK 没抛异常。解法是先打印原始返回resp client.chat.completions.create(...) print(resp.model_dump())看model_dump()里有没有error字段。如果有按错误信息处理。常见的是模型 ID 写错了比如把qwen2.5:3b写成了qwen2.5-3bOllama 会返回错误但格式不标准。另一个原因是max_tokens设得太大超过了模型上下文也会导致异常返回。第四类OAuth 相关报错。如果你用 Claude Code 或者某些 CLI 工具可能会看到OAuth token expired或者invalid_grant。这类工具默认走 OAuth 流程但接入 TaoToken 时应该用 API Key 模式。解法是在工具的配置里关掉 OAuth改用api_key字段。以 Claude Code 为例配置里指定ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY别让它走默认的 OAuth 登录流程。三件套还是那三个Base URL 填https://taotoken.net/apiKey 填sk-xxxModel ID 填你选的模型。再补一个 Ollama 特有的model requires more system memory。这是本地显存/内存不够换个更小的模型比如从qwen2.5:7b降到qwen2.5:3b。或者调小max_tokens减少 KV cache 占用。排查顺序建议先 curl 确认通道通再 Python 确认 SDK 通最后接工具确认配置通。每一步都单独验证别一上来就全套跑出错不好定位。6. 从本地到云端用 TaoToken 统一管理 Agent 的 LLM 调用通道走到这里你的 Agent 应该已经能用一套 client 同时调本地 Ollama 和云端模型了。最后说说怎么把这套东西用顺。核心思路是配置驱动。你的 Agent 代码里不出现任何硬编码的 URL 和 Key全部从配置读。切换模型时只改配置不改代码。这样你在做模型对比、A/B 测试、成本优化的时候效率会高很多。具体做法把第 3 节的get_client和get_model封装成一个LLMFactory类Agent 初始化时传入 provider 名字后面所有调用都走这个工厂。如果你要跑批量任务可以写一个循环遍历 provider 列表每个 provider 跑一遍同样的 prompt收集结果对比。TaoToken 这边的价值在于统一入口。你不需要为每个云端模型单独申请 Key、单独记 Base URL。一个 Key 走所有模型模型 ID 作为参数传。这对 Agent 开发特别友好因为 Agent 经常需要根据任务难度动态选模型简单任务用本地小模型省成本复杂任务切云端大模型保质量。如果你要长期跑编码类 Agent可以看看 Coding Plan地址是https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentcoding_plan。它适合需要持续调用、对稳定性有要求的场景。验证模型效果的时候可以直接用模型对话页面快速试https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentmodel_chat。不用写代码就能对比不同模型的回复风格。接入文档在https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentdoc里面有完整的模型列表和参数说明。API Key 管理在https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentapi_keys可以创建多个 Key 做权限隔离。最后给一个实用技巧在 Agent 里加一个 fallback 逻辑。当云端调用失败超时、限流、401时自动降级到本地 Ollama。这样你的 Agent 不会因为网络波动直接挂掉。代码大概长这样def call_with_fallback(prompt: str) - str: try: client get_client(taotoken) resp client.chat.completions.create( modelget_model(taotoken), messages[{role: user, content: prompt}], max_tokens500, ) return resp.choices[0].message.content except Exception as e: print(f云端调用失败: {e}降级到本地) client get_client(ollama_local) resp client.chat.completions.create( modelget_model(ollama_local), messages[{role: user, content: prompt}], max_tokens500, ) return resp.choices[0].message.content这段代码实测下来很稳本地 Ollama 作为兜底云端作为主力。你按这个结构搭Agent 的 LLM 调用层就基本成型了。
返回列表