Skip to content

LLM 最佳实践与性能优化

本文档汇总了使用 TFRobot LLM 模块的最佳实践和性能优化技巧。

模型选择

按场景选择

场景 推荐模型 原因
通用对话 GPT-4o, Claude 3.5 Sonnet 综合能力最强
复杂推理 Claude 3.5 Sonnet (Extended Thinking) 推理过程可见
长文档分析 Gemini 1.5 Pro, Claude Opus 上下文窗口大
代码生成 GPT-4o, Claude 3.5 Sonnet 代码能力强
中文场景 DeepSeek, GLM 中文理解好
成本敏感 GPT-4o-mini, Claude Haiku 价格低
快速响应 GPT-4o-mini, Claude Haiku 延迟低
本地部署 Ollama (Llama 3) 数据隐私

成本对比

模型 输入价格 输出价格 性价比
GPT-4o ¥0.025/1M ¥0.05/1M ⭐⭐⭐⭐
Claude 3.5 Sonnet ¥0.015/1M ¥0.0375/1M ⭐⭐⭐⭐⭐
Gemini 1.5 Pro ¥0.00875/1M ¥0.02625/1M ⭐⭐⭐⭐⭐
DeepSeek-Chat ¥0.001/1M ¥0.002/1M ⭐⭐⭐⭐⭐
GPT-4o-mini ¥0.00075/1M ¥0.0015/1M ⭐⭐⭐⭐⭐

Prompt 工程

Prompt 位置策略

from tfrobot.brain.chain.llms import Claude
from tfrobot.brain.chain.prompt.knowledge_prompt import KnowledgePrompt
from tfrobot.brain.chain.prompt.memo_prompt import MemoPrompt
from tfrobot.brain.chain.prompt.template.jinja2_template import Jinja2PromptTemplate
from tfrobot.brain.chain.prompt.tool_prompt import ToolPrompt
from tfrobot.schema.types import Locale

llm = Claude(name="claude-3-5-sonnet-20241022")

# 推荐的组织方式
llm.system_msg_prompt = [
    MemoPrompt(
        template=Jinja2PromptTemplate(templates={Locale.DEFAULT: "你是一个专业的 Python 开发助手。"})
    ),  # 1. 系统角色
    ToolPrompt(),  # 2. 工具列表
    KnowledgePrompt(),  # 3. 知识库
]

llm.before_input_msg_prompt = [
    MemoPrompt(
        template=Jinja2PromptTemplate(templates={Locale.DEFAULT: "当前项目是一个 FastAPI Web 框架。"})
    ),  # 任务背景
]

llm.after_input_msg_prompt = [
    MemoPrompt(template=Jinja2PromptTemplate(templates={Locale.DEFAULT: "请使用 Markdown 格式回复。"})),  # 输出格式
]

llm.after_intermediate_msg_prompt = [
    MemoPrompt(
        template=Jinja2PromptTemplate(templates={Locale.DEFAULT: "请根据工具返回结果继续完成任务。"})
    ),  # 工具调用后引导
]

Prompt 模板选择

from tfrobot.brain.chain.prompt.template.jinja2_template import Jinja2PromptTemplate
from tfrobot.schema.types import Locale

# 推荐:使用 Jinja2 模板(支持条件、循环)
template = Jinja2PromptTemplate(
    templates={
        Locale.ZH: """
你是一个{{ role }}。

{% if tools %}
可用工具:
{% for tool in tools %}
- {{ tool.name }}: {{ tool.description }}
{% endfor %}
{% endif %}

用户问题:{{ user_input.input }}
"""
    }
)

Few-Shot 学习

from tfrobot.brain.chain.llms import GPT

llm = GPT(
    name="gpt-4o",
    response_format={
        "type": "text",
        "examples": '{"name": "张三", "age": 25}\n{"name": "李四", "age": 30}',  # Few-shot 示例
    },
)

Token 优化

上下文压缩策略

  1. 自动压缩:Chain 会自动触发压缩
  2. 手动压缩:调用 collapse_context 方法
from tfrobot.brain.chain.llms import Claude
from tfrobot.schema.exceptions import ContextTooLargeError
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

llm = Claude(name="claude-3-5-sonnet-20241022")
user = BaseUser(name="用户", uid="1")
user_input = TextMessage(content="很长的问题...", creator=user)
long_conversation = [TextMessage(content=f"历史消息 {i}", creator=user) for i in range(1000)]

try:
    result = llm.complete(current_input=user_input, conversation=long_conversation)
