agentic rag architecture

Agentic RAG 架构:当 RAG 遇到智能体

从传统 RAG 到 Agentic RAG:一次范式跃迁 检索增强生成(Retrieval-Augmented Generation, RAG)在过去两年里几乎成了大模型应用的标配方案。但如果你在实际业务中部署过 RAG 系统,大概率经历过这些痛点:检索结果不相关却仍被塞进上下文、面对复杂问题无法分步检索、知识库更新滞后导致回答过时、多跳推理任务中检索策略僵化且无从调整。这些问题的根源在于传统 RAG 本质上是一个线性的、一次性的管道——查询进来,检索一轮,拼上下文,生成回答,结束。 Agentic RAG 的核心思路是把这个线性管道升级为一个闭环的、自适应的智能体系统。智能体不再被动地执行"检索→生成"的固定流程,而是能够自主判断何时需要检索、检索什么、检索结果是否足够、是否需要多轮检索、何时停止以及如何综合多源信息给出最终答案。这就像是把一个只会按食谱做菜的厨师,升级成了一个能根据食材、客人喜好和现场情况即兴创作的大厨。 Agentic RAG 的核心架构组件 1. 智能体控制器(Agent Controller) 整个系统的大脑。它负责理解用户意图,制定检索策略,决定下一步行动。与传统 RAG 中固定的流程不同,控制器是一个基于 LLM 的决策引擎,能够在"检索"、“推理”、“工具调用”、“回答"之间动态切换。 控制器的工作循环可以这样描述: 用户查询 → 意图分析 → 策略制定 → 行动执行 → 结果评估 → ├─ 信息充分 → 生成回答 ├─ 信息不足 → 重新检索(调整查询) └─ 需要工具 → 调用外部工具 这个循环本质上是一个 ReAct(Reasoning + Acting)模式的变体,但加入了专门的检索策略模块。 2. 多级检索引擎(Multi-Stage Retrieval Engine) 传统 RAG 通常只有一层向量检索。Agentic RAG 则部署了多级检索策略: 语义检索层:基于向量数据库的稠密检索,处理模糊语义匹配 关键词检索层:基于 BM25 等算法的稀疏检索,处理精确术语匹配 结构化检索层:知识图谱查询,处理实体关系推理 实时检索层:联网搜索 API,处理最新信息获取 智能体控制器会根据查询类型动态选择检索策略。比如面对"对比 React 和 Vue 在 2025 年的性能表现"这样的问题,控制器可能会先做语义检索找到相关技术文档,再通过知识图谱获取两个框架的属性对比,最后通过联网搜索补充 2025 年的最新基准数据。 ...

2026-06-26 · 2 min · 252 words · 硅基 AGI 探索者
multimodal agent design

多模态智能体设计:图文音视一体化架构

从单模态到多模态:智能体的进化跃迁 2026 年的智能体已经不再满足于"只能读文字"的局限。用户希望 Agent 能看图说话、听音理解、看视频分析——这正是多模态智能体(Multimodal Agent)要解决的问题。 多模态智能体的核心挑战不在于"能不能处理图片"(GPT-4o 早就做到了),而在于如何让不同模态的信息在一个统一的推理框架中协同工作。一个成熟的多模态智能体需要做到: 跨模态理解:将图片中的信息与文本上下文融合 多模态推理:基于视觉证据进行逻辑推断 模态转换:文本→图片生成、图片→语音描述 时序处理:理解视频中的时间维度信息 本文将系统阐述多模态智能体的架构设计,并给出可落地的实现方案。 整体架构 ┌──────────────────────────────────────────────────────────────┐ │ Multimodal Agent Core │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Vision │ │ Audio │ │ Video │ │ Text │ │ │ │ Module │ │ Module │ │ Module │ │ Module │ │ │ └─────┬─────┘ └─────┬────┘ └─────┬────┘ └─────┬────┘ │ │ │ │ │ │ │ │ ▼ ▼ ▼ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Multimodal Fusion Layer │ │ │ │ (Cross-Modal Attention + Shared Embedding Space) │ │ │ └──────────────────────────┬───────────────────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ Unified Reasoning Engine │ │ │ │ (LLM Core with Multimodal Capabilities) │ │ │ └──────────────────────────┬───────────────────────────┘ │ │ │ │ │ ┌─────────────────┼─────────────────┐ │ │ ▼ ▼ ▼ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Tool Hub │ │ Memory Store │ │ Output Gen │ │ │ │ (Multimodal) │ │ (Vector+Graph)│ │ (Text/Img/ │ │ │ │ │ │ │ │ Audio/Video)│ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ └──────────────────────────────────────────────────────────────┘ 模态编码器:将世界转化为向量 视觉编码器 视觉模块负责将图片编码为 LLM 可理解的嵌入向量。当前主流方案对比: ...

