Skip to content

最佳实践

更新: 4/9/2026 字数: 0 字 时长: 0 分钟

本章总结 LangChain Agent 开发的最佳实践,涵盖性能、安全、可维护性等方面。

Prompt 工程

Prompt 模板结构

python
# 推荐的 Prompt 模板结构
SYSTEM_PROMPT = """# 角色定义
你是一个[角色名称],专门负责[主要职责]。

# 能力范围
你可以:
1. [能力1]
2. [能力2]
3. [能力3]

# 工作原则
- [原则1]
- [原则2]

# 输出格式
请按以下格式输出:

[输出格式说明]


# 限制
- 不要[禁止行为]
- 遇到[边界情况]时,请[处理方式]
"""

Few-shot 示例

python
SYSTEM_PROMPT = """你是一个翻译助手,将中文翻译成英文。

示例:
输入:你好世界
输出:Hello World

输入:今天天气真好
输出:The weather is nice today

输入:{input}
输出:"""

工具设计

工具设计检查清单

工具设计规范
═══════════════════════════════════════════════════════════════

命名规范
────────────────────────────────────────────────────────────
✅ 使用 snake_case
✅ 动词或动词短语开头:get_, search_, create_
✅ 名词描述对象:get_user_info, search_products

参数规范
────────────────────────────────────────────────────────────
✅ 类型注解
✅ 默认值(可选参数)
✅ Pydantic 验证
✅ 完整描述

返回规范
────────────────────────────────────────────────────────────
✅ 返回字符串
✅ 结构化输出
✅ 包含状态信息
✅ 友好错误提示
═══════════════════════════════════════════════════════════════

工具分组

python
# 按功能分组工具
TOOLS = {
    "search": [search_web, search_news, search_academic],
    "communication": [send_email, send_sms, send_notification],
    "data": [query_database, get_analytics, generate_report],
}

def get_tools_by_permission(user_role: str) -> list:
    permissions = {
        "admin": ["*"],
        "user": ["search", "data"],
        "guest": ["search"],
    }
    return permissions.get(user_role, [])

错误处理

分层错误处理

python
@tool
def robust_tool(input_data: str) -> str:
    """带错误处理的工具"""
    try:
        result = call_api(input_data)
        return result
    except ValidationError as e:
        return f"参数错误:{str(e)}"
    except RateLimitError:
        return f"请求过于频繁,请稍后再试"
    except TimeoutError:
        return f"请求超时,请稍后重试"
    except Exception as e:
        logger.error(f"Unexpected error: {str(e)}")
        return f"发生未知错误"

重试装饰器

python
import time
from functools import wraps

def retry(max_attempts: int = 3, delay: float = 1.0, backoff: float = 2.0):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except (RateLimitError, TimeoutError) as e:
                    if attempt < max_attempts - 1:
                        wait = delay * (backoff ** attempt)
                        time.sleep(wait)
        return wrapper
    return decorator

性能优化

缓存策略

python
from functools import lru_cache

@lru_cache(maxsize=100)
def cached_weather(city: str) -> str:
    """带缓存的天气查询"""
    return fetch_weather_from_api(city)

消息截断

python
from langchain_core.messages import trim_messages, get_buffer_string

def trim_history(messages: list, max_tokens: int = 8000) -> list:
    """截断消息历史"""
    buffer = get_buffer_string(messages)
    if len(buffer) > max_tokens * 4:
        trimmer = trim_messages(
            max_tokens=max_tokens,
            strategy="last",
            include_system=True
        )
        return trimmer.invoke(messages)
    return messages

安全考虑

输入验证

python
from pydantic import BaseModel, Field

class SafeInput(BaseModel):
    query: str = Field(..., max_length=500)
    email: str | None = None

def sanitize_input(user_input: str) -> str:
    """清理用户输入"""
    dangerous = ["<script>", "DROP TABLE", "rm -rf"]
    for pattern in dangerous:
        user_input = user_input.replace(pattern, "")
    return user_input.strip()

敏感信息处理

python
import re

def mask_sensitive(text: str) -> str:
    """脱敏处理"""
    text = re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', text)  # 手机号
    text = re.sub(r'([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})', r'\1***@\2', text)
    return text

测试策略

单元测试

python
# tests/test_tools.py
import pytest
from tools import get_weather, calculator

class TestWeatherTool:
    def test_get_weather_known_city(self):
        result = get_weather("北京")
        assert "北京" in result
        assert "°C" in result

    def test_get_weather_unknown_city(self):
        result = get_weather("不存在城市")
        assert "不支持" in result or "未知" in result

class TestCalculator:
    def test_addition(self):
        assert calculator("2 + 3") == "5"
    
    def test_invalid_expression(self):
        assert "错误" in calculator("2 +")

集成测试

python
# tests/test_agent.py
import pytest
from langchain.agents import create_agent
from langgraph.checkpoint.memory import InMemorySaver

@pytest.fixture
def agent():
    return create_agent(
        model="anthropic:claude-sonnet-4-6",
        tools=[get_weather, calculator],
        system_prompt="你是一个助手",
        checkpointer=InMemorySaver()
    )

class TestAgent:
    def test_simple_query(self, agent):
        result = agent.invoke({
            "messages": [{"role": "user", "content": "你好"}]
        })
        assert len(result["messages"]) >= 2
    
    def test_memory(self, agent):
        config = {"configurable": {"thread_id": "test_memory"}}
        agent.invoke(
            {"messages": [{"role": "user", "content": "记住我喜欢蓝色"}]},
            config=config
        )
        result = agent.invoke(
            {"messages": [{"role": "user", "content": "我喜欢什么颜色"}]},
            config=config
        )
        assert "蓝色" in result["messages"][-1]["content"]

本章小结

最佳实践要点
────────────────────────────────────────────────────────

Prompt 工程
✅ 清晰的角色定义
✅ 详细的工具描述
✅ 适当的示例

工具设计
✅ 命名规范
✅ 类型注解
✅ 参数验证

错误处理
✅ 分层处理
✅ 重试机制
✅ 友好提示

性能优化
✅ 缓存策略
✅ 消息截断
✅ 异步执行

安全
✅ 输入验证
✅ 敏感信息脱敏
✅ 权限控制

Released under the MIT License.