Skip to content

DeskLLM 技术文档

1. 概述

DeskLLM 是一个模拟桌面环境的大语言模型封装框架,它提供了一个统一的接口来与各种大语言模型进行交互。DeskLLM 的设计理念是将大模型视为一个拥有自己桌面环境的智能体,它可以在这个环境中执行各种任务,如编辑文件、运行代码等。

DeskLLM 的核心优势在于: - 统一的接口设计,便于切换不同的底层大语言模型 - 丰富的提示词管理机制,支持多种提示词模板 - 灵活的上下文管理,包括系统消息、指令消息、工作环境状态等 - 支持工具调用和中间结果处理

2. 架构设计

DeskLLM 采用了抽象基类 + 具体实现的设计模式:

GenerationLLM (抽象基类)
    └── DeskLLM (抽象基类)
        ├── GPTDesk (OpenAI 实现)
        ├── ClaudeDesk (Anthropic 实现)
        └── DeepSeekDesk (DeepSeek 实现)

每个具体实现类负责与特定的 LLM 服务提供商 API 进行交互,而共享相同的接口和基础功能。

3. 核心组件

3.1 提示词管理

DeskLLM 将提示词分为多个类别,每个类别都有特定的用途:

  • system_prompt: 系统消息提示,用于限定大模型角色、工具范围及提供背景信息
  • instruction_prompt: 指令消息提示,通过 few-shot 学习方式提供示例
  • original_desk_screenshot_prompt: 初始工作环境状态,描述任务初始时的环境
  • purpose_prompt: 任务目的提示,提供任务目标和要求
  • intermediate_prompt: 中间结果提示,记录 LLM 生成的中间结果和状态变更
  • current_desk_screenshot_prompt: 当前工作环境状态,描述任务进行时的环境状态

3.2 模板系统

DeskLLM 支持多种提示词模板系统,推荐使用 Jinja2PromptTemplate:

  • 支持条件语句、循环和宏定义
  • 支持多语言模板
  • 支持自定义过滤器和全局函数

3.3 请求处理流程

  1. 构造请求参数 (construct_request_params)
  2. 发送请求到 LLM API (complete/async_complete)
  3. 处理响应并构造结果 (construct_llm_result)

4. 实现原则与注意事项

4.1 基本原则

  1. 接口一致性:所有 DeskLLM 的实现类应保持相同的接口,便于切换不同的底层模型
  2. 错误处理:实现应包含完善的错误处理机制,特别是网络错误和 API 限制错误
  3. 上下文管理:合理管理上下文长度,避免超出模型的最大上下文窗口
  4. 参数验证:使用 Pydantic 进行参数验证,确保参数的正确性
  5. 异步支持:同时提供同步和异步接口,满足不同场景的需求

4.2 注意事项

  1. 响应格式限制:DeskLLM 仅支持纯文本返回,不支持 JSON Schema 格式
  2. 上下文窗口管理:当上下文超出限制时,应有策略进行上下文压缩
  3. 代理配置:在网络受限环境中,需要正确配置代理
  4. API 密钥管理:安全存储和使用 API 密钥
  5. 重试机制:对于可重试的错误(如网络超时),应实现适当的重试策略

5. 最佳实践

5.1 模型选择

根据任务复杂度和性能要求选择合适的模型:

  • 简单任务:可使用轻量级模型如 GPT-3.5-Turbo
  • 复杂推理:推荐使用高级模型如 GPT-4、Claude-3-Opus 或 DeepSeek-Reasoning
  • 中文场景:DeepSeek 模型在中文处理上有较好表现

5.2 提示词设计

  1. 使用 Jinja2 模板:优先使用 Jinja2PromptTemplate 而非 FStrPromptTemplate
  2. 分层提示词:合理利用不同类型的提示词,清晰分离系统指令、用户输入和环境状态
  3. 保持简洁:避免冗余信息,减少 token 消耗
  4. 结构化信息:对于复杂信息,使用结构化格式呈现

5.3 工具集成

  1. 工具描述:提供清晰的工具描述和参数说明
  2. 错误处理:处理工具执行过程中可能出现的错误
  3. 结果反馈:将工具执行结果正确反馈给模型

5.4 代码示例

基本使用示例