2026-06-26 · 8 min · 1517 words · 硅基 AGI 探索者
event driven agent

事件驱动 Agent 架构:从 Webhook 到实时响应

1. 从轮询到事件驱动 传统 Agent 采用轮询模式:定期检查是否有新任务或状态变化。这种模式简单但低效——要么延迟高(轮询间隔长),要么浪费资源(轮询间隔短)。 事件驱动架构(EDA)将 Agent 从"主动检查"转变为"被动响应":当有意义的事件发生时,系统主动通知 Agent 处理。核心优势: 低延迟:事件发生即触发,无需等待轮询周期 低资源消耗:无事件时 Agent 处于休眠状态 天然解耦:事件生产者和消费者完全分离 弹性扩展:事件积压时可动态增加消费者 2. 事件驱动 Agent 整体架构 ┌──────────┐ ┌──────────┐ ┌──────────┐ │ GitHub │ │ Slack │ │ Sensor │ 事件源 │ Webhook │ │ Events │ │ Data │ └────┬─────┘ └────┬─────┘ └────┬─────┘ │ │ │ ▼ ▼ ▼ ┌────────────────────────────────────────┐ │ Event Ingestion Layer │ │ (API Gateway / Message Queue) │ └───────────────────┬────────────────────┘ │ ▼ ┌────────────────────────────────────────┐ │ Event Router / Filter │ └───────────────────┬────────────────────┘ │ ┌───────────┼───────────┐ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Agent A │ │ Agent B │ │ Agent C │ 事件消费者 │(Coder) │ │(Reviewer)│ │(Notifier)│ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────────────────────────┐ │ Action Executor │ │ (API calls, DB writes, etc.) │ └─────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ Event Publisher (新事件) │ └─────────────────────────────────────┘ 3. 事件模型设计 3.1 事件 Schema from pydantic import BaseModel, Field from datetime import datetime from enum import Enum from typing import Any, Optional import uuid class EventSeverity(str, Enum): INFO = "info" WARNING = "warning" ERROR = "error" CRITICAL = "critical" class AgentEvent(BaseModel): """统一事件格式 - CloudEvents 兼容""" event_id: str = Field(default_factory=lambda: str(uuid.uuid4())) event_type: str # "github.pr.opened", "agent.task.completed" source: str # 事件来源标识 subject: str = "" # 事件主题(如 PR #123) data: dict[str, Any] # 事件负载 time: datetime = Field(default_factory=datetime.now) severity: EventSeverity = EventSeverity.INFO trace_id: str = "" # 分布式追踪 ID correlation_id: str = "" # 关联 ID(同一会话) # 事件版本控制 spec_version: str = "1.0" data_content_type: str = "application/json" class TaskCompletedEvent(AgentEvent): event_type: str = "agent.task.completed" data: dict[str, Any] = Field(description="包含 task_id, result, duration 等") class ErrorEvent(AgentEvent): event_type: str = "agent.error" severity: EventSeverity = EventSeverity.ERROR 3.2 事件注册表 class EventRegistry: """事件类型注册表 - 管理 Schema 和路由规则""" def __init__(self): self._schemas: dict[str, type[BaseModel]] = {} self._handlers: dict[str, list[callable]] = {} def register(self, event_type: str, schema: type[BaseModel]): self._schemas[event_type] = schema def subscribe(self, event_type: str, handler: callable): self._handlers.setdefault(event_type, []).append(handler) def get_handlers(self, event_type: str) -> list[callable]: # 支持通配符匹配: "github.pr.*" 匹配 "github.pr.opened" handlers = self._handlers.get(event_type, []) for pattern, h_list in self._handlers.items(): if "*" in pattern: prefix = pattern.replace("*", "") if event_type.startswith(prefix): handlers.extend(h_list) return handlers def validate(self, event: AgentEvent) -> bool: schema = self._schemas.get(event.event_type) if schema: schema(**event.model_dump()) return True 4. 事件总线实现 4.1 内存事件总线(单机) import asyncio from collections import defaultdict from concurrent.futures import ThreadPoolExecutor class InMemoryEventBus: def __init__(self, max_workers: int = 10): self._subscribers: dict[str, list] = defaultdict(list) self._executor = ThreadPoolExecutor(max_workers=max_workers) self._dead_letter_queue: list[tuple[AgentEvent, Exception]] = [] self._middleware: list[callable] = [] def use(self, middleware: callable): """注册中间件:日志、认证、限流等""" self._middleware.append(middleware) async def subscribe(self, event_type: str, handler: callable): self._subscribers[event_type].append(handler) async def publish(self, event: AgentEvent): # 执行中间件链 for mw in self._middleware: event = await mw(event) if event is None: return # 被中间件拦截 handlers = self._subscribers.get(event.event_type, []) # 匹配通配符订阅 for pattern, h_list in self._subscribers.items(): if "*" in pattern: prefix = pattern.replace("*", "") if event.event_type.startswith(prefix): handlers.extend(h_list) # 并行执行所有处理器 tasks = [self._safe_execute(h, event) for h in handlers] await asyncio.gather(*tasks, return_exceptions=True) async def _safe_execute(self, handler: callable, event: AgentEvent): try: if asyncio.iscoroutinefunction(handler): await handler(event) else: await asyncio.get_event_loop().run_in_executor( self._executor, handler, event ) except Exception as e: self._dead_letter_queue.append((event, e)) # 发布错误事件 error_event = ErrorEvent( source="event_bus", data={"original_event": event.event_id, "error": str(e)}, trace_id=event.trace_id, ) await self.publish(error_event) 4.2 Kafka 事件总线(分布式) from aiokafka import AIOKafkaProducer, AIOKafkaConsumer import json class KafkaEventBus: def __init__(self, bootstrap_servers: str = "localhost:9092"): self.bootstrap_servers = bootstrap_servers self._producer: AIOKafkaProducer = None self._consumers: list[AIOKafkaConsumer] = [] self._handlers: dict[str, callable] = {} async def start(self): self._producer = AIOKafkaProducer( bootstrap_servers=self.bootstrap_servers, value_serializer=lambda v: json.dumps(v.model_dump(mode="json")).encode(), key_serializer=lambda k: k.encode() if k else None, acks="all", # 等待所有副本确认 enable_idempotence=True, # 幂等生产者 compression_type="lz4", # 压缩 max_in_flight_requests_per_connection=5, ) await self._producer.start() async def publish(self, event: AgentEvent, topic: str = None): topic = topic or event.event_type.split(".")[0] # 按事件类型分 Topic partition_key = event.correlation_id or event.source await self._producer.send_and_wait( topic, event, key=partition_key ) async def subscribe(self, event_type: str, handler: callable, group_id: str = "agent-group"): topic = event_type.split(".")[0] consumer = AIOKafkaConsumer( topic, bootstrap_servers=self.bootstrap_servers, group_id=group_id, value_deserializer=lambda v: AgentEvent(**json.loads(v.decode())), auto_offset_reset="latest", enable_auto_commit=False, ) await consumer.start() self._consumers.append(consumer) self._handlers[event_type] = handler async for msg in consumer: event = msg.value if event.event_type == event_type or event_type.endswith("*"): try: await handler(event) await consumer.commit() except Exception as e: # 重试或进入死信队列 await self._handle_error(event, e) async def stop(self): await self._producer.stop() for c in self._consumers: await c.stop() 5. Agent 状态机 事件驱动 Agent 的核心是一个状态机:不同事件触发不同状态转换。 ...

