Skip to content

第2章:核心引擎实现

2.1 Agent主循环

Agent是Nanobot2的核心引擎,负责处理用户请求、生成响应、管理上下文等核心功能。Agent采用思考-行动-观察循环(Thought-Action-Observation Loop)模式,模拟人类的决策过程。

2.1.1 核心实现

python
class Agent:
    def __init__(self, provider_manager, session_manager, message_bus):
        self.provider_manager = provider_manager
        self.session_manager = session_manager
        self.message_bus = message_bus
    
    async def process_message(self, user_id: str, channel: str, content: str) -> str:
        # 获取或创建会话
        session = self.session_manager.get_or_create_session(user_id, channel)
        
        # 添加用户消息到会话
        session.add_message("user", content)
        
        # 构建上下文
        context = self._build_context(session)
        
        # 调用LLM生成响应
        response = await self._call_llm(context)
        
        # 添加助手响应到会话
        session.add_message("assistant", response)
        
        # 发布助手响应事件
        await self.message_bus.publish("assistant.response", {
            "user_id": user_id,
            "channel": channel,
            "content": response
        })
        
        return response

2.1.2 工作流程

  1. 接收消息:从渠道接收用户消息
  2. 会话管理:获取或创建用户会话
  3. 上下文构建:基于会话历史构建上下文
  4. LLM调用:使用上下文调用LLM生成响应
  5. 响应处理:处理LLM响应并存储到会话
  6. 事件发布:发布助手响应事件
  7. 响应返回:将响应返回给渠道

2.2 上下文构建

上下文是LLM生成响应的重要依据,包含用户历史消息、系统提示和其他相关信息。Agent需要构建一个包含足够信息但又不过长的上下文。

2.2.1 上下文构建实现

python
def _build_context(self, session: Session) -> str:
    """
    构建上下文
    
    Args:
        session: 会话对象
    
    Returns:
        构建好的上下文
    """
    # 系统提示
    system_prompt = """
    你是Nanobot2,一个智能AI助手。
    你的任务是帮助用户解决问题,回答用户的问题,执行用户的命令。
    你需要保持友好、专业的态度,提供准确、有用的信息。
    
    可用技能:
    - search: 搜索网络信息
    - weather: 查询天气
    - calculator: 计算数学表达式
    - time: 获取当前时间
    
    如果你不确定如何回答,或者需要更多信息,请直接询问用户。
    """
    
    # 获取历史消息
    messages = session.get_messages(limit=20)  # 限制消息数量
    
    # 构建上下文
    context = system_prompt + "\n\n"
    
    for message in messages:
        role = message["role"]
        content = message["content"]
        context += f"{role}: {content}\n"
    
    return context

2.2.2 上下文优化

  1. 消息限制:限制历史消息数量,避免上下文过长
  2. 重要信息优先:优先保留最近的消息
  3. 系统提示优化:清晰定义助手的角色和能力
  4. 格式规范:使用统一的格式,便于LLM理解

2.3 LLM集成

LLM(大型语言模型)是Agent的核心能力来源,Nanobot2支持多种LLM提供商,包括OpenAI、Anthropic和本地模型。

2.3.1 LLM提供商抽象

python
class LLMProvider(ABC):
    @abstractmethod
    async def generate(self, prompt: str, **kwargs) -> str:
        pass

class OpenAIProvider(LLMProvider):
    def __init__(self, api_key: str, model: str = "gpt-3.5-turbo"):
        self.api_key = api_key
        self.model = model
    
    async def generate(self, prompt: str, **kwargs) -> str:
        import openai
        openai.api_key = self.api_key
        
        response = await openai.ChatCompletion.acreate(
            model=self.model,
            messages=[{"role": "user", "content": prompt}],
            **kwargs
        )
        
        return response.choices[0].message.content

class AnthropicProvider(LLMProvider):
    def __init__(self, api_key: str, model: str = "claude-2"):
        self.api_key = api_key
        self.model = model
    
    async def generate(self, prompt: str, **kwargs) -> str:
        import anthropic
        client = anthropic.Anthropic(api_key=self.api_key)
        
        response = client.completions.create(
            model=self.model,
            prompt=prompt,
            max_tokens=1024,
            **kwargs
        )
        
        return response.completion

2.3.2 提供商管理

python
class ProviderManager:
    def __init__(self):
        self.providers = {}
        self.default_provider = None
    
    def register_provider(self, name: str, provider: LLMProvider):
        self.providers[name] = provider
    
    def set_default_provider(self, name: str):
        if name in self.providers:
            self.default_provider = name
    
    def get_provider(self, name: str = None) -> LLMProvider:
        if name and name in self.providers:
            return self.providers[name]
        elif self.default_provider and self.default_provider in self.providers:
            return self.providers[self.default_provider]
        else:
            raise ValueError("No provider available")

