如果你已经照着「本地化 MCP 网络设备巡检方案」搭好了 ask_ai.py、mcp_server.py 和 devices.json,却在最后一步被本地大模型卡住:ollama run deepseek-coder 拉到一半没速度,模型起来后 16GB 内存告急,那你真正要换的可能不是电脑,而是 ask_ai.py 里那一次 requests.post 的目标地址。TaoToken 统一 API 专门解决这一段的接入问题,官网是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 。先到官网注册并创建 API Key,然后回来把 ask_ai.py 的 URL 和鉴权头改掉;MCP 服务器和 netmiko 的设备巡检逻辑完全不用动。下面我会按“改动点 → 配置 → 验证 → 排障”的顺序,把这次切换完整拆开。
1. 本地 Ollama 卡住时,ask_ai.py 最需要改的是哪一行
1.1 原始链路回顾:一段自然语言怎么变成 MCP 请求
在原始方案里,ask_ai.py 扮演的是一个“翻译官”:它把你输入的“请帮我检查所有网络设备状态”打包进 prompt,发给本机的 Ollama。Ollama 上的 DeepSeek 读完 prompt 后返回一段 JSON,内容就是 MCP 请求,比如 {"method": "check_device_status", "params": {}}。然后你再把这个 JSON 交给 mcp_server.py 的 /mcp 接口,由 netmiko 去连设备执行巡检。
这段设计的好处是模型和巡检逻辑解耦:模型只负责把自然语言翻译成结构化指令,至于设备怎么连、命令怎么发、结果怎么解析,全在 mcp_server.py 里。但问题恰恰出在模型侧。DeepSeek 这类模型体积不小,单是拉取量化权重就要等很久;运行起来之后,CPU 或内存稍弱就会频繁交换内存,有时一个“请生成 JSON”的简单请求要等十几秒,还经常把 Ollama 进程直接挤到 OOM。最后形成一种很尴尬的状态:巡检链路本身是好的,但模型入口把整个流程拖住了。
1.2 改动点就一行:把模型请求从 localhost 切到统一 API
如果不想放弃这套 MCP 巡检框架,最省事的办法不是再换一个更小的本地模型,而是把 ask_ai.py 里 requests.post 的 URL 从 http://localhost:11434/api/generate 改成 TaoToken 的兼容接口 https://taotoken.net/api/chat/completions,同时补上鉴权头,并把响应解析从 response.json()["response"] 调整成 choices[0]["message"]["content"]。
mcp_server.py 里的 FastAPI 接口、netmiko 连接逻辑、devices.json 的格式都可以原样保留。你之前手工 curl 能通过的巡检接口,切换后依然能通过。相当于只换模型通道,不换设备巡检链路。需要接受的取舍是:自然语言转 JSON 这一步从纯本地变成了走云端统一 API,但设备清单和巡检结果仍然由你自己的脚本控制,发给 TaoToken 的只有问题和提示词,不包含 devices.json 里的设备密码。对绝大多数网络巡检场景来说,这个交换是值得的。
2. 准备材料:devices.json、Python 依赖和 API Key
2.1 Python 依赖和网络设备清单
需要一个 Python 3.10+ 环境,安装四样东西即可:fastapi、uvicorn、netmiko、requests。原始方案里的 mcp-client 在这个极简流程里不是必需的,所以这里不放它,避免装了一堆用不到的包。
pip install fastapi uvicorn netmiko requests
设备清单仍然放在 devices.json 中。下面这份保留华为设备示例,生产环境请把密码换成环境变量或密钥管理:
{
"devices": [
{
"ip": "192.168.1.1",
"device_type": "huawei",
"username": "admin",
"password": "Admin@123"
}
]
}
注意:devices.json 只被 mcp_server.py 读取,TaoToken 那边接收到的 prompt 里不包含这些设备信息。所以你不需要因为切换模型通道,就把设备账号密码跟着交出去。
如果你之前已经装了 Ollama,现在可以不启动它;如果还没装,也不建议为了这套方案再特意装一遍了,因为 ask_ai.py 改造完成后,本地不再需要常驻一个大模型进程。
2.2 到 TaoToken 创建 API Key
打开 TaoToken 注册并登录,在控制台创建一个 API Key。拿到的是形如 YOUR_API_KEY 的占位串,先保存在本地环境变量 TAOTOKEN_API_KEY 里。凡是填进代码或工具的 Base URL,一律使用 https://taotoken.net/api(后面不要加 /v1);官网落地页只用来注册、创建 Key、看模型广场和用量记录。
提示:官网落地页和接口 Base URL 是两回事。落地页给你操作账户和 Key,填进脚本的地址只有一个:https://taotoken.net/api。脚本里出现 YOUR_MODEL_ID 的地方,等第 4 节对照模型广场再填。
3. 巡检接口 mcp_server.py 保持不动,先单独验证设备连通性
3.1 FastAPI 巡检服务器
mcp_server.py 仍然是一个极简 FastAPI 服务,收到 POST /mcp 后根据 method 字段判断动作。这里补了一个 GET /health,方便你先确认服务本身活着:
import json
from fastapi import FastAPI
from netmiko import ConnectHandler
app = FastAPI()
with open("devices.json", encoding="utf-8") as f:
DEVICES = json.load(f)["devices"]
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/mcp")
async def handle_request(data: dict):
method = data.get("method")
if method != "check_device_status":
return {"error": f"unknown method: {method}"}
results = {}
for device in DEVICES:
try:
conn = ConnectHandler(
ip=device["ip"],
device_type=device["device_type"],
username=device["username"],
password=device["password"],
)
results[device["ip"]] = conn.send_command("display health")
conn.disconnect()
except Exception as exc:
results[device["ip"]] = f"error: {exc}"
return {"result": results}
相比原版,这里只加了健康检查、断开连接和未知方法提示,核心巡检逻辑完全不变。这样改是为了让后续排障更清晰:设备连不上时,你能在 mcp_server.py 这层就发现问题,而不是把锅甩给模型。
3.2 先用手工 curl 验证巡检链路
启动服务:
uvicorn mcp_server:app --reload --port 8000
再开一个终端,直接发一次巡检请求:
curl -X POST http://localhost:8000/mcp \
-H "Content-Type: application/json" \
-d '{"method":"check_device_status","params":{}}'
如果你能看到 Health Status 和 CPU、内存使用率,说明设备账号、网络、netmiko 驱动都是好的。这一步非常重要:如果手工 curl 都失败,后续模型怎么换都救不了巡检链路。等到 curl 能稳定返回,再继续改 ask_ai.py。切换模型通道的唯一目的,是把“生成这段 JSON”这件事交给云端模型,而不是替换掉你验证好的设备巡检路径。
4. ask_ai.py 改造:从 Ollama 格式切到统一 API 的 chat/completions
4.1 两种请求格式的差异
这是本次改造最核心的部分。本地 Ollama 的旧写法是 POST http://localhost:11434/api/generate,请求体用 model 和 prompt 两个字段,响应直接读 response.json()["response"]。TaoToken 是 OpenAI 兼容的调用方式,地址为 https://taotoken.net/api/chat/completions,请求体换成 model 和 messages,其中 messages 是 system/user 结构,鉴权通过请求头 Authorization: Bearer YOUR_API_KEY 完成,响应要读 choices[0]["message"]["content"]。
差异可以列成一张表:
| 字段或动作 | Ollama 本地 | TaoToken 统一 API |
|---|---|---|
| 完整请求地址 | http://localhost:11434/api/generate | https://taotoken.net/api/chat/completions |
| 鉴权方式 | 无 | Authorization: Bearer YOUR_API_KEY |
| 请求体结构 | model + prompt | model + messages(system/user) |
| 响应读取路径 | data["response"] | data["choices"][0]["message"]["content"] |
| 模型 ID 来源 | 本地 ollama pull/run 的模型名 | TaoToken 模型广场展示的 ID |
这里有一个容易踩的坑:本地 Ollama 用的模型名 deepseek-coder 只是你本地的名字,不能默认云端也叫这个 ID。模型 ID 必须以 TaoToken 模型广场展示的为准,否则请求会返回 model not found。
4.2 可运行的 ask_ai.py
下面的脚本把“自然语言转 MCP 请求”和“请求本地 MCP 服务器执行巡检”两件事合在了一起,方便你一条命令验证。如果你只想看 AI 生成的 JSON,把后半段 if mcp_request.get("method")... 注释掉即可。
import json
import os
import re
import requests
API_BASE = "https://taotoken.net/api" # 统一 API 入口,末尾不要加 /v1
API_KEY = os.getenv("TAOTOKEN_API_KEY", "YOUR_API_KEY")
MODEL_ID = os.getenv("TAOTOKEN_MODEL", "YOUR_MODEL_ID")
def extract_json(text: str) -> dict:
text = text.strip()
if text.startswith("```"):
text = re.sub(r"^```[a-zA-Z]*\n?", "", text)
text = re.sub(r"\n?```$", "", text)
return json.loads(text)
def ask_ai(question: str) -> dict:
prompt = (
f"用户说了:{question}。"
"请把它转换成调用 MCP 巡检网络设备状态的 JSON 请求,"
"设备信息已经在后台配好。只输出 JSON,不要解释。"
)
resp = requests.post(
f"{API_BASE}/chat/completions",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
},
json={
"model": MODEL_ID,
"messages": [
{"role": "system", "content": "你是网络设备巡检助手,只输出 JSON。"},
{"role": "user", "content": prompt},
],
"temperature": 0.2,
},
timeout=60,
)
resp.raise_for_status()
content = resp.json()["choices"][0]["message"]["content"]
return extract_json(content)
if __name__ == "__main__":
user_input = "请帮我检查所有网络设备状态"
mcp_request = ask_ai(user_input)
print("AI 生成的 MCP 请求:", mcp_request)
if mcp_request.get("method") == "check_device_status":
r = requests.post(
"http://localhost:8000/mcp",
json={
"method": mcp_request["method"],
"params": mcp_request.get("params", {}),
},
timeout=30,
)
print("设备巡检结果:", json.dumps(r.json(), ensure_ascii=False, indent=2))
注意:YOUR_API_KEY 是占位符,真实 Key 要到 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 的控制台创建;YOUR_MODEL_ID 也不是随便填,需要到 TaoToken 模型广场查看可选 DeepSeek 模型 ID 后替换。之前本地 Ollama 用的 deepseek-coder 只是你本地 pull 的名字,不能默认云端也有这个 ID。
4.3 环境变量如何设置
如果不想把 Key 写在代码里,运行前设置环境变量即可。Windows PowerShell 下是:
$env:TAOTOKEN_API_KEY="YOUR_API_KEY"
$env:TAOTOKEN_MODEL="YOUR_MODEL_ID"
macOS / Linux 下是:
export TAOTOKEN_API_KEY=YOUR_API_KEY
export TAOTOKEN_MODEL=YOUR_MODEL_ID
设置完之后直接运行 python ask_ai.py。代码里的 os.getenv("TAOTOKEN_API_KEY", "YOUR_API_KEY") 会优先读环境变量;如果你图省事,直接把文件里两处 YOUR_API_KEY、YOUR_MODEL_ID 替换成真实值也一样。但无论如何,不要把这个脚本推到公网 git 仓库,Key 一旦泄露就要立刻回控制台吊销重建。
5. 全流程测试:自然语言转 MCP JSON,curl 巡检照常返回设备状态
5.1 这次不需要再启动 Ollama
改造后的链路里,模型请求不再经过 localhost:11434,所以终端里不用再执行 ollama run deepseek-coder。你只需要保持两个进程:
uvicorn mcp_server:app --reload --port 8000
另一个终端:
python ask_ai.py
如果你的机器配置比较紧张,这样反而更轻松:Ollama 不再常驻内存,本地只剩 FastAPI 和 Python 脚本,16GB 内存的机器跑起来会宽裕很多。设备巡检仍然由 mcp_server.py 在本地发起,netmiko 照常往设备上发命令,这部分没有变成云端调用。
5.2 预期结果
ask_ai.py 会向 TaoToken 发起一次 chat/completions 请求,拿到 AI 生成的 MCP 指令后,紧接着请求本地 8000 端口的巡检服务。正常输出类似:
AI 生成的 MCP 请求: {'method': 'check_device_status', 'params': {}}
设备巡检结果: {
"result": {
"192.168.1.1": "Health Status: Normal\nCPU Usage: 15%\nMemory Usage: 30%"
}
}
第二段输出和你之前 curl mcp_server.py 拿到的结果应该完全一致。这正好说明:MCP 服务器和 netmiko 巡检逻辑原封不动,只是模型请求的通道变了。你可以多试几个自然语言问法,比如“只检查内存使用率”,看模型是否还会生成其他 method 或 params;如果模型跑偏,微调 system 提示词里的约束即可。
5.3 到 TaoToken 控制台核对用量
跑完之后,打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 登录控制台,查看本次调用是否被记录、消耗了多少 token。如果页面上能看到刚才那次 chat/completions 请求,说明 ask_ai.py 确实已经接入 TaoToken 统一 API;如果看不到记录,就到下一节排查。
6. 报错排查:401、404、模型 ID、设备连接
6.1 401 Unauthorized
最直接的原因是 Key 不对。检查 ask_ai.py 或环境变量里的 YOUR_API_KEY 是否被真实 Key 替换,注意不要带上引号或换行。有时候从网页复制 Key,末尾会多出一个空格,也会导致鉴权失败。另一个常见原因是 Key 复制了一半,建议回到 TaoToken 控制台重新创建或完整复制,不要把本地怀疑堆到脚本逻辑上。
6.2 404 或 model not found
404 通常有两个来源。第一个是 Base URL 写错:脚本里应该是 https://taotoken.net/api,再加 /chat/completions,不要在 api 后面补 /v1。第二个是模型 ID 不对:YOUR_MODEL_ID 必须和 TaoToken 模型广场展示的 ID 完全一致,本地 Ollama 的模型名不能直接搬过来。TaoToken 是统一接入通道,但每个模型 ID 仍然以控制台模型广场为准,没有统一的万能 ID。
6.3 AI 返回内容不是合法 JSON
TaoToken 返回的 content 有时会带着 markdown 代码块,比如开头有 ```json。ask_ai.py 里的 extract_json 会剥掉围栏再解析,但如果 AI 在 JSON 后面多加了说明文字,json.loads 还是会抛错。遇到这种情况,先把 temperature 调低到 0.2,再把 system 提示改成“只输出 JSON,不要解释”。不要靠猜,直接把返回的 content 打印出来看是哪种格式,再决定是清理还是改提示词。
6.4 设备连接失败或超时
如果 AI 已经生成了 check_device_status,但 mcp_server.py 返回的 result 里是 error 或 timeout,那问题基本在网络侧。用 ping 192.168.1.1 确认设备可达,检查 devices.json 里的 device_type 是否和真实设备匹配,用户名密码是否正确。和原来的本地方案相比,这部分报错没有任何变化,因为设备巡检链路没有动过。先手工 curl /mcp,如果手工能通而 ask_ai.py 不行,问题出在 JSON 生成或参数传递;如果手工也不通,就专注修设备和网络。
把 ask_ai.py 改到 TaoToken 之后,我最直观的感受是:本地 Ollama 不再需要常驻内存,模型拉取慢的问题也没了,MCP 巡检指令照样生成,设备结果照常返回。如果你也卡在本地模型这一环,可以直接打开 https://taotoken.net/?utm_source=taotoken_aicg_blog_end 注册并创建 API Key,然后按第 4 节的脚本跑一遍自然语言巡检。用最小的改动解放一台被大模型占满内存的电脑,这套方案经得起实际使用。




被折叠的 条评论
为什么被折叠?