2026-06-25 · 7 min · 1381 words · AI 实战派
agent memory architecture

Agent 记忆架构设计:短期/长期/情景记忆

为什么 Agent 需要记忆 没有记忆的 Agent 就像金鱼——每次对话都从零开始。你告诉它你的名字,下一轮它就忘了。你纠正过它的错误,它下次照犯。 记忆系统让 Agent 能够: 记住用户偏好和历史交互 从过去经验中学习 保持跨会话的上下文一致性 在长任务中不丢失关键信息 记忆类型体系 人类认知科学启发 记忆类型 持续时间 容量 Agent 对应 存储方案 工作记忆 秒-分钟 4±2 项 当前对话上下文 LLM Context Window 短期记忆 分钟-小时 有限 当前会话摘要 内存/Redis 长期记忆 天-永久 近无限 用户偏好、知识 向量库 + 关系库 情景记忆 事件级 大 具体交互记录 时序向量库 架构总览 ┌──────────────────────────────────────────────┐ │ Agent 主循环 │ │ │ │ ┌─────────┐ ┌─────────┐ ┌──────────────┐ │ │ │ 工作记忆 │ │ 短期记忆 │ │ 长期记忆 │ │ │ │ Context │←→│ Session │←→│ Persistent │ │ │ │ Window │ │ Summary │ │ Store │ │ │ └─────────┘ └─────────┘ └──────────────┘ │ │ │ │ │ │ │ │ │ ┌────────┼────────┐ │ │ │ │ │ │ │ │ │ │ │ ┌──┴──┐ ┌───┴───┐ ┌──┴──┐ │ │ │ │语义 │ │情景 │ │程序 │ │ │ │ │记忆 │ │记忆 │ │记忆 │ │ │ │ │向量 │ │时序 │ │图 │ │ │ │ └─────┘ └───────┘ └─────┘ │ │ │ │ ┌────┴────────────┴────────────────────────┐│ │ │ 记忆管理器 ││ │ │ 写入 → 压缩 → 检索 → 遗忘 → 巩固 ││ │ └────────────────────────────────────────────┘│ └──────────────────────────────────────────────┘ 工作记忆:上下文窗口管理 from dataclasses import dataclass, field from typing import List, Dict @dataclass class WorkingMemory: """工作记忆: 管理 LLM 上下文窗口""" max_tokens: int = 128000 reserved_for_response: int = 4096 messages: List[dict] = field(default_factory=list) def add(self, role: str, content: str): self.messages.append({"role": role, "content": content}) self._evict_if_needed() def add_system(self, content: str): """系统消息放在最前面,不被驱逐""" self.messages.insert(0, {"role": "system", "content": content}) def _evict_if_needed(self): """当超过 token 限制时,驱逐最旧的对话""" while self._count_tokens() > self.max_tokens - self.reserved_for_response: if len(self.messages) <= 1: break # 找到第一个非 system 消息并移除 for i, msg in enumerate(self.messages): if msg["role"] != "system": evicted = self.messages.pop(i) # 触发压缩: 被驱逐的消息需要被压缩到短期记忆 self._on_evict(evicted) break def _count_tokens(self) -> int: import tiktoken enc = tiktoken.encoding_for_model("gpt-4o") return sum(len(enc.encode(m["content"])) for m in self.messages) def _on_evict(self, evicted_msg: dict): """被驱逐的消息回调,交给短期记忆处理""" # 由 MemoryManager 注册 pass def get_context(self) -> List[dict]: """获取当前上下文""" return self.messages.copy() 短期记忆:会话级摘要 class ShortTermMemory: """短期记忆: 当前会话的压缩摘要""" def __init__(self): self.summary = "" self.key_points: List[str] = [] self.token_budget = 2000 # 摘要不超 2000 token async def compress(self, messages: List[dict]) -> str: """将多轮对话压缩为摘要""" conversation = "\n".join( f"{m['role']}: {m['content'][:200]}" for m in messages ) prompt = f"""请将以下对话压缩为简洁摘要,保留: 1. 用户的核心需求 2. 已确定的关键事实 3. 未解决的问题 4. 用户的明确偏好 对话: {conversation} 摘要:""" response = await llm_call(prompt, max_tokens=self.token_budget) self.summary = response return response async def extract_key_points(self, messages: List[dict]) -> List[str]: """提取关键信息点""" prompt = f"""从以下对话中提取关键信息点,每点一行: {chr(10).join(m['content'][:200] for m in messages)} 关键信息:""" response = await llm_call(prompt, max_tokens=500) self.key_points = response.strip().split('\n') return self.key_points def to_context(self) -> str: """转换为可注入上下文的文本""" parts = [] if self.summary: parts.append(f"之前的对话摘要:\n{self.summary}") if self.key_points: parts.append(f"关键信息:\n" + "\n".join(f"- {p}" for p in self.key_points)) return "\n\n".join(parts) 长期记忆:持久化存储 语义记忆(向量库) class SemanticMemory: """语义记忆: 存储事实和知识,向量检索""" def __init__(self, vector_store, embed_model): self.store = vector_store self.embed = embed_model async def remember(self, content: str, metadata: dict = None): """记住一条信息""" embedding = await self.embed(content) await self.store.upsert({ "id": self._generate_id(content), "values": embedding, "metadata": { "content": content, "type": "semantic", "created_at": datetime.now().isoformat(), **(metadata or {}) } }) async def recall(self, query: str, top_k: int = 5) -> List[dict]: """检索相关记忆""" query_embedding = await self.embed(query) results = await self.store.query( vector=query_embedding, top_k=top_k, filter={"type": {"$eq": "semantic"}} ) return [ { "content": r.metadata["content"], "score": r.score, "metadata": r.metadata } for r in results.matches ] async def forget(self, content_id: str): """主动遗忘""" await self.store.delete(ids=[content_id]) 情景记忆(时序事件) class EpisodicMemory: """情景记忆: 记录具体交互事件,支持时间检索""" def __init__(self, db): self.db = db # PostgreSQL + pgvector async def record(self, event: dict): """记录一个交互事件""" await self.db.execute( """ INSERT INTO episodic_memory (event_id, user_id, timestamp, input, output, outcome, context_snapshot, embedding) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) """, event["id"], event["user_id"], datetime.now(), event["input"], event["output"], event["outcome"], json.dumps(event.get("context", {})), event.get("embedding") ) async def recall_by_time(self, user_id: str, start: datetime, end: datetime) -> List[dict]: """按时间范围回忆""" rows = await self.db.fetch( """SELECT * FROM episodic_memory WHERE user_id = $1 AND timestamp BETWEEN $2 AND $3 ORDER BY timestamp DESC""", user_id, start, end ) return [dict(r) for r in rows] async def recall_similar(self, user_id: str, query_embedding: list, top_k: int = 5) -> List[dict]: """检索相似的历史事件""" rows = await self.db.fetch( """SELECT *, embedding <=> $1 as distance FROM episodic_memory WHERE user_id = $2 ORDER BY embedding <=> $1 LIMIT $3""", query_embedding, user_id, top_k ) return [dict(r) for r in rows] 程序记忆(知识图谱) class ProceduralMemory: """程序记忆: 存储技能、流程、因果关系(图结构)""" def __init__(self, graph_db): self.graph = graph_db # Neo4j async def learn_procedure(self, name: str, steps: List[str], triggers: List[str]): """学习一个新流程""" await self.graph.execute( """ CREATE (p:Procedure {name: $name}) WITH p UNWIND $steps as step_text CREATE (s:Step {text: step_text}) CREATE (p)-[:HAS_STEP]->(s) WITH p UNWIND $triggers as trigger CREATE (t:Trigger {text: trigger}) CREATE (t)-[:ACTIVATES]->(p) """, name=name, steps=steps, triggers=triggers ) async def recall_procedure(self, context: str) -> List[dict]: """根据上下文检索相关流程""" result = await self.graph.execute( """ MATCH (t:Trigger)-[:ACTIVATES]->(p:Procedure)-[:HAS_STEP]->(s:Step) WHERE $context CONTAINS t.text RETURN p.name as procedure, collect(s.text) as steps """, context=context ) return [dict(r) for r in result] 记忆管理器:统一调度 class MemoryManager: """统一记忆管理器""" def __init__(self): self.working = WorkingMemory() self.short_term = ShortTermMemory() self.semantic = SemanticMemory(...) self.episodic = EpisodicMemory(...) self.procedural = ProceduralMemory(...) self.recall_count = 0 async def think(self, user_input: str, user_id: str) -> str: """带记忆的思考过程""" # 1. 从长期记忆检索相关信息 semantic_results = await self.semantic.recall(user_input, top_k=3) episodic_results = await self.episodic.recall_similar( user_id, await self.embed(user_input), top_k=3 ) procedures = await self.procedural.recall_procedure(user_input) # 2. 组装上下文 context_parts = [] if self.short_term.summary: context_parts.append(self.short_term.to_context()) if semantic_results: context_parts.append("相关知识:\n" + "\n".join(f"- {r['content']}" for r in semantic_results)) if episodic_results: context_parts.append("历史交互:\n" + "\n".join(f"- {r['input']} → {r['output']}" for r in episodic_results)) if procedures: context_parts.append("可用流程:\n" + "\n".join(f"- {p['procedure']}: {p['steps']}" for p in procedures)) context = "\n\n".join(context_parts) # 3. 注入工作记忆 if context: self.working.add("system", f"记忆上下文:\n{context[:4000]}") self.working.add("user", user_input) # 4. 生成回复 response = await llm_call(self.working.get_context()) self.working.add("assistant", response) # 5. 异步写入记忆 asyncio.create_task(self._consolidate(user_input, response, user_id)) return response async def _consolidate(self, input: str, output: str, user_id: str): """记忆巩固: 筛选重要信息写入长期记忆""" # 判断是否值得记住 importance = await self._assess_importance(input, output) if importance > 0.7: # 高重要性: 写入语义记忆 + 情景记忆 await self.semantic.remember( f"用户说了: {input}\n助手回答: {output}", metadata={"importance": importance, "user_id": user_id} ) # 总是记录情景记忆 await self.episodic.record({ "id": str(uuid4()), "user_id": user_id, "input": input, "output": output, "outcome": "success", "embedding": await self.embed(input), }) async def _assess_importance(self, input: str, output: str) -> float: """评估信息重要性 0-1""" prompt = f"""评估以下交互的信息重要性(0-1): 输入: {input[:200]} 输出: {output[:200]} 评分标准: - 0.9+: 用户明确要求记住/涉及核心偏好 - 0.7-0.8: 包含重要事实或决策 - 0.5-0.6: 有一定参考价值 - 0.3-0.4: 闲聊但含少量信息 - 0.0-0.2: 纯闲聊无信息 只输出数字:""" return float(await llm_call(prompt, max_tokens=10)) 遗忘机制 class ForgettingMechanism: """遗忘机制: 防止记忆膨胀""" async def decay(self, user_id: str): """基于时间的记忆衰减""" await self.db.execute( """ UPDATE semantic_memory SET importance = importance * 0.95 -- 每天衰减5% WHERE user_id = $1 AND last_accessed < NOW() - INTERVAL '1 day' """, user_id ) # 删除低重要性记忆 await self.db.execute( """ DELETE FROM semantic_memory WHERE user_id = $1 AND importance < 0.1 """, user_id ) async def deduplicate(self, user_id: str): """去重: 合并语义相似的记忆""" # 找到相似度 > 0.9 的记忆对 duplicates = await self.db.fetch( """ SELECT a.id as id_a, b.id as id_b, a.content as content_a, b.content as content_b FROM semantic_memory a JOIN semantic_memory b ON a.id < b.id WHERE a.user_id = $1 AND b.user_id = $1 AND a.embedding <=> b.embedding < 0.1 """, user_id ) for dup in duplicates: # 合并: 保留更详细的,删除另一个 longer = dup['content_a'] if len(dup['content_a']) > len(dup['content_b']) else dup['content_b'] shorter_id = dup['id_b'] if len(dup['content_a']) > len(dup['content_b']) else dup['id_a'] await self.db.execute("DELETE FROM semantic_memory WHERE id = $1", shorter_id) async def compress_old_memories(self, user_id: str, days: int = 30): """压缩旧记忆: 把多条相关记忆合并为一条摘要""" old_memories = await self.db.fetch( """ SELECT content FROM semantic_memory WHERE user_id = $1 AND created_at < NOW() - INTERVAL '$2 days' ORDER BY created_at """, user_id, days ) if len(old_memories) < 10: return # 用 LLM 合并 memories_text = "\n".join(m['content'] for m in old_memories) summary = await llm_call( f"将以下记忆合并为简洁摘要,保留关键信息:\n{memories_text}" ) # 删除旧记忆,写入摘要 await self.db.execute( "DELETE FROM semantic_memory WHERE user_id = $1 AND created_at < NOW() - INTERVAL '$2 days'", user_id, days ) await self.semantic.remember(summary, metadata={"compressed": True}) MemGPT / Letta 架构参考 MemGPT (现 Letta) 的核心思想是把操作系统的虚拟内存概念引入 LLM: ...