2.4 响应生成

Agent调用LLM生成响应后,需要对响应进行处理,确保其符合预期格式和内容要求。

2.4.1 响应处理

python
async def _call_llm(self, context: str) -> str:
    """
    调用LLM生成响应
    
    Args:
        context: 上下文
    
    Returns:
        LLM生成的响应
    """
    try:
        # 获取默认提供商
        provider = self.provider_manager.get_provider()
        
        # 调用LLM生成响应
        response = await provider.generate(context)
        
        # 处理响应
        response = self._process_response(response)
        
        return response
    except Exception as e:
        print(f"调用LLM失败: {e}")
        return f"抱歉,我现在无法处理您的请求,请稍后再试。错误信息: {str(e)}"

def _process_response(self, response: str) -> str:
    """
    处理LLM响应
    
    Args:
        response: LLM生成的响应
    
    Returns:
        处理后的响应
    """
    # 去除首尾空白
    response = response.strip()
    
    # 处理空响应
    if not response:
        return "抱歉,我没有理解您的问题,请再详细说明一下。"
    
    # 返回处理后的响应
    return response

2.4.2 响应质量控制

  1. 错误处理:捕获并处理LLM调用错误
  2. 响应验证:确保响应非空且有意义
  3. 格式标准化:统一响应格式
  4. 安全检查:过滤不安全内容

2.5 核心引擎测试

2.5.1 单元测试

为核心引擎编写单元测试,确保各功能正常工作:

python
import unittest
from unittest.mock import Mock, AsyncMock
from nanobot.agent import Agent
from nanobot.session import Session

class TestAgent(unittest.TestCase):
    def setUp(self):
        # 创建模拟对象
        self.provider_manager = Mock()
        self.session_manager = Mock()
        self.message_bus = Mock()
        self.message_bus.publish = AsyncMock()
        
        # 创建模拟提供商
        self.mock_provider = Mock()
        self.mock_provider.generate = AsyncMock(return_value="测试响应")
        self.provider_manager.get_provider = Mock(return_value=self.mock_provider)
        
        # 创建模拟会话
        self.mock_session = Mock(spec=Session)
        self.mock_session.get_messages = Mock(return_value=[])
        self.session_manager.get_or_create_session = Mock(return_value=self.mock_session)
        
        # 创建Agent实例
        self.agent = Agent(self.provider_manager, self.session_manager, self.message_bus)
    
    async def test_process_message(self):
        # 测试处理消息
        response = await self.agent.process_message("user1", "cli", "你好")
        
        # 验证结果
        self.assertEqual(response, "测试响应")
        self.mock_session.add_message.assert_any_call("user", "你好")
        self.mock_session.add_message.assert_any_call("assistant", "测试响应")
        self.message_bus.publish.assert_called_once()

if __name__ == "__main__":
    unittest.main()

2.5.2 集成测试

运行完整的集成测试,确保核心引擎与其他模块正常协作:

bash
python -m pytest tests/test_agent.py -v

2.6 性能优化

2.6.1 异步处理

使用Python的asyncio库实现异步处理,提高并发性能:

python
async def process_messages(self, messages: list):
    """
    批量处理消息
    
    Args:
        messages: 消息列表
    
    Returns:
        响应列表
    """
    tasks = []
    for message in messages:
        user_id = message["user_id"]
        channel = message["channel"]
        content = message["content"]
        task = self.process_message(user_id, channel, content)
        tasks.append(task)
    
    return await asyncio.gather(*tasks)

2.6.2 缓存优化

使用缓存减少重复计算和API调用:

python
class ResponseCache:
    def __init__(self, max_size=1000):
        self.cache = {}
        self.max_size = max_size
    
    def get(self, key):
        return self.cache.get(key)
    
    def set(self, key, value):
        if len(self.cache) >= self.max_size:
            # 删除最旧的项
            oldest_key = next(iter(self.cache))
            del self.cache[oldest_key]
        self.cache[key] = value
    
    def clear(self):
        self.cache.clear()

2.7 小结

本章介绍了Nanobot2核心引擎的实现,包括:

  1. Agent主循环:处理用户请求的核心逻辑
  2. 上下文构建:为LLM提供必要的信息
  3. LLM集成:支持多种LLM提供商
  4. 响应生成:处理和优化LLM响应
  5. 测试与优化:确保核心引擎的可靠性和性能

核心引擎是Nanobot2的大脑,负责理解用户意图、生成响应和协调各模块工作。在接下来的章节中,我们将学习技能系统和多渠道集成,进一步增强Nanobot2的能力。