OllamaDesk - Ollama 本地模型实现指南¶
⚠️ 重要说明¶
OllamaDesk 仅适用于本地测试,不建议用于生产环境
功能限制¶
OllamaDesk 在以下方面存在显著不足:
- 错误捕获与处理
- 缺乏完善的错误分类和识别机制
- 上下文超长等异常处理不完善
-
网络错误恢复能力有限
-
高级功能支持
- Token 计算不准确(使用 tiktoken 近似计算)
- 缺少速率限制处理
-
流式输出支持不完整
-
测试覆盖不足
- TFRobot 团队对 OllamaDesk 的测试覆盖有限
-
生产环境验证不足
-
原生能力设计限制
- Ollama 的 API 设计相对简单,缺少企业级功能
- 与云端 API 相比,错误处理和重试机制较为基础
原因分析¶
这些不足既有测试覆盖不够的原因,也有 Ollama 原生能力设计不足的综合因素:
- 测试层面:TFRobot 团队对 Ollama 的测试优先级较低,覆盖不充分
- 设计层面:Ollama 作为本地推理工具,其 API 设计优先考虑简单性而非企业级特性
- 生态层面:Ollama 缺少完善的错误处理、监控、可观测性等生产级功能
推荐替代方案¶
生产环境强烈建议使用云端 API:
| 需求 | 推荐方案 | 优势 |
|---|---|---|
| 纯文本生成 | DeepSeekDesk | ✅ 中文能力强,价格低,测试充分 |
| 多模态任务 | GeminiDesk | ✅ 1M 上下文,多模态支持完善 |
| 代码生成 | DeepSeekDesk | ✅ FIM 支持,代码能力强 |
| 通用场景 | TencentDSDesk | ✅ 国内访问稳定,功能完善 |
适用场景¶
OllamaDesk 仅适用于: - ✅ 本地开发测试 - ✅ 概念验证(POC) - ✅ 数据隐私要求极高的场景(且能接受功能限制)
💡 如需生产级 LLM 服务,请参考: - DeepSeekDesk - 纯文本任务首选 - GeminiDesk - 多模态任务首选 - TencentDSDesk - 国内环境稳定选择
概述¶
OllamaDesk 是基于 Ollama 本地部署的 LLM 的 DeskLLM 实现。Ollama 允许在本地运行各种开源大语言模型,无需联网即可使用,特别适合对数据隐私要求高的场景。
模型支持¶
推荐模型¶
| 模型名称 | 参数量 | 特点 |
|---|---|---|
qwen2.5 |
7B/14B/32B | 中文能力强,适合通用场景 |
codellama |
7B/13B/34B | 代码专用模型 |
llama3.2 |
3B/8B | 轻量级,快速响应 |
mistral |
7B | 平衡性能与速度 |
gemma2 |
9B/27B | Google 开源模型 |
安装 Ollama¶
macOS/Linux¶
curl -fsSL https://ollama.com/install.sh | sh
Windows¶
从 Ollama 官网 下载安装包。
拉取模型¶
# 拉取 Qwen2.5 模型
ollama pull qwen2.5:7b
# 拉取 CodeLlama 模型
ollama pull codellama:7b
# 拉取 Llama3.2 模型
ollama pull llama3.2:8b
快速开始¶
基本使用¶
from tfrobot.brain.chain.llms.generation_llms.desk_llm.ollama_desk import OllamaDesk
from tfrobot.brain.chain.prompt.memo_prompt import MemoPrompt
from tfrobot.schema.message.conversation.message_dto import TextMessage
# 创建 OllamaDesk 实例
desk_llm = OllamaDesk(
name="qwen2.5:7b",
host="http://localhost",
port=11434
)
# 配置系统提示
desk_llm.system_prompt = [
MemoPrompt(template="你是一个专业的代码助手,擅长 Python 开发。")
]
# 调用
result = desk_llm.complete(
current_input=TextMessage(content="帮我写一个快速排序函数")
)
print(result.generations[0].text)
核心参数¶
基础配置¶
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
host |
str |
http://localhost |
Ollama 服务地址 |
port |
int |
11434 |
Ollama 服务端口 |
timeout |
int |
180 |
请求超时时间(秒) |
模型参数¶
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
name |
str |
qwen3 |
模型名称 |
max_tokens |
int |
- | 最大生成长度(num_predict) |
temperature |
float |
0.8 |
采样温度(0-1) |
top_p |
float |
0.9 |
核采样参数 |
stop |
str\|list[str] |
- | 停止词列表 |
num_ctx |
int |
64000 |
上下文长度(Ollama 默认 2k 太小) |
高级参数¶
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
stream |
bool |
False |
是否流式输出 |
system |
str |
- | 覆盖模型默认的系统提示 |
append |
str |
- | 追加词(停止后需要追加的内容) |
特殊功能¶
思维链提取¶
OllamaDesk 支持从模型输出中提取思维链(thinking content):
from tfrobot.brain.chain.llms.generation_llms.desk_llm.ollama_desk import OllamaDesk
desk_llm = OllamaDesk(name="qwen2.5:7b")
# 如果模型输出包含思维链标记
result = desk_llm.complete(current_input=user_input)
# 提取思维链和最终答案
if result.generations[0].reasoning_content:
print("思维链:", result.generations[0].reasoning_content)
print("答案:", result.generations[0].text)
FIM(Fill-in-the-Middle)模式¶
OllamaDesk 支持 FIM 模式:
desk_llm = OllamaDesk(name="codellama:7b")
# 前缀(prefix)
desk_llm.prefix_prompt = [
MemoPrompt(template="def quicksort(arr):\n ")
]
# 后缀(suffix)- 希望模型达到的状态
desk_llm.suffix_prompt = [
MemoPrompt(template="\n return sorted_arr")
]
# 模型会在中间生成代码
result = desk_llm.complete(current_input=TextMessage(content="完成函数"))
print(result.generations[0].text)
多模态支持¶
OllamaDesk 支持图片输入:
from tfrobot.brain.chain.llms.generation_llms.desk_llm.ollama_desk import OllamaDesk
from tfrobot.schema.message.conversation.message_dto import MultiPartMessage
from tfrobot.schema.message.msg_part import TextPart, ImagePart
from tfrobot.schema.message.image_url import ImgUrl
desk_llm = OllamaDesk(
name="llama3.2-vision:11b", # 需要使用支持视觉的模型
num_ctx=64000
)
# 多模态输入
msg = MultiPartMessage(content=[
TextPart(text="请描述这个界面的布局"),
ImagePart(image_url=ImgUrl(url="screenshot.png")),
])
result = desk_llm.complete(current_input=msg)
print(result.generations[0].text)
使用场景¶
代码生成¶
desk_llm = OllamaDesk(
name="codellama:7b",
num_ctx=64000 # 增加上下文长度
)
desk_llm.system_prompt = [
MemoPrompt(template="你是一个 Python 专家,编写高质量、有文档的代码。")
]
desk_llm.purpose_prompt = [
MemoPrompt(template="创建一个 Person 数据类,包含 name 和 age 属性。")
]
desk_llm.prefix_prompt = [
MemoPrompt(template="```python\nfrom dataclasses import dataclass\n\n")
]
result = desk_llm.complete(current_input=TextMessage(content="开始生成"))
print(result.generations[0].text)
中文内容生成¶
# 使用 Qwen2.5 获得更好的中文效果
desk_llm = OllamaDesk(
name="qwen2.5:7b",
temperature=0.8,
top_p=0.9,
num_ctx=64000
)
desk_llm.system_prompt = [
MemoPrompt(template="你是一个专业的文案撰写助手。")
]
desk_llm.purpose_prompt = [
MemoPrompt(template="为一款智能家居产品撰写一段宣传文案,突出便捷性和智能化。")
]
result = desk_llm.complete(current_input=TextMessage(content="开始撰写"))
print(result.generations[0].text)
使用追加词¶
desk_llm = OllamaDesk(
name="qwen2.5:7b",
stop=["```"], # 在遇到 ``` 时停止
append="```" # 追加 ``` 以闭合代码块
)
desk_llm.purpose_prompt = [
MemoPrompt(template="生成一个 Python 快速排序函数。")
]
result = desk_llm.complete(current_input=TextMessage(content="开始"))
# 输出会包含 ``` 闭合标记
配置优化¶
调整上下文长度¶
Ollama 默认上下文长度为 2K,太小了。建议调整为 64K:
desk_llm = OllamaDesk(
name="qwen2.5:7b",
num_ctx=64000 # 64K tokens
)
温度和采样参数¶
# 确定性输出(代码生成)
desk_llm = OllamaDesk(
name="codellama:7b",
temperature=0.0,
top_p=0.9
)
# 创造性输出(文案创作)
desk_llm = OllamaDesk(
name="qwen2.5:7b",
temperature=0.8,
top_p=0.95
)
系统提示覆盖¶
# 覆盖模型的默认系统提示
desk_llm = OllamaDesk(
name="qwen2.5:7b",
system="你是一个专业的 Python 开发者,专注于编写高质量的代码。"
)
Token 计算¶
OllamaDesk 使用 tiktoken 近似计算 Token 消耗:
result = desk_llm.complete(current_input=user_input)
# Token 使用情况
print(result.usage)
# {
# "prompt_tokens": 100,
# "completion_tokens": 50,
# "total_tokens": 150,
# "prompt_cost": 0.0, # 本地模型,无成本
# "completion_cost": 0.0,
# "total_cost": 0.0
# }
性能优化¶
1. 选择合适的模型大小¶
# 小模型:快速,适合简单任务
desk_llm = OllamaDesk(name="llama3.2:3b")
# 中等模型:平衡性能和速度
desk_llm = OllamaDesk(name="qwen2.5:7b")
# 大模型:更好的质量,但更慢
desk_llm = OllamaDesk(name="qwen2.5:32b")
2. 调整上下文长度¶
# 根据任务需求调整
desk_llm = OllamaDesk(
name="qwen2.5:7b",
num_ctx=16000 # 简单任务
# num_ctx=64000 # 复杂任务
)
3. 使用停止词¶
# 减少不必要的生成
desk_llm = OllamaDesk(
name="codellama:7b",
stop=["```", "END", "<|end_of_text|>"]
)
4. 本地模型管理¶
# 查看已安装的模型
ollama list
# 删除不需要的模型
ollama rm old-model:7b
# 查看模型信息
ollama show qwen2.5:7b
错误处理¶
连接失败¶
from requests.exceptions import ConnectionError
try:
result = desk_llm.complete(current_input=user_input)
except ConnectionError:
print("无法连接到 Ollama 服务,请确保 Ollama 正在运行")
print("启动命令: ollama serve")
超时错误¶
# 增加超时时间
desk_llm = OllamaDesk(
name="qwen2.5:32b", # 大模型需要更长时间
timeout=300 # 5 分钟
)
内存不足¶
# 如果遇到内存不足错误,可以:
# 1. 使用更小的模型
ollama pull qwen2.5:3b
# 2. 减少 num_ctx
desk_llm = OllamaDesk(name="qwen2.5:7b", num_ctx=16000)
高级用法¶
多轮编辑¶
from tfrobot.brain.chain.llms.generation_llms.desk_llm.ollama_desk import OllamaDesk
desk_llm = OllamaDesk(name="codellama:7b", num_ctx=64000)
# 初始代码
original_code = """
def add(a, b):
return a + b
"""
desk_llm.original_desk_screenshot_prompt = [
MemoPrompt(template=f"原始代码:\n```python\n{original_code}\n```")
]
# 第一轮:添加类型注解
desk_llm.purpose_prompt = [
MemoPrompt(template="添加类型注解。")
]
result1 = desk_llm.complete(current_input=TextMessage(content="开始编辑"))
current_code = result1.generations[0].text
# 第二轮:添加文档字符串
desk_llm.current_desk_screenshot_prompt = [
MemoPrompt(template=f"当前代码:\n```python\n{current_code}\n```")
]
desk_llm.intermediate_prompt = [
MemoPrompt(template="已添加类型注解。")
]
desk_llm.purpose_prompt = [
MemoPrompt(template="添加文档字符串。")
]
result2 = desk_llm.complete(current_input=TextMessage(content="继续编辑"))
print(result2.generations[0].text)
异步调用¶
import asyncio
async def generate():
desk_llm = OllamaDesk(name="qwen2.5:7b")
result = await desk_llm.async_complete(
current_input=TextMessage(content="生成代码")
)
return result.generations[0].text
result = asyncio.run(generate())
最佳实践¶
1. 选择合适的模型¶
# 中文场景:Qwen2.5
desk_llm = OllamaDesk(name="qwen2.5:7b")
# 代码场景:CodeLlama
desk_llm = OllamaDesk(name="codellama:7b")
# 英文场景:Llama3.2
desk_llm = OllamaDesk(name="llama3.2:8b")
# 平衡场景:Mistral
desk_llm = OllamaDesk(name="mistral:7b")
2. 调整上下文长度¶
# Ollama 默认 2K 太小,建议至少 16K
desk_llm = OllamaDesk(
name="qwen2.5:7b",
num_ctx=64000 # 64K
)
3. 使用合适的温度¶
# 代码生成:低温度
desk_llm = OllamaDesk(
name="codellama:7b",
temperature=0.0
)
# 文案创作:高温度
desk_llm = OllamaDesk(
name="qwen2.5:7b",
temperature=0.8
)
4. 管理本地模型¶
# 定期清理不需要的模型
ollama list
ollama rm unused-model:7b
# 更新模型
ollama pull qwen2.5:7b
与远程模型的区别¶
| 特性 | OllamaDesk | ClaudeDesk/GPTDesk |
|---|---|---|
| 网络依赖 | 无 | 需要 |
| 数据隐私 | 完全本地 | 上传到云端 |
| 成本 | 免费 | 按使用付费 |
| 性能 | 取决于硬件 | 稳定 |
| 模型更新 | 手动 | 自动 |
| 上下文长度 | 需手动配置 | 默认较大 |