2026-06-25 · 7 min · 1414 words · AI 实战派
codex agent loop architecture

Codex Agent Loop 架构解析:感知-决策-行动-记忆

Agent Loop 是什么 传统 AI 助手的工作模式是"一问一答":用户输入 → 模型生成回答 → 结束。而 Agent Loop 是一个自主执行循环,模型会持续感知环境、做出决策、执行行动,直到任务完成。 用户: "把项目里所有的 console.log 替换为 logger.info" 传统 AI: → 生成一段 sed 命令给用户复制粘贴 Codex Agent Loop: → 循环1: 扫描项目,找到 47 个含 console.log 的文件 → 循环2: 逐文件替换,记录修改 → 循环3: 运行测试,发现 2 个测试失败 → 循环4: 分析失败原因,修复测试 → 循环5: 再次运行测试,全部通过 → 循环6: 生成 git commit → 输出: 修改了 47 个文件,替换了 132 处,测试全部通过 四阶段执行循环 1. 感知(Perceive) 感知阶段收集完成任务所需的所有上下文信息: # 伪代码:感知阶段 def perceive(task: str) -> Environment: env = Environment() # 解析任务意图 env.intent = parse_intent(task) # 读取文件系统状态 env.files = scan_workspace() # 检查运行环境 env.runtime = detect_runtime() # Node.js? Python? Docker? # 获取 Git 状态 env.git = get_git_status() # 检查网络连通性 env.network = check_network() return env 感知的具体内容: ...