except ContextTooLargeError as e:
    # 手动压缩
    compacted_conv, _, _, _, _ = llm.collapse_context(
        current_input=user_input, conversation=long_conversation, to_size=e.target_size
    )
    result = llm.complete(current_input=user_input, conversation=compacted_conv)

摘要模式

from tfrobot.brain.chain.llms import Claude
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

llm = Claude(name="claude-3-5-sonnet-20241022")
user = BaseUser(name="用户", uid="1")

# 历史消息自动使用摘要模式
conversation = [TextMessage(content=f"历史消息 {i}", creator=user) for i in range(100)]
user_input = TextMessage(content="当前问题", creator=user)

result = llm.complete(current_input=user_input, conversation=conversation)  # 内部自动摘要

控制知识库大小

# 截断过长的知识库
max_knowledge_length = 5000  # tokens
knowledge = "这是一段很长的知识库内容..." * 1000  # 模拟长文本
if len(knowledge) > max_knowledge_length:
    knowledge = knowledge[:max_knowledge_length]

使用 smaller models

# 简单任务使用更小的模型
from tfrobot.brain.chain.llms import GPT

# 复杂任务
complex_llm = GPT(name="gpt-4o")

# 简单任务
simple_llm = GPT(name="gpt-4o-mini")

工具调用优化

工具描述优化

from tfrobot.drive.tool.tool import tool


@tool
def search_code(query: str, language: str = "python") -> str:
    """
    搜索代码示例

    Args:
        query: 搜索关键词(如 "快速排序")
        language: 编程语言,支持 python、javascript、java 等

    Returns:
        代码示例和简要说明

    Examples:
        >>> search_code("快速排序", "python")
        "def quicksort(arr): ..."
    """
    # 工具实现
    ...

工具过滤

from tfrobot.brain.chain.llms import GPT

llm = GPT(name="gpt-4o", tool_filter="(&(Edit)(!(IDEWrite)))")  # 仅使用 Tag=Edit 且名称不为 IDEWrite 的工具

Map-Reduce 优化

from tfrobot.drive.tool.tool import tool


@tool
def batch_process(items: list[str]) -> str:
    """
    批量处理项目

    Args:
        items: 待处理的项目列表

    Returns:
        Map 模式:返回中间结果
        Reduce 模式:返回最终汇总
    """
    # Map 模式
    for item in items:
        yield f"处理结果: {item}"

    # Reduce 模式
    return f"汇总完成,共处理 {len(items)} 个项目"

错误处理

统一错误处理

from tfrobot.brain.chain.llms import Claude
from tfrobot.schema.exceptions import ContextTooLargeError
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

llm = Claude(name="claude-3-5-sonnet-20241022")
user = BaseUser(name="用户", uid="1")
user_input = TextMessage(content="很长的问题...", creator=user)
conversation = [TextMessage(content=f"历史消息 {i}", creator=user) for i in range(1000)]

try:
    result = llm.complete(current_input=user_input)
except ContextTooLargeError as e:
    # 上下文超长
    print(f"上下文超长: {e.current_size} > {e.target_size}")
    # 触发压缩
    compacted, _, _, _, _ = llm.collapse_context(
        current_input=user_input, conversation=conversation, to_size=e.target_size
    )
    result = llm.complete(current_input=user_input, conversation=compacted)
except Exception as e:
    # 其他错误
    print(f"错误: {e}")
    raise

重试策略

from tenacity import retry, stop_after_attempt, wait_exponential


@retry(
    stop=stop_after_attempt(3),
    wait=wait_exponential(multiplier=1, min=4, max=10),
)
def call_llm_with_retry(llm, user_input):
    return llm.complete(current_input=user_input)

性能优化

并发调用

import asyncio


async def batch_call_llm(llm, inputs):
    tasks = [llm.async_complete(current_input=inp) for inp in inputs]
    results = await asyncio.gather(*tasks)
    return results

缓存

import functools

from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

user = BaseUser(name="用户", uid="1")


@functools.lru_cache(maxsize=128)
def cached_llm_call(llm, query: str):
    return llm.complete(current_input=TextMessage(content=query, creator=user))

流式输出

from tfrobot.brain.chain.llms import GPT
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

llm = GPT(name="gpt-4o", stream=True)
user = BaseUser(name="用户", uid="1")
user_input = TextMessage(content="你好", creator=user)

result = llm.complete(current_input=user_input)
# result.generations[0].text 会逐步生成

成本控制

设置价格

from tfrobot.brain.chain.llms import GPT

llm = GPT(
    name="gpt-4o",
    input_price=0.005,  # 5美元/百万tokens
    output_price=0.015,  # 15美元/百万tokens
)