from tfrobot.brain.chain.llms.generation_llms.desk_llm.openai_desk import GPTDesk
from tfrobot.brain.chain.prompt.template.jinja2_template import Jinja2PromptTemplate
from tfrobot.brain.chain.prompt.memo_prompt import MemoPrompt
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.types import Locale
from tfrobot.schema.users import BaseUser

# 创建 DeskLLM 实例
desk_llm = GPTDesk(
    name="gpt-4-turbo-preview",
    openai_api_key="your_api_key",
    temperature=0.7
)

# 添加系统提示
system_template = Jinja2PromptTemplate(
    templates={
        Locale.EN: "You are a helpful assistant that specializes in coding.",
        Locale.ZH: "你是一个专注于编程的助手。"
    }
)
memo_prompt = MemoPrompt()
desk_llm.system_prompt.append(memo_prompt)

# 创建用户输入
user_input = TextMessage(
    role="user",
    creator=BaseUser(name="User", uid="1"),
    content="帮我写一个简单的 Python 函数来计算斐波那契数列"
)

# 获取响应
result = desk_llm.complete(current_input=user_input)
print(result.generations[0].text)

工具调用示例

from tfrobot.brain.chain.llms.generation_llms.desk_llm.openai_desk import GPTDesk
from tfrobot.brain.chain.prompt.tool_prompt import ToolPrompt
from tfrobot.drive.tool.tool import tool

# 定义工具
@tool
def calculate(expression: str) -> str:
    """计算数学表达式的结果"""
    try:
        return str(eval(expression))
    except Exception as e:
        return f"Error: {str(e)}"

# 创建 DeskLLM 实例
desk_llm = GPTDesk(name="gpt-4-turbo-preview", openai_api_key="your_api_key")

# 添加工具提示
tool_prompt = ToolPrompt()
desk_llm.system_prompt.append(tool_prompt)

# 使用工具
result = desk_llm.complete(
    current_input=TextMessage(content="计算 123 + 456 的结果"),
    tools=[calculate]
)

6. 扩展 DeskLLM

6.1 创建新的 DeskLLM 实现

要为新的 LLM 服务提供商创建 DeskLLM 实现,需要:

  1. 继承 DeskLLM 抽象基类
  2. 实现必要的方法:
  3. model_post_init: 初始化客户端
  4. construct_request_params: 构造请求参数
  5. complete: 同步请求处理
  6. async_complete: 异步请求处理
  7. construct_llm_result: 构造结果对象

6.2 自定义提示词模板

可以通过继承 BasePrompt 和使用 Jinja2PromptTemplate 创建自定义提示词模板:

from tfrobot.brain.chain.prompt.base import BasePrompt
from tfrobot.brain.chain.prompt.template.jinja2_template import Jinja2PromptTemplate
from tfrobot.schema.meta.tf_field import TFField
from tfrobot.schema.types import Locale

class CustomPrompt(BasePrompt):
    template = TFField(
        default_factory=lambda: Jinja2PromptTemplate(
            templates={
                Locale.EN: "Custom template: {{ variable }}",
                Locale.ZH: "自定义模板: {{ variable }}"
            }
        )
    )

7. 故障排除

7.1 常见问题

  1. 上下文长度超限
  2. 症状:API 返回 "context_length_exceeded" 错误
  3. 解决方案:减少提示词长度,或使用 collapse_context 方法压缩上下文

  4. API 认证失败

  5. 症状:API 返回 401 错误
  6. 解决方案:检查 API 密钥是否正确,是否过期

  7. 网络超时

  8. 症状:请求超时错误
  9. 解决方案:增加 timeout 参数,或配置代理

7.2 调试技巧

  1. 使用 warnings 模块记录非致命错误
  2. 检查 LLMResult 中的 meta_info 字段获取额外信息
  3. 使用 prompt 字段查看实际发送给 API 的提示词

8. 总结

DeskLLM 提供了一个强大而灵活的框架,用于与各种大语言模型进行交互。通过遵循本文档中的原则和最佳实践,可以有效地利用 DeskLLM 构建高质量的 AI 应用。

关键要点: - 使用统一接口简化模型切换 - 合理组织提示词结构 - 优先使用 Jinja2 模板 - 妥善处理错误和边界情况 - 根据任务需求选择合适的模型