2026-06-25 · 5 min · 949 words · AI 实战派
hermes dual llm design

Hermes 双 LLM 架构:主模型+复盘模型协同

单模型的问题 大多数 Agent 框架使用单个 LLM 完成所有工作:理解指令、规划任务、调用工具、生成回复、总结经验。这带来三个问题: 成本高:用 GPT-4o 做经验总结是大材小用,总结任务用 Llama 3 8B 就够了 延迟高:任务执行完后还要等同一个模型完成总结才能返回 质量妥协:为了省成本用便宜模型,执行质量打折;用好模型,总结又太贵 Hermes 的解法是双 LLM 架构:一个主模型负责"干活",一个轻量复盘模型负责"学习和记忆"。 架构全景 用户消息 │ ▼ ┌──────────────┐ │ 主 LLM │ ← GPT-4o / Claude / Qwen(强大但昂贵) │ (执行层) │ │ │ │ · 任务理解 │ │ · 规划决策 │ │ · 工具调用 │ │ · 结果生成 │ └──────┬───────┘ │ │ 同步返回结果给用户 ▼ 用户收到回复 │ │ 异步触发(不阻塞用户) ▼ ┌──────────────┐ │ 复盘 LLM │ ← Llama 3 8B / Qwen 7B(轻量但够用) │ (学习层) │ │ │ │ · 经验总结 │ │ · 技能提炼 │ │ · 记忆更新 │ │ · 画像修正 │ └──────────────┘ 关键点:复盘 LLM 完全异步执行,用户不需要等待学习过程完成。 ...

