尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
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 调用层就基本成型了。
RELATED

相关推荐

Claude Code Web开发工作流:把settings改到TaoToken的完整配置指南

Claude Code Web开发工作流:把settings改到TaoToken的完整配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/8 12:17:22
DB2 数据库性能参数优化笔记:从监控指标到配置调优的完整整理

DB2 数据库性能参数优化笔记:从监控指标到配置调优的完整整理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/10/8 12:17:22
wp-calypso 国际化构建基石:babel-plugin-i18n-calypso 提取 translate 调用生成 POT 全解析

wp-calypso 国际化构建基石:babel-plugin-i18n-calypso 提取 translate 调用生成 POT 全解析

前端CMS 【免费下载链接】wp-calypso The JavaScript and API powered WordPress.com 项目地址: https://gitcode.com/gh_mirrors/wp/wp-calypso 点击查看 免费下载 本文围绕 packages/babel-plugin-i18n-calypso/README.md 展开,深入剖析这个 Babel 插…

📅 2026/10/8 12:17:22
MORE NEWS

更多资讯

📰

一维差分数组算法模板:从区间加原理到边界避坑与二维扩展

一维差分算法模板这个关键词,我估计很多刷题人都不是第一次见。我当年第一次遇到它,是在一道“区间加”的题上卡了整整一下午:数组长度十万,操作次数十万,老老实实写了两层循环,样例全对,一提交…

📰

Python驱动睿尔曼仿人机械臂:医疗工作站抓取与视觉引导实战

写这篇内容之前,我翻了翻最近调试记录里的一些笔记。睿尔曼超轻量仿人机械臂、医疗工作站、Python Demo,这三个词放一起,拆开看每个都不新鲜,但组合起来就是一个挺典型的落地场景:用轻量协作臂在医疗工作台上做样本管抓…

📰

agedu磁盘分析工具实战:快照索引轻松揪出Linux大文件与空间占用

服务器磁盘又满了,这条告警短信我这半年已经收过不下十次。每次的剧情几乎一样:先df -h看到某个分区红了,再用du -sh一层层往里翻,运气好几分钟能定位到目标,运气不好遇到那种上百个嵌套目录、里面全是很零碎的大文件&…

📰

Hive查询重写优化实战:从慢SQL到19分钟收工的改造路径

先抛一个我踩过很多次的坑:生产环境里一段Hive SQL跑了一个多小时,任务失败率居高不下,集群报警一封接一封。运维兄弟第一反应是扩容、调参数、加队列,结果折腾一晚上,执行时间只从90分钟降到75分钟。后来我静下心把SQ…

📰

文件系统崩溃一致性:断电不损坏的底层逻辑与工程实践

“文件系统崩溃一致性”这七个字,第一次听到的人多半以为是“停电了文件还在不在”这种小学生问题。但真在存储或嵌入式领域待过几年,你就会明白,这是文件系统设计里最烧钱的工程问题之一。我见过太多项目,功能跑得好好的&#xf…

📰

三十岁运维转行网安:十个月学习路线与实战经验分享

三十岁那年的春节,我人在机房,窗外烟花正浓,面前是密密麻麻的告警。那一夜我处理了三起故障:一台数据库服务器磁盘写满,一套业务系统进程假死,还有一个开发环境因为某些兼容问题起不来。每一步操作都和五年…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