Skip to content

OllamaDesk - Ollama 本地模型实现指南

⚠️ 重要说明

OllamaDesk 仅适用于本地测试,不建议用于生产环境

功能限制

OllamaDesk 在以下方面存在显著不足:

  1. 错误捕获与处理
  2. 缺乏完善的错误分类和识别机制
  3. 上下文超长等异常处理不完善
  4. 网络错误恢复能力有限

  5. 高级功能支持

  6. Token 计算不准确(使用 tiktoken 近似计算)
  7. 缺少速率限制处理
  8. 流式输出支持不完整

  9. 测试覆盖不足

  10. TFRobot 团队对 OllamaDesk 的测试覆盖有限
  11. 生产环境验证不足

  12. 原生能力设计限制

  13. Ollama 的 API 设计相对简单,缺少企业级功能
  14. 与云端 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
网络依赖 需要
数据隐私 完全本地 上传到云端
成本 免费 按使用付费
性能 取决于硬件 稳定
模型更新 手动 自动
上下文长度 需手动配置 默认较大

相关文档