2026-06-25 · 4 min · 684 words · AI 实战派
llm gateway implementation

LLM API 网关实现:多模型路由/限流/缓存/审计

为什么需要 LLM API 网关 当你的团队同时使用 OpenAI、Anthropic、本地模型等多个 LLM 提供商时,直接在业务代码中调用各家 API 会带来一系列问题:密钥散落各处、无法统一限流、缺乏调用审计、模型切换成本高。LLM API 网关就是解决这些问题的中间层。 ┌──────────────────────────────────────────────────────┐ │ 业务服务层 │ │ (Chat UI / RAG / Agent / Code Gen) │ └──────────────────┬───────────────────────────────────┘ │ 统一 API: POST /v1/chat/completions ┌──────────────────▼───────────────────────────────────┐ │ LLM API Gateway │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌────────────┐ │ │ │ 路由引擎 │ │ 限流器 │ │ 缓存层 │ │ 审计日志 │ │ │ └─────────┘ └─────────┘ └─────────┘ └────────────┘ │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ 密钥管理 │ │ 重试器 │ │ 负载均衡│ │ │ └─────────┘ └─────────┘ └─────────┘ │ └──────┬──────────┬──────────┬──────────┬─────────────┘ │ │ │ │ ┌────▼────┐┌───▼────┐┌───▼─────┐┌───▼──────┐ │ OpenAI ││Claude ││ Llama ││ Qwen │ │ API ││ API ││ Local ││ API │ └─────────┘└────────┘└─────────┘└──────────┘ 多模型路由 路由引擎是网关的核心。它根据任务复杂度、成本预算、延迟要求将请求分发到最合适的模型。 ...

2026-06-25 · 4 min · 842 words · AI 实战派
openclaw architecture deep

OpenClaw 架构深度解析:Agent Loop 执行循环

Agent Loop:龙虾的大脑 OpenClaw 的核心是一个称为 Agent Loop 的执行循环。这不是简单的 while(true) 轮询,而是一个融合了感知、决策、行动、记忆的完整认知架构。 ┌─────────────────────────────────────────┐ │ Agent Loop │ │ │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ 感知 │───▶│ 决策 │───▶│ 行动 │ │ │ │Perceive│ │Decide│ │ Act │ │ │ └──┬───┘ └──────┘ └──┬───┘ │ │ │ │ │ │ │ ┌──────┐ │ │ │ └────│ 记忆 │◀───────────┘ │ │ │Memory│ │ │ └──────┘ │ └─────────────────────────────────────────┘ 每一轮循环包含四个阶段,下面逐一拆解。 1. 感知层(Perceive) 感知层负责接收和解析输入信号,包括: 用户消息:来自 Telegram、WhatsApp、Discord 等 50+ 渠道 定时触发:cron 任务、心跳轮询 系统事件:文件变更、进程状态、设备传感器 Agent 间通信:多 Agent 协作时的消息传递 interface Perception { source: "user" | "cron" | "system" | "agent"; channel: string; // "telegram", "webchat", "cron" ... rawContent: string; // 原始内容 metadata: { timestamp: number; priority: "low" | "normal" | "high" | "urgent"; context?: Context; // 上下文继承 }; } 感知层的关键设计是多路复用。OpenClaw 可以同时监听多个渠道的消息,通过消息网关统一格式后送入决策层。这就像龙虾的触角——同时感知水流、温度、化学信号。 ...

2026-06-25 · 4 min · 657 words · AI 实战派
transformer architecture deep

Transformer 架构深度解析:从 Attention 到 GPT

1. Transformer 的诞生与核心思想 2017 年 Google 发表《Attention Is All You Need》,Transformer 彻底取代了 RNN/LSTM 的序列建模范式。其核心创新:完全基于注意力机制,消除循环结构,实现高度并行化训练。 Transformer 的三大设计支柱: 组件 作用 解决的问题 Self-Attention 捕捉序列内任意位置间的依赖 RNN 长距离梯度消失 Positional Encoding 注入位置信息 注意力本身是排列不变的 Residual + LayerNorm 稳定深层网络训练 深层网络梯度退化 2. 自注意力机制(Self-Attention) 2.1 公式推导 给定输入序列 $X \in \mathbb{R}^{n \times d}$,通过三个线性投影得到 Query、Key、Value: $$Q = XW_Q, \quad K = XW_K, \quad V = XW_V$$ 注意力计算公式: $$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$ 其中 $\sqrt{d_k}$ 是缩放因子,防止内积值过大导致 softmax 梯度饱和。 为什么除以 $\sqrt{d_k}$? 当 $d_k$ 较大时,$QK^T$ 的方差为 $d_k$(假设 $Q, K$ 各分量独立标准正态),softmax 输入过大时梯度趋近于零。缩放后方差恢复为 1。 ...

2026-06-24 · 4 min · 724 words · AI 实战派
rag architecture advanced

高级 RAG 架构模式:超越简单检索

超越朴素 RAG 朴素 RAG 的流程是:用户提问 -> 检索 top-K 文档 -> 拼接到 Prompt -> LLM 生成。这对简单问题够用,但面对复杂问题力不从心。本文介绍 6 种高级 RAG 架构模式。 模式一览 模式 核心思想 适用场景 复杂度 多跳检索 分步检索,每步基于前步结果 多跳推理问题 中 递归检索 先粗后细,分层检索 层级结构文档 中 自适应检索 LLM 决定是否检索/检索什么 不确定是否需要检索 高 Self-RAG LLM 自我反思检索质量 高质量要求 高 CRAG 检索质量评估+Web兜底 知识库覆盖不全 高 模块化 RAG 可插拔模块组合 生产环境灵活部署 高 1. 多跳检索(Multi-Hop Retrieval) 面对"张三所在公司的CEO毕业于哪所大学?“这种问题,单次检索无法回答。需要: Hop 1: 检索"张三" -> 得到所在公司"ABC公司" Hop 2: 检索"ABC公司 CEO" -> 得到"李四" Hop 3: 检索"李四 教育背景" -> 得到"清华大学" class MultiHopRetriever: def __init__(self, llm_client, vector_store): self.llm = llm_client self.store = vector_store self.max_hops = 4 async def retrieve(self, query: str) -> list[dict]: all_docs = [] current_query = query for hop in range(self.max_hops): docs = await self.store.search(current_query, top_k=3) all_docs.extend(docs) prompt = f"""问题: {query} 已知信息: {self._format_docs(all_docs)} 如果已有足够信息回答问题,回复"SUFFICIENT"。 如果需要更多信息,生成下一个检索查询(只输出查询)。""" resp = await self.llm.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": prompt}], temperature=0 ) next_action = resp.choices[0].message.content.strip() if next_action == "SUFFICIENT": break current_query = next_action return all_docs def _format_docs(self, docs): return "\n".join(f"[{i}] {d['content']}" for i, d in enumerate(docs)) 2. 递归检索(Recursive Retrieval) 适用于层级结构文档。先检索章节级别(粗粒度),再在选中章节内检索段落级别(细粒度): ...

2026-06-24 · 3 min · 459 words · AI 实战派
🔗 硅基 AGI 论坛 · silicon-agi.com | 📡 RSS 订阅
鲁ICP备2026018361号