统计成本

from tfrobot.brain.chain.llms import GPT
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

llm = GPT(
    name="gpt-4o",
    input_price=0.005,
    output_price=0.015,
)
user = BaseUser(name="用户", uid="1")
user_input = TextMessage(content="你好", creator=user)

result = llm.complete(current_input=user_input)

# 查看成本
print(f"输入 tokens: {result.usage['prompt_tokens']}")
#> 输入 tokens: 10
print(f"输出 tokens: {result.usage['completion_tokens']}")
#> 输出 tokens: 11
print(f"总 tokens: {result.usage['total_tokens']}")
#> 总 tokens: 21

# 计算成本
input_cost = result.usage['prompt_tokens'] * llm.input_price / 1000
output_cost = result.usage['completion_tokens'] * llm.output_price / 1000
total_cost = input_cost + output_cost
print(f"总成本: ¥{total_cost:.4f}")
#> 总成本: ¥0.0002

使用更便宜的模型

from tfrobot.brain.chain.llms import GPT
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

user = BaseUser(name="用户", uid="1")
user_input = TextMessage(content="简单问题", creator=user)


def is_simple_task(msg: TextMessage) -> bool:
    """判断是否为简单任务"""
    return len(msg.content) < 50


# 简单任务使用 mini 模型
if is_simple_task(user_input):
    llm = GPT(name="gpt-4o-mini")
else:
    llm = GPT(name="gpt-4o")

多模态优化

图片 Detail 级别

from tfrobot.schema.message.msg_part import ImagePart, ImgUrl

# 不需要细节时使用 low detail
ImagePart(image_url=ImgUrl(url="path/to/image.jpg", mime_type="image/jpeg"), detail="low")  # 仅 85 tokens

# 需要细节时使用 high detail
ImagePart(image_url=ImgUrl(url="path/to/image.jpg", mime_type="image/jpeg"), detail="high")  # 根据瓦片数计算

图片预压缩

from PIL import Image


def compress_image(image_path: str, max_size: int = 1024):
    """压缩图片以减少 token 消耗"""
    img = Image.open(image_path)

    # 等比缩放
    img.thumbnail((max_size, max_size))

    # 保存
    compressed_path = image_path.replace(".", "_compressed.")
    img.save(compressed_path, quality=85)
    return compressed_path

遥测与调试

查看实际 Prompt

from tfrobot.brain.chain.llms import GPT
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

llm = GPT(name="gpt-4o")
user = BaseUser(name="用户", uid="1")
user_input = TextMessage(content="你好", creator=user)

result = llm.complete(current_input=user_input)

# 查看实际发送给 LLM 的 prompt
print(result.meta_info.get("prompt"))

查看工具调用

from tfrobot.brain.chain.llms import GPT
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser

llm = GPT(name="gpt-4o")
user = BaseUser(name="用户", uid="1")
user_input = TextMessage(content="你好", creator=user)

result = llm.complete(current_input=user_input)

# 查看工具调用
for gen in result.generations:
    if gen.tool_calls:
        for tc in gen.tool_calls:
            print(f"调用工具: {tc.function.name}")
            print(f"参数: {tc.function.parameters}")

OpenTelemetry 追踪

from tfrobot.brain.chain.llms import GPT
from tfrobot.schema.message.conversation.message_dto import TextMessage
from tfrobot.schema.users import BaseUser
from tfrobot.telemetry.tracer import tracer

llm = GPT(name="gpt-4o")
user = BaseUser(name="用户", uid="1")


@tracer.start_as_current_span("my_llm_operation")
def my_llm_function():
    user_input = TextMessage(content="你好", creator=user)
    result = llm.complete(current_input=user_input)
    return result

安全建议

API 密钥管理

import os

from tfrobot.brain.chain.llms import GPT

# 推荐:使用环境变量
api_key = os.getenv("OPENAI_API_KEY")
llm = GPT(name="gpt-4o", openai_api_key=api_key)

# 不推荐:硬编码密钥
# llm = GPT(name="gpt-4o", openai_api_key="sk-...")

输入验证

def validate_input(user_input: str) -> bool:
    """验证用户输入"""
    if len(user_input) > 10000:
        raise ValueError("输入过长")
    # 其他验证逻辑
    return True

输出过滤

from tfrobot.schema.message.llms.llm_response import LLMResult


def filter_output(result: LLMResult) -> str:
    """过滤输出内容"""
    text = result.generations[0].text
    # 过滤敏感词
    # ...
    return text

相关文档