GenerationLLM 生成模型¶
GenerationLLM 是为连续文本生成场景设计的 LLM 抽象类,适合 DSL 生成、代码编辑、图提取等需要连续输出的场景。DeskLLM 是 GenerationLLM 的主要实现,专注于桌面环境模拟。
设计理念¶
为什么需要 GenerationLLM¶
虽然 ChatLLM 已经可以处理大部分场景,但在某些特殊需求下,生成模型更有优势:
- 连续工具调用:生成模型在连续工具调用时效果更好
- 不需要数据结构:只需要不断追加内容,无需考虑复杂的 JSON 结构
- 流式输出:生成模型的输出可以自然地逐步生成
- 专用场景优化:如 DSL 生成、代码编辑、图提取等
- 简化 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 |
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 本地服务实现
- ⚠️ 仅适用于本地测试
- ⚠️ 需要手动部署和维护
技术文档¶
- DeskLLM 技术文档 - 架构设计、实现原则、最佳实践