Skip to content

GenerationLLM 生成模型

GenerationLLM 是为连续文本生成场景设计的 LLM 抽象类,适合 DSL 生成、代码编辑、图提取等需要连续输出的场景。DeskLLM 是 GenerationLLM 的主要实现,专注于桌面环境模拟。

设计理念

为什么需要 GenerationLLM

虽然 ChatLLM 已经可以处理大部分场景,但在某些特殊需求下,生成模型更有优势:

  1. 连续工具调用:生成模型在连续工具调用时效果更好
  2. 不需要数据结构:只需要不断追加内容,无需考虑复杂的 JSON 结构
  3. 流式输出:生成模型的输出可以自然地逐步生成
  4. 专用场景优化:如 DSL 生成、代码编辑、图提取等
  5. 简化 Prompt 结构:通过单一 Prompt 控制整个生成过程

与 ChatLLM 的区别

特性 ChatLLM GenerationLLM
主要用途 多轮对话、工具调用 连续文本生成
响应格式 支持结构化(JSON/工具调用) 仅纯文本
API 类型 Chat Completions API Completions API
消息结构 支持多角色(user/assistant/system/tool) 简化的输入输出
典型场景 QA、代码助手、数据分析 DSL 生成、代码编辑、图提取
Prompt 系统 5 个 Prompt 位置 7 个 Prompt 位置

DeskLLM 桌面环境模拟

DeskLLM 是 GenerationLLM 的主要实现,专门用于模拟桌面环境的智能体。

核心概念

DeskLLM 将 LLM 视为一个拥有自己桌面环境的智能体,它可以在这个环境中执行各种任务,如编辑文件、运行代码等。

桌面环境隐喻

┌─────────────────────────────────────────┐
│         DeskLLM 桌面环境                 │
│                                          │
│  ┌──────────────┐  ┌──────────────┐     │
│  │  Editor      │  │  Terminal    │     │
│  │  (代码编辑器) │  │  (命令行)    │     │
│  └──────────────┘  └──────────────┘     │
│                                          │
│  状态变化:                                │
│  original_desk → 操作 → current_desk     │
└─────────────────────────────────────────┘

Prompt 结构(7 层架构)

DeskLLM 使用与 ChatLLM 不同的 Prompt 结构,专门优化了桌面环境模拟场景:

Prompt 类型 说明 典型用途
system_prompt 系统角色、工具范围、背景信息 限定 LLM 角色,提供全局上下文
instruction_prompt Few-shot 学习示例 展示期望的行事风格和规则
original_desk_screenshot_prompt 任务初始时的环境状态 记录未编辑时的文件原始内容
purpose_prompt 任务目标和要求 用户输入或当前任务描述
intermediate_prompt 中间结果和状态变更 记录已执行的操作和状态变化
current_desk_screenshot_prompt 任务进行时的环境状态 当前文件内容(随操作变化)
prefix_prompt 输出前缀 强制 LLM 以特定格式开头

Prompt 渲染顺序

system_prompt          ← 全局角色定义
    ↓
instruction_prompt    ← Few-shot 示例
    ↓
original_desk_screenshot_prompt  ← 初始状态
    ↓
purpose_prompt         ← 当前任务
    ↓
intermediate_prompt    ← 中间步骤
    ↓
current_desk_screenshot_prompt  ← 当前状态
    ↓
prefix_prompt          ← 输出引导
    ↓
[LLM 生成内容]

使用场景

  • DSL 生成:生成特定领域语言的代码(如 SQL、GraphQL、Excel 公式)
  • 代码编辑:自动编辑代码文件(增量修改而非重写)
  • 图提取:从文本中提取图谱结构(RDF、OWL)
  • 桌面自动化:控制桌面应用程序(模拟鼠标键盘操作)

快速开始

使用 DeskLLM

from tfrobot.brain.chain.llms.generation_llms.desk_llm.openai_desk import GPTDesk
from tfrobot.brain.chain.prompt.memo_prompt import MemoPrompt
from tfrobot.schema.message.conversation.message_dto import TextMessage

# 创建 DeskLLM
desk_llm = GPTDesk(name="gpt-4o")

# 配置系统提示
desk_llm.system_prompt = [
    MemoPrompt(template="你是一个代码编辑助手,专注于 Python 开发。")
]

# 调用
result = desk_llm.complete(
    current_input=TextMessage(content="帮我写一个快速排序函数")
)
print(result.generations[0].text)

代码编辑场景示例

from tfrobot.brain.chain.llms.generation_llms.desk_llm.claude_desk import ClaudeDesk
from tfrobot.brain.chain.prompt.memo_prompt import MemoPrompt

desk_llm = ClaudeDesk(name="claude-3-5-sonnet-20241022")

# 配置代码编辑场景的 Prompts
desk_llm.system_prompt = [
    MemoPrompt(template="你是一个 Python 代码编辑助手。")
]

# 原始文件内容
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="请为 add 函数添加类型注解和文档字符串。"
    )
]

# 强制输出格式
desk_llm.prefix_prompt = [
    MemoPrompt(template="修改后的代码:\n```python\n")
]

# 生成
result = desk_llm.complete(current_input=TextMessage(content="开始编辑"))
print(result.generations[0].text)

DSL 生成场景示例

from tfrobot.brain.chain.llms.generation_llms.desk_llm.gemini_desk import GeminiDesk

desk_llm = GeminiDesk(name="gemini-2.5-flash")

# 配置 DSL 生成场景
desk_llm.system_prompt = [
    MemoPrompt(template="你是一个 SQL 专家,擅长根据自然语言描述生成 SQL 查询。")
]

# Few-shot 示例
desk_llm.instruction_prompt = [
    MemoPrompt(template="""
示例 1:
输入:查询所有年龄大于 18 的用户
输出:SELECT * FROM users WHERE age > 18;

示例 2:
查询每个部门的平均工资
输出:SELECT department, AVG(salary) FROM employees GROUP BY department;
""")
]

# 当前任务
desk_llm.purpose_prompt = [
    MemoPrompt(template="输入:查询销售额排名前 10 的产品")
]

# 强制输出前缀
desk_llm.prefix_prompt = [
    MemoPrompt(template="输出:")
]

result = desk_llm.complete(current_input=TextMessage(content="生成 SQL"))
print(result.generations[0].text)

核心参数

通用参数

参数 类型 默认值 说明
name str - 模型名称(如 gpt-4o, claude-3-5-sonnet-20241022
temperature float 1.0 采样温度,0-2 之间
max_tokens int 4096 最大生成 tokens 数
top_p float 1.0 核采样参数
stop str\|list[str] - 停止词列表
stream bool False 是否流式输出

Prompt 参数

参数 类型 默认值 说明
system_prompt list[BasePrompt] [] 系统提示(角色定义)
instruction_prompt list[BasePrompt] [] 指令提示(Few-shot 示例)
original_desk_screenshot_prompt list[BasePrompt] [] 初始环境状态
purpose_prompt list[BasePrompt] [UserInputPrompt(...)] 任务目的提示
intermediate_prompt list[BasePrompt] [] 中间结果提示
current_desk_screenshot_prompt list[BasePrompt] [] 当前环境状态
prefix_prompt list[BasePrompt] [] 输出前缀提示

提供商特定参数

不同提供商有额外的配置参数,详见各提供商文档。

支持的实现

类名 提供商 说明 默认模型
GPTDesk OpenAI GPT 系列模型 gpt-4-turbo-preview
ClaudeDesk Anthropic Claude 系列模型 claude-3-opus-20240229
GeminiDesk Google Gemini 系列模型 gemini-2.5-flash
DeepSeekDesk DeepSeek DeepSeek 系列模型 deepseek-coder
OllamaDesk Ollama 本地模型 codellama:7b
SGLangDesk SGLang SGLang 本地服务 -
TencentDSDesk 腾讯 腾讯混元系列 -

重要约束

仅支持纯文本返回

DeskLLM 不支持结构化响应格式(JSON/JSON Schema),只能返回纯文本:

# ❌ 错误:不支持 JSON 格式
desk_llm = GPTDesk(
    name="gpt-4o",
    response_format={"type": "json_object"}  # 会抛出 ValueError
)

# ✅ 正确:使用纯文本,自行解析
desk_llm = GPTDesk(name="gpt-4o")
# 在 Prompt 中提示模型返回 JSON
desk_llm.system_prompt = [
    MemoPrompt(template="请以 JSON 格式返回结果。")
]

result = desk_llm.complete(...)
# 手动解析 result.generations[0].text
import json
json_data = json.loads(result.generations[0].text)

代理配置

部分 DeskLLM 实现支持代理配置:

# OpenAI/Claude/Gemini 支持 HTTP(S) 代理
desk_llm = GPTDesk(
    name="gpt-4o",
    proxy_host="127.0.0.1",
    proxy_port=7890,
    proxy_user=None,  # 可选
    proxy_pass=None,  # 可选
)

# Gemini 还支持 SOCKS5 代理
from tfrobot.brain.chain.llms.generation_llms.desk_llm.gemini_desk import GeminiDesk

desk_llm = GeminiDesk(
    name="gemini-2.5-flash",
    socks5_proxy=True,  # 使用 SOCKS5
    proxy_host="127.0.0.1",
    proxy_port=1080,
)

API 映射

DeskLLM 使用各提供商的 Completions API 而非 Chat Completions API:

提供商 API 类型 端点
OpenAI Completions POST /v1/completions
Anthropic Completions POST /v1/messages (legacy)
Gemini Generate Content POST /v1beta/models/{model}:generateContent

最佳实践

1. Prompt 顺序设计

合理设计 Prompt 的顺序和内容:

desk_llm = GPTDesk(name="gpt-4o")

# 1. 定义全局角色
desk_llm.system_prompt = [
    MemoPrompt(template="你是一个专业的 Python 开发者。")
]

# 2. 提供示例
desk_llm.instruction_prompt = [
    MemoPrompt(template="""
示例:
输入:创建一个Person类
输出:
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
""")
]

# 3. 提供初始状态
desk_llm.original_desk_screenshot_prompt = [
    MemoPrompt(template="# 当前文件为空\n")
]

# 4. 定义任务
desk_llm.purpose_prompt = [
    MemoPrompt(template="请创建一个Student类,继承Person类。")
]

# 5. 提供中间步骤(如果有)
desk_llm.intermediate_prompt = []

# 6. 提供当前状态
desk_llm.current_desk_screenshot_prompt = []

# 7. 强制输出格式
desk_llm.prefix_prompt = [
    MemoPrompt(template="```python\n")
]

2. 状态管理

在多轮生成中正确管理环境状态:

# 初始状态
original_content = read_file("main.py")

desk_llm.original_desk_screenshot_prompt = [
    MemoPrompt(template=f"原始文件内容:\n{original_content}")
]

# 第一次修改
desk_llm.purpose_prompt = [
    MemoPrompt(template="添加错误处理")
]
result1 = desk_llm.complete(...)
current_content = result1.generations[0].text

# 第二次修改(基于第一次的结果)
desk_llm.current_desk_screenshot_prompt = [
    MemoPrompt(template=f"当前文件内容:\n{current_content}")
]
desk_llm.intermediate_prompt = [
    MemoPrompt(template="已添加错误处理。")
]
desk_llm.purpose_prompt = [
    MemoPrompt(template="添加类型注解")
]
result2 = desk_llm.complete(...)

3. 多模态支持

部分 DeskLLM 实现支持多模态输入:

from tfrobot.brain.chain.llms.generation_llms.desk_llm.gemini_desk import GeminiDesk
from tfrobot.schema.message.conversation.message_dto import MultiPartMessage
from tfrobot.schema.message.msg_part import TextPart, ImagePart

desk_llm = GeminiDesk(name="gemini-2.5-flash")

# 多模态输入
msg = MultiPartMessage(content=[
    TextPart(text="请描述这个界面的布局"),
    ImagePart(image_url=ImgUrl(url="screenshot.png")),
])

result = desk_llm.complete(current_input=msg)

错误处理

上下文超长

当上下文超出限制时,抛出 ContextTooLargeError

from tfrobot.schema.exceptions import ContextTooLargeError

try:
    result = desk_llm.complete(current_input=long_input)
except ContextTooLargeError as e:
    print(f"当前大小: {e.current_size}")
    print(f"目标大小: {e.target_size}")
    print(f"模型: {e.model_name}")
    # 由 Chain 层自动处理压缩

参数验证

# ❌ 错误:尝试设置 JSON 格式
try:
    desk_llm = GPTDesk(
        name="gpt-4o",
        response_format={"type": "json_object"}
    )
except ValueError as e:
    print(e)  # "DeskLLM仅支持纯文本返回..."

性能优化

1. 使用流式输出

desk_llm = GPTDesk(name="gpt-4o", stream=True)

result = desk_llm.complete(current_input=user_input)
# 内容会逐步生成

2. 控制 max_tokens

# 对于简单任务,限制输出长度
desk_llm = GPTDesk(
    name="gpt-4o",
    max_tokens=512  # 减少延迟和成本
)

3. 使用合适的模型

# 简单任务使用小模型
desk_llm = GPTDesk(name="gpt-4o-mini")

# 复杂任务使用大模型
desk_llm = GPTDesk(name="gpt-4o")

相关文档

基础文档

DeskLLM 实现文档

云端 API 实现(推荐用于生产环境)

  • GeminiDesk - Google Gemini 实现
  • 多模态任务首选 - 1M 上下文,完善的多模态支持
  • ✅ 国内访问相对稳定
  • ✅ SOCKS5 代理支持

  • DeepSeekDesk - DeepSeek 实现

  • 纯文本任务推荐 - 中文能力强,价格低
  • ✅ FIM(Fill-in-the-Middle)支持
  • ✅ 测试充分,稳定性好

  • TencentDSDesk - 腾讯混元实现

  • ✅ 国内访问稳定
  • ✅ 功能完善,流式输出支持

  • GPTDesk - OpenAI Responses API 实现

  • ⚠️ Completion API 支持有限
  • ⚠️ 国内访问困难

  • GPTGenDesk - OpenAI Completions API 实现

  • ✅ 支持停止词(最多 4 个)
  • ⚠️ 仅支持 gpt-3.5-turbo-instruct 模型

  • ClaudeDesk - Anthropic Claude 实现

  • ⚠️ 国内访问困难
  • ⚠️ 未经过充分测试
  • 💡 建议使用 GeminiDesk 或 DeepSeekDesk 替代

本地模型实现(仅用于测试)

  • OllamaDesk - Ollama 本地模型实现
  • ⚠️ 仅适用于本地测试,不建议用于生产环境
  • ⚠️ 错误处理、测试覆盖均有不足
  • 💡 生产环境推荐使用云端 API

  • SGLangDesk - SGLang 本地服务实现

  • ⚠️ 仅适用于本地测试
  • ⚠️ 需要手动部署和维护

技术文档