# Ollama(本地 / 自托管)实测记录 > 日期:2026-06-09 · 环境:macOS,Ollama @ `127.0.0.1:11434`,模型 `qwen2.5:7b` / `qwen2.5-coder:32b` 把 claim ④ 的"本地 Ollama 灵活切换"从**纸面声明**变为**实测通过**。坐实"自托管"这条结构性护城河(大厂 SaaS 无法提供气隙部署)。 ## 实测结论 | 层级 | 结果 | |---|---| | Provider `chat()` | ✅ 正常,usage 累积 | | Provider `chat_typed()` | ✅ 正常,返回 token/model/finish_reason | | `get_usage()` 会话累计 | ✅ 正常(修复后,见下) | | 全栈 simple agent(YAML→compile→Sandbox→workspace) | ✅ 完成,产物三件套齐全 | | 全栈 react agent(含 terminate 工具) | ✅ 完成,token 捕获正确(232 tokens) | | 本地模型计费 | ✅ **$0**(修复后,见下) | ## 实测中发现并修复的 3 个真问题 1. **本地模型被按 Claude 定价计费**(`agentpaas/engine/sandbox.py::_compute_cost_usd`) - 修复:`provider == "ollama"` → 直接返回 `0.0`。本地模型无 per-token API 成本。 2. **`chat_typed()` 不累积 session usage**(`lambdagent/.../openai_compat_provider.py`) - 只有 `chat()` 累积,`chat_typed()` 返回了 usage 却没加进 `_usage_input/_usage_output`,导致用 typed 接口时 `get_usage()` 永远返回 0。 - 修复:`chat_typed()` 内同步累积,与 `chat()` 对齐。 3. **cost.json 的 `source` 标签对非 Claude provider 误导** - 原来只要有 usage 就写死 `"claude_jsonl"`,即使是 ollama/qwen。 - 修复:按 provider 反映真实来源——Claude=`claude_jsonl`,其余=`{provider}_api`。 ## 已知遗留(非 ollama 专属,跨 provider 既有限制) - **simple agent token 计数为 0**:simple 类型没有 react 的 `_think_ref`,Sandbox 读不到 provider 已累积的 usage → `source: trace_fallback, tokens: 0`。对 ollama 无害(成本本就 $0),但对计费型 provider 会低估 token。属既有架构限制,待单独处理(让 simple 路径也能回读 provider.get_usage())。 ## 可重复测试 `tests/test_ollama.py`: - 成本单测(**不需** ollama 运行):local=$0、Claude/qwen 定价回归。 - live 测试(**ollama 可达才跑,否则自动 skip**):chat 往返、usage 累积、全栈 $0 run。 - 复现前置:`ollama pull qwen2.5:7b && ollama serve`。 ## 配置用法 ```yaml model: provider: ollama name: qwen2.5:7b # 或 qwen2.5-coder:32b 等本地模型 temperature: 0.0 maxTokens: 256 ``` 默认 base_url `http://127.0.0.1:11434/v1`,可用 `base_url` 覆盖远程 ollama。