LightRAG 多租户智能体(Agent)系统改造技术论证

📑 目录

  1. 需求背景
  2. 现有架构分析
  3. 技术可行性论证
  4. 详细设计方案
  5. 风险评估与应对
  6. 实施路线图
  7. 关键代码审查

1. 需求背景

1.1 业务需求

用户需要能够:

  • 创建多个独立的智能体(Agent),每个智能体拥有独立的知识库
  • 上传文档到指定智能体,实现数据隔离
  • 选择不同智能体进行对话,查询结果仅来自该智能体的知识库
  • 删除智能体及其所有数据,包括文档、向量、图数据
  • 删除空智能体(无任何文档的智能体)

1.2 核心目标

  • ✅ 数据严格隔离:不同智能体的数据互不干扰
  • ✅ 用户体验友好:简单的创建/切换/删除操作
  • ✅ 向后兼容:不影响现有单workspace使用场景
  • ✅ 性能可控:多智能体不会导致内存/连接爆炸

2. 现有架构分析

2.1 LightRAG已有的Workspace机制

2.1.1 核心发现:Workspace已是多租户基础

通过源码分析,LightRAG已经具备完整的workspace数据隔离能力:

证据1:所有存储层都支持workspace参数

python 复制代码
# lightrag/lightrag.py:157
workspace: str = field(default_factory=lambda: os.getenv("WORKSPACE", ""))

# lightrag/lightrag.py:576-641 - 每个存储实例都传入workspace
self.llm_response_cache: BaseKVStorage = self.key_string_value_json_storage_cls(
    namespace=NameSpace.KV_STORE_LLM_RESPONSE_CACHE,
    workspace=self.workspace,  # ✅ workspace隔离
    global_config=global_config,
    embedding_func=self.embedding_func,
)

证据2:JSON存储实现了workspace目录隔离

python 复制代码
# lightrag/kg/json_kv_impl.py:30-38
if self.workspace:
    # Include workspace in the file path for data isolation
    workspace_dir = os.path.join(working_dir, self.workspace)
else:
    workspace_dir = working_dir
    self.workspace = ""

os.makedirs(workspace_dir, exist_ok=True)
self._file_name = os.path.join(workspace_dir, f"kv_store_{self.namespace}.json")

证据3:PostgreSQL/MongoDB/Redis等存储也支持workspace过滤

python 复制代码
# lightrag/kg/postgres_impl.py:1883-1895
# Implement workspace priority: self.workspace > PostgreSQLDB.workspace > "default"
if hasattr(self, "workspace") and self.workspace:
    pass  # Use storage class's workspace (highest priority)

# lightrag/kg/mongo_impl.py:749-758
mongodb_workspace = os.environ.get("MONGODB_WORKSPACE")
if mongodb_workspace and mongodb_workspace.strip():
    effective_workspace = mongodb_workspace.strip()
else:
    effective_workspace = self.workspace
2.1.2 RagManager已支持多workspace实例管理

证据4:RagManager的多实例缓存机制

python 复制代码
# lightrag/api/lightrag_server.py:388-414
class RagManager:
    def __init__(self, args, rag_init_wrapper):
        self.rag_instances: Dict[str, LightRAG] = {}  # ✅ 按workspace缓存实例
        self.doc_managers: Dict[str, DocumentManager] = {}
        self.lock = asyncio.Lock()

    async def get_rag_instance_async(self, workspace: str) -> LightRAG:
        ws = workspace or self.args.workspace or ""
        if ws not in self.rag_instances:
            async with self.lock:
                if ws not in self.rag_instances:
                    rag = self.rag_init_wrapper(ws)  # ✅ 创建新实例
                    await rag.initialize_storages()
                    self.rag_instances[ws] = rag
        return self.rag_instances[ws]
2.1.3 ContextVar实现请求级上下文传递

证据5:已有的上下文变量机制

python 复制代码
# lightrag/api/lightrag_server.py:86
current_workspace_var: ContextVar[str] = ContextVar("current_workspace", default="")

# lightrag/api/lightrag_server.py:367-369
def _get_real_instance(self):
    ws = current_workspace_var.get()  # ✅ 从上下文获取workspace
    return self._manager.get_rag_instance(ws)

2.2 现有架构的优势

优势 说明 改造影响
数据隔离已实现 workspace参数已贯穿全栈 ✅ 无需修改存储层
多实例管理已就绪 RagManager支持动态创建 ✅ 只需增强元数据管理
上下文传递机制完善 ContextVar避免参数污染 ✅ 复用现有机制
向后兼容性好 默认workspace=""不影响旧代码 ✅ 零破坏性改动

2.3 现有架构的不足

不足 影响 改造方案
缺少Agent元数据存储 无法管理Agent名称、描述、创建时间 ✅ 新增 agent_manager.py
缺少Agent CRUD API 前端无法创建/查询/删除Agent ✅ 新增 agent_routes.py
缺少workspace生命周期管理 删除workspace时数据残留风险 ✅ 利用已有的 drop() 方法
前端无Agent选择界面 用户无法切换智能体 ✅ 新增前端组件

3. 技术可行性论证

3.1 数据隔离可行性

3.1.1 存储层隔离验证

JSON存储实现物理隔离

复制代码
working_dir/
├── agent_001/              # workspace="agent_001"
│   ├── kv_store_full_docs.json
│   ├── vdb_entities.json
│   └── graph_chunk_entity_relation.graphml
├── agent_002/              # workspace="agent_002"
│   ├── kv_store_full_docs.json
│   ├── vdb_entities.json
│   └── graph_chunk_entity_relation.graphml
└── default/                # workspace=""
    └── ...

PostgreSQL/MongoDB实现逻辑隔离

sql 复制代码
-- 所有查询都带workspace过滤条件
SELECT * FROM lightrag_full_docs WHERE workspace = 'agent_001' AND ...
SELECT * FROM lightrag_entities WHERE workspace = 'agent_002' AND ...
3.1.2 向量检索隔离验证

证据6:所有向量存储都支持workspace过滤

python 复制代码
# lightrag/kg/postgres_impl.py:3012-3016
params = {
    "workspace": self.workspace,  # ✅ workspace作为查询条件
    "closer_than_threshold": 1 - self.cosine_better_than_threshold,
    "top_k": top_k,
}

# lightrag/kg/qdrant_impl.py:580-582
query_filter=models.Filter(
    must=[workspace_filter_condition(self.effective_workspace)]  # ✅ workspace过滤
),

3.2 删除操作可行性

3.2.1 所有存储已实现drop()方法

证据7:StorageNameSpace抽象类定义了drop()接口

python 复制代码
# lightrag/base.py:191-214
@abstractmethod
async def drop(self) -> dict[str, str]:
    """Drop all data from storage and clean up resources
    
    Returns:
        dict[str, str]: Operation status and message
        - On success: return {"status": "success", "message": "data dropped"}
        - On failure: return {"status": "error", "message": "<error details>"}
    """

证据8:所有存储实现都已支持drop()

python 复制代码
# JSON存储
# lightrag/kg/json_kv_impl.py:395-407
async def drop(self) -> dict[str, str]:
    try:
        async with self._storage_lock:
            self._data.clear()  # ✅ 清空内存
            await set_all_update_flags(self.namespace, workspace=self.workspace)
        await self.index_done_callback()  # ✅ 持久化
        return {"status": "success", "message": "data dropped"}

# PostgreSQL存储
# lightrag/kg/postgres_impl.py - drop()实现已存在
# MongoDB存储
# lightrag/kg/mongo_impl.py:478-497 - drop()实现已存在
# Redis存储
# lightrag/kg/redis_impl.py:398-425 - drop()实现已存在

证据9:文档清空功能已使用drop()方法

python 复制代码
# lightrag/api/routers/document_routes.py:2374-2398
# Use drop method to clear all data
storages = [
    rag.text_chunks,
    rag.full_docs,
    rag.entities_vdb,
    rag.relationships_vdb,
    rag.chunks_vdb,
    rag.chunk_entity_relation_graph,
    rag.doc_status,
]

for storage in storages:
    if storage is not None:
        drop_tasks.append(storage.drop())  # ✅ 已在生产环境使用
3.2.2 文件删除可行性

证据10:DocumentManager已支持workspace目录管理

python 复制代码
# lightrag/api/routers/document_routes.py:1857-1872
class DocumentManager:
    def __init__(self, input_dir: Path, workspace: str = ""):
        self.base_dir = Path(input_dir)
        self.workspace = workspace
        
        # Construct workspace-specific directory
        if self.workspace:
            self.input_dir = self.base_dir / self.workspace  # ✅ workspace目录隔离
        else:
            self.input_dir = self.base_dir

删除Agent的完整流程

python 复制代码
async def delete_agent(agent_id: str):
    # 1. 调用所有存储的drop()
    rag = await rag_manager.get_rag_instance_async(agent_id)
    await asyncio.gather(
        rag.full_docs.drop(),
        rag.entities_vdb.drop(),
        rag.chunk_entity_relation_graph.drop(),
        # ... 其他存储
    )
    
    # 2. 删除workspace文件目录
    import shutil
    workspace_dir = Path(working_dir) / agent_id
    if workspace_dir.exists():
        shutil.rmtree(workspace_dir)  # ✅ 物理删除
    
    # 3. 删除上传的文档目录
    doc_dir = Path(input_dir) / agent_id
    if doc_dir.exists():
        shutil.rmtree(doc_dir)
    
    # 4. 从RagManager移除实例
    rag_manager.rag_instances.pop(agent_id, None)
    rag_manager.doc_managers.pop(agent_id, None)

3.3 性能可行性

3.3.1 内存占用分析

单个LightRAG实例内存占用估算

  • Python对象本身:~50KB
  • 12个Storage实例:~200KB(主要是对象引用)
  • 共享的shared_storage缓存:所有实例共享,不重复计算
  • 合计:~250KB/实例

100个Agent场景

  • 总内存:100 × 250KB = 25MB(可接受)
  • 实际数据在数据库,内存只是管理对象
3.3.2 连接池管理

证据11:PostgreSQL/MongoDB使用单例连接池

python 复制代码
# lightrag/kg/postgres_impl.py:1785-1853
class ClientManager:
    """Singleton client manager for PostgreSQL connections"""
    _instance: PostgreSQLDB | None = None
    _lock: asyncio.Lock = asyncio.Lock()
    _ref_count: int = 0
    
    @classmethod
    async def get_client(cls) -> PostgreSQLDB:
        # ✅ 所有workspace共享同一连接池

结论:多个workspace不会创建多个数据库连接池,只是逻辑隔离。


4. 详细设计方案

4.1 Agent元数据模型

4.1.1 数据结构设计
python 复制代码
# lightrag/api/models/agent_model.py
from pydantic import BaseModel, Field
from datetime import datetime
from typing import Optional

class Agent(BaseModel):
    """智能体元数据模型"""
    id: str = Field(..., description="智能体唯一ID(等同于workspace)")
    name: str = Field(..., min_length=1, max_length=100, description="智能体名称")
    description: str = Field(default="", max_length=500, description="智能体描述")
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)
    doc_count: int = Field(default=0, description="文档数量(运行时计算)")
    
    class Config:
        json_schema_extra = {
            "example": {
                "id": "agent_legal_20250123_abc123",
                "name": "法律助手",
                "description": "专业法律咨询智能体",
                "created_at": "2025-01-23T10:00:00Z",
                "updated_at": "2025-01-23T10:00:00Z",
                "doc_count": 5
            }
        }
4.1.2 存储方案

方案选择:JSON文件存储(与LightRAG风格一致)

json 复制代码
// {working_dir}/agents_meta.json
{
  "agent_legal_20250123_abc123": {
    "id": "agent_legal_20250123_abc123",
    "name": "法律助手",
    "description": "专业法律咨询智能体",
    "created_at": "2025-01-23T10:00:00Z",
    "updated_at": "2025-01-23T10:00:00Z"
  },
  "agent_customer_service_xyz789": {
    "id": "agent_customer_service_xyz789",
    "name": "客服助手",
    "description": "24小时在线客服",
    "created_at": "2025-01-23T11:00:00Z",
    "updated_at": "2025-01-23T11:00:00Z"
  }
}

优势

  • ✅ 与LightRAG现有风格一致(如doc_status使用JSON)
  • ✅ 无需额外数据库依赖
  • ✅ 便于备份和迁移
  • ✅ 支持多进程通过文件锁安全访问

4.2 AgentManager实现

4.2.1 核心类设计
python 复制代码
# lightrag/api/agent_manager.py
import os
import json
import asyncio
from pathlib import Path
from datetime import datetime, timezone
from typing import Dict, Optional, List
from lightrag.utils import logger, compute_mdhash_id

class AgentManager:
    """智能体元数据管理器"""
    
    def __init__(self, working_dir: str):
        self.working_dir = Path(working_dir)
        self.meta_file = self.working_dir / "agents_meta.json"
        self.lock = asyncio.Lock()
        
    async def initialize(self):
        """初始化元数据文件"""
        if not self.meta_file.exists():
            await self._save_meta({})
    
    async def create_agent(self, name: str, description: str = "") -> Dict:
        """创建新智能体"""
        async with self.lock:
            meta = await self._load_meta()
            
            # 生成唯一ID
            timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
            unique_suffix = compute_mdhash_id(f"{name}_{timestamp}", prefix="")[:8]
            agent_id = f"agent_{name}_{unique_suffix}"
            
            # 检查名称重复
            if any(a["name"] == name for a in meta.values()):
                raise ValueError(f"智能体名称 '{name}' 已存在")
            
            # 创建元数据
            agent = {
                "id": agent_id,
                "name": name,
                "description": description,
                "created_at": datetime.now(timezone.utc).isoformat(),
                "updated_at": datetime.now(timezone.utc).isoformat(),
            }
            
            meta[agent_id] = agent
            await self._save_meta(meta)
            logger.info(f"创建智能体成功: {agent_id} ({name})")
            return agent
    
    async def list_agents(self) -> List[Dict]:
        """列出所有智能体(包含doc_count)"""
        meta = await self._load_meta()
        
        # 动态计算文档数量
        for agent_id, agent in meta.items():
            agent["doc_count"] = await self._get_doc_count(agent_id)
        
        return list(meta.values())
    
    async def get_agent(self, agent_id: str) -> Optional[Dict]:
        """获取智能体详情"""
        meta = await self._load_meta()
        agent = meta.get(agent_id)
        
        if agent:
            agent["doc_count"] = await self._get_doc_count(agent_id)
        
        return agent
    
    async def delete_agent(self, agent_id: str) -> bool:
        """删除智能体元数据(不删除实际数据)"""
        async with self.lock:
            meta = await self._load_meta()
            
            if agent_id not in meta:
                return False
            
            del meta[agent_id]
            await self._save_meta(meta)
            logger.info(f"删除智能体元数据成功: {agent_id}")
            return True
    
    async def _get_doc_count(self, agent_id: str) -> int:
        """获取智能体的文档数量"""
        try:
            # 通过读取doc_status获取文档数量
            doc_status_file = self.working_dir / agent_id / "kv_store_doc_status.json"
            if doc_status_file.exists():
                with open(doc_status_file, "r", encoding="utf-8") as f:
                    data = json.load(f)
                    return len(data)
            return 0
        except Exception as e:
            logger.warning(f"获取文档数量失败 {agent_id}: {e}")
            return 0
    
    async def _load_meta(self) -> Dict:
        """加载元数据"""
        try:
            if self.meta_file.exists():
                with open(self.meta_file, "r", encoding="utf-8") as f:
                    return json.load(f)
            return {}
        except Exception as e:
            logger.error(f"加载Agent元数据失败: {e}")
            return {}
    
    async def _save_meta(self, meta: Dict):
        """保存元数据"""
        try:
            with open(self.meta_file, "w", encoding="utf-8") as f:
                json.dump(meta, f, ensure_ascii=False, indent=2)
        except Exception as e:
            logger.error(f"保存Agent元数据失败: {e}")
            raise

4.3 API路由设计

4.3.1 Agent管理路由
python 复制代码
# lightrag/api/routers/agent_routes.py
from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel, Field
from typing import List, Literal
import shutil

router = APIRouter(prefix="/agents", tags=["Agent Management"])

class CreateAgentRequest(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    description: str = Field(default="", max_length=500)

class AgentResponse(BaseModel):
    id: str
    name: str
    description: str
    created_at: str
    updated_at: str
    doc_count: int

class DeleteAgentResponse(BaseModel):
    status: Literal["success", "error"]
    message: str
    deleted_doc_count: int = 0

def create_agent_routes(agent_manager, rag_manager, args, combined_auth):
    
    @router.post("", response_model=AgentResponse)
    async def create_agent(request: CreateAgentRequest):
        """创建新智能体"""
        try:
            agent = await agent_manager.create_agent(
                name=request.name,
                description=request.description
            )
            return {**agent, "doc_count": 0}
        except ValueError as e:
            raise HTTPException(status_code=400, detail=str(e))
        except Exception as e:
            raise HTTPException(status_code=500, detail=str(e))
    
    @router.get("", response_model=List[AgentResponse])
    async def list_agents():
        """获取智能体列表"""
        agents = await agent_manager.list_agents()
        return agents
    
    @router.get("/{agent_id}", response_model=AgentResponse)
    async def get_agent(agent_id: str):
        """获取智能体详情"""
        agent = await agent_manager.get_agent(agent_id)
        if not agent:
            raise HTTPException(status_code=404, detail="智能体不存在")
        return agent
    
    @router.delete("/{agent_id}", response_model=DeleteAgentResponse)
    async def delete_agent(agent_id: str):
        """删除智能体及其所有数据"""
        try:
            # 1. 检查智能体是否存在
            agent = await agent_manager.get_agent(agent_id)
            if not agent:
                raise HTTPException(status_code=404, detail="智能体不存在")
            
            doc_count = agent["doc_count"]
            
            # 2. 获取RAG实例并调用drop()
            try:
                rag = await rag_manager.get_rag_instance_async(agent_id)
                
                storages = [
                    rag.text_chunks,
                    rag.full_docs,
                    rag.full_entities,
                    rag.full_relations,
                    rag.entity_chunks,
                    rag.relation_chunks,
                    rag.entities_vdb,
                    rag.relationships_vdb,
                    rag.chunks_vdb,
                    rag.chunk_entity_relation_graph,
                    rag.doc_status,
                ]
                
                drop_results = await asyncio.gather(
                    *[s.drop() for s in storages if s],
                    return_exceptions=True
                )
                
                # 检查是否有失败
                failed = [r for r in drop_results if isinstance(r, Exception)]
                if failed:
                    logger.warning(f"部分存储删除失败: {failed}")
                
            except Exception as e:
                logger.error(f"删除存储数据失败: {e}")
                raise HTTPException(status_code=500, detail=f"删除数据失败: {str(e)}")
            
            # 3. 删除workspace目录
            workspace_dir = Path(args.working_dir) / agent_id
            if workspace_dir.exists():
                shutil.rmtree(workspace_dir)
            
            # 4. 删除文档目录
            doc_dir = Path(args.input_dir) / agent_id
            if doc_dir.exists():
                shutil.rmtree(doc_dir)
            
            # 5. 从RagManager移除实例
            rag_manager.rag_instances.pop(agent_id, None)
            rag_manager.doc_managers.pop(agent_id, None)
            
            # 6. 删除元数据
            await agent_manager.delete_agent(agent_id)
            
            return {
                "status": "success",
                "message": f"智能体 '{agent['name']}' 删除成功",
                "deleted_doc_count": doc_count
            }
            
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"删除智能体失败: {e}")
            raise HTTPException(status_code=500, detail=str(e))
    
    return router

4.4 中间件增强

4.4.1 Agent上下文中间件
python 复制代码
# lightrag/api/lightrag_server.py 添加中间件
@app.middleware("http")
async def agent_context_middleware(request: Request, call_next):
    """从请求头提取Agent ID并设置上下文"""
    agent_id = request.headers.get("X-Agent-ID", "")
    
    # 设置到ContextVar
    current_workspace_var.set(agent_id)
    
    # 记录日志(调试用)
    if agent_id:
        logger.debug(f"请求使用Agent: {agent_id} - {request.url.path}")
    
    response = await call_next(request)
    return response

4.5 前端改造

4.5.1 Agent选择器组件
typescript 复制代码
// lightrag_webui/src/components/agent/AgentSelector.tsx
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
import { useAgentStore } from '@/stores/agentStore'

export function AgentSelector() {
  const { currentAgent, agents, setCurrentAgent, fetchAgents } = useAgentStore()
  
  useEffect(() => {
    fetchAgents()
  }, [])
  
  return (
    <Select value={currentAgent?.id} onValueChange={(id) => {
      const agent = agents.find(a => a.id === id)
      if (agent) setCurrentAgent(agent)
    }}>
      <SelectTrigger className="w-[200px]">
        <SelectValue placeholder="选择智能体" />
      </SelectTrigger>
      <SelectContent>
        {agents.map(agent => (
          <SelectItem key={agent.id} value={agent.id}>
            {agent.name} ({agent.doc_count}篇)
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  )
}
4.5.2 Axios拦截器自动添加Agent头
typescript 复制代码
// lightrag_webui/src/api/lightrag.ts
import axios from 'axios'
import { useAgentStore } from '@/stores/agentStore'

const axiosInstance = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL
})

// 请求拦截器:自动添加X-Agent-ID
axiosInstance.interceptors.request.use((config) => {
  const currentAgent = useAgentStore.getState().currentAgent
  if (currentAgent) {
    config.headers['X-Agent-ID'] = currentAgent.id
  }
  return config
})

export default axiosInstance

5. 风险评估与应对

5.1 技术风险

风险项 风险等级 影响 应对措施
删除操作不可逆 误删导致数据永久丢失 1. 删除前强制二次确认 2. 实施软删除(标记后延迟真删) 3. 提供备份导出功能
并发删除冲突 同时删除同一Agent导致异常 使用asyncio.Lock锁定删除操作
元数据与实际数据不一致 显示错误的文档数量 doc_count实时计算,不存储缓存
大量Agent内存占用 超过100个Agent可能占用过多内存 实施LRU淘汰策略,仅保留活跃实例

5.2 用户体验风险

风险项 风险等级 影响 应对措施
Agent名称冲突 用户困惑 创建时检查重名,提示用户
删除空Agent误操作 用户后悔 明确提示"该智能体无文档,确认删除?"
切换Agent后忘记当前上下文 查询结果混淆 1. 顶部显著位置显示当前Agent 2. 对话记录自动清空

5.3 兼容性风险

风险项 风险等级 影响 应对措施
破坏现有单workspace用户 现有用户无法使用 workspace=""作为默认值,完全向后兼容
多进程环境元数据冲突 Gunicorn模式下数据异常 使用文件锁保护agents_meta.json

6. 实施路线图

6.1 开发阶段划分

第一阶段:后端核心(3-4天)

Day 1:Agent元数据管理

  • 实现 agent_manager.py
  • 单元测试:创建/查询/删除Agent
  • 集成测试:与RagManager配合

Day 2:Agent API路由

  • 实现 agent_routes.py
  • API测试:Postman/curl验证
  • 压力测试:并发创建/删除

Day 3:数据删除功能

  • 完整删除流程实现
  • 测试各存储类型的drop()
  • 验证文件目录删除

Day 4:中间件与集成

  • 实现Agent上下文中间件
  • 修改现有API支持X-Agent-ID
  • 端到端测试
第二阶段:前端界面(2-3天)

Day 5:Agent管理界面

  • Agent列表卡片
  • 创建Agent对话框
  • 删除确认对话框

Day 6:Agent选择器

  • 顶部导航栏集成
  • 切换Agent逻辑
  • Axios拦截器

Day 7:联调与优化

  • 前后端联调
  • UI/UX优化
  • 错误提示优化
第三阶段:测试与文档(1-2天)

Day 8:全面测试

  • 功能测试矩阵
  • 边界条件测试
  • 性能测试

Day 9:文档与发布

  • 用户使用文档
  • API文档更新
  • 部署指南

6.2 测试验收标准

功能验收
  • 创建Agent成功,返回唯一ID
  • Agent列表显示正确的文档数量
  • 上传文档到Agent A,在Agent B中查询不到
  • 删除Agent后,所有数据完全清除
  • 删除空Agent无错误
  • 切换Agent后对话上下文正确
性能验收
  • 创建Agent响应时间 < 500ms
  • 删除Agent响应时间 < 3s(含存储清理)
  • 支持至少50个并发Agent
  • 单个Agent最大支持10000篇文档
兼容性验收
  • 现有无workspace用户不受影响
  • PostgreSQL/MongoDB/Redis存储全部通过
  • 多进程(Gunicorn)模式正常

7. 关键代码审查

7.1 需要修改的文件清单

新增文件(5个)
  1. lightrag/api/agent_manager.py - Agent元数据管理器
  2. lightrag/api/models/agent_model.py - Agent数据模型
  3. lightrag/api/routers/agent_routes.py - Agent API路由
  4. lightrag_webui/src/stores/agentStore.ts - Agent状态管理
  5. lightrag_webui/src/components/agent/AgentSelector.tsx - Agent选择器
修改文件(2个)
  1. lightrag/api/lightrag_server.py - 添加中间件、注册路由
  2. lightrag_webui/src/api/lightrag.ts - Axios拦截器

7.2 关键函数调用链

创建Agent流程
复制代码
用户操作
  ↓
POST /agents {name, description}
  ↓
agent_routes.create_agent()
  ↓
agent_manager.create_agent()
  ├─ 生成唯一ID: agent_{name}_{hash}
  ├─ 检查名称重复
  ├─ 保存到 agents_meta.json
  └─ 返回Agent对象
  ↓
前端agentStore.addAgent()
  ↓
更新UI列表
上传文档到Agent流程
复制代码
用户选择Agent A + 上传文件
  ↓
前端发送请求:
  POST /documents/upload
  Headers: X-Agent-ID: agent_A
  Body: FormData(file)
  ↓
中间件提取X-Agent-ID → current_workspace_var.set("agent_A")
  ↓
document_routes.upload_file()
  ├─ rag = await rag_manager.get_rag_instance_async()
  │   └─ 从current_workspace_var.get() → "agent_A"
  │   └─ 返回 rag_instances["agent_A"]
  ↓
rag.ainsert(file_content)
  ├─ self.workspace = "agent_A"
  ├─ 所有存储操作带workspace参数
  │   ├─ text_chunks.upsert(..., workspace="agent_A")
  │   ├─ entities_vdb.upsert(..., workspace="agent_A")
  │   └─ chunk_entity_relation_graph.upsert(..., workspace="agent_A")
  └─ 数据物理/逻辑隔离完成
删除Agent流程
复制代码
用户确认删除Agent
  ↓
DELETE /agents/{agent_id}
  ↓
agent_routes.delete_agent()
  ├─ 1. 获取Agent元数据(含doc_count)
  ├─ 2. 获取RAG实例
  │      rag = await rag_manager.get_rag_instance_async(agent_id)
  ├─ 3. 调用所有存储的drop()
  │      await asyncio.gather(
  │          rag.text_chunks.drop(),
  │          rag.entities_vdb.drop(),
  │          rag.chunk_entity_relation_graph.drop(),
  │          ...
  │      )
  ├─ 4. 删除文件目录
  │      shutil.rmtree(working_dir / agent_id)
  │      shutil.rmtree(input_dir / agent_id)
  ├─ 5. 移除内存实例
  │      rag_manager.rag_instances.pop(agent_id)
  └─ 6. 删除元数据
         await agent_manager.delete_agent(agent_id)

7.3 核心代码依赖关系

复制代码
┌─────────────────────────────────────┐
│      lightrag_server.py             │
│  - 注册agent_routes                 │
│  - 添加agent_context_middleware     │
│  - current_workspace_var (已有)     │
└──────────┬──────────────────────────┘
           │
           ├─────────────────────┐
           ↓                     ↓
┌──────────────────┐   ┌────────────────────┐
│  agent_routes.py │   │  document_routes.py│
│  - create_agent  │   │  - upload_file     │
│  - list_agents   │   │  (已有,无需修改)   │
│  - delete_agent  │   └────────────────────┘
└─────┬────────────┘
      ↓
┌──────────────────┐
│ agent_manager.py │
│ - 管理元数据      │
│ - 文件存储       │
└─────┬────────────┘
      ↓
┌──────────────────┐
│agents_meta.json  │
│ {                │
│   "agent_id": {  │
│     "name": ...  │
│   }              │
│ }                │
└──────────────────┘

8. 总结与建议

8.1 技术可行性结论

完全可行,理由如下:

  1. LightRAG已有完整的workspace基础架构

    • 所有存储层支持workspace参数
    • RagManager支持多实例管理
    • ContextVar实现上下文传递
  2. 数据隔离能力已验证

    • JSON存储实现物理隔离(独立目录)
    • PostgreSQL/MongoDB实现逻辑隔离(workspace字段过滤)
    • 向量检索带workspace过滤条件
  3. 删除功能已就绪

    • 所有存储实现了drop()抽象方法
    • 文档清空功能已使用drop()并在生产环境验证
  4. 性能风险可控

    • 单实例内存占用 ~250KB
    • 数据库连接池共享,不会爆炸
    • 支持100+并发Agent

8.2 改造风险评估

总体风险等级 :🟢 低风险

  • 向后兼容性:✅ 完全兼容(workspace=""作为默认值)
  • 代码侵入性:✅ 最小侵入(只增加,不修改核心逻辑)
  • 测试覆盖率:✅ 可全面测试(功能点清晰)
  • 回滚难度:✅ 容易回滚(新增文件可直接删除)

8.3 实施建议

立即开始的理由
  1. 架构基础已就绪:无需大规模重构
  2. 关键代码已验证:drop()方法已在生产使用
  3. 用户价值明确:多智能体是强需求
  4. 技术债务小:不会引入复杂依赖
推荐实施路径
复制代码
第1周:后端核心
  ├─ Day 1-2: agent_manager + agent_routes
  ├─ Day 3-4: 删除功能 + 中间件
  └─ Day 5: 单元测试 + 集成测试

第2周:前端界面
  ├─ Day 6-7: Agent管理界面
  ├─ Day 8: Agent选择器 + 拦截器
  └─ Day 9-10: 联调 + 优化

第3周:测试与发布
  ├─ Day 11-12: 全面测试
  └─ Day 13-14: 文档 + 上线

8.4 后续扩展方向

完成基础多租户后,可进一步扩展:

  1. 用户权限系统:User → Agent 多对多关系
  2. Agent共享:允许多个用户共享同一Agent
  3. Agent模板:预设领域专家Agent
  4. Agent导出/导入:备份与迁移
  5. Agent统计分析:查询次数、文档来源分析

9. 附录

9.1 关键类图

manages
creates/manages
collaborates
LightRAG
+str workspace
+BaseKVStorage text_chunks
+BaseVectorStorage entities_vdb
+BaseGraphStorage chunk_entity_relation_graph
+async initialize_storages()
+async finalize_storages()
RagManager
+Dict[str, LightRAG] rag_instances
+Dict[str, DocumentManager] doc_managers
+async get_rag_instance_async(workspace: str)
+async finalize_all()
AgentManager
+Path meta_file
+async create_agent(name, description)
+async list_agents()
+async delete_agent(agent_id)
-async _load_meta()
-async _save_meta(meta)
Agent
+str id
+str name
+str description
+datetime created_at
+int doc_count

9.2 序列图:创建Agent并上传文档

Storage LightRAG RagManager AgentManager API Frontend User Storage LightRAG RagManager AgentManager API Frontend User 点击"创建智能体" POST /agents {name: "法律助手"} create_agent("法律助手") 生成agent_id 保存到agents_meta.json 返回Agent对象 返回Agent JSON 更新Agent列表 选择"法律助手" + 上传文件 POST /documents/upload Header: X-Agent-ID=agent_legal_xxx Middleware提取X-Agent-ID get_rag_instance_async("agent_legal_xxx") new LightRAG(workspace="agent_legal_xxx") initialize storages with workspace 返回LightRAG实例 ainsert(file_content) upsert data with workspace="agent_legal_xxx" 存储成功 处理完成 上传成功

9.3 关键配置项

bash 复制代码
# .env 配置示例

# Workspace配置(可选,为空表示默认workspace)
WORKSPACE=

# PostgreSQL配置(多workspace共享连接池)
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=lightrag
POSTGRES_PASSWORD=password
POSTGRES_DATABASE=lightrag

# 文档存储目录
INPUT_DIR=./input_files

# RAG存储目录
WORKING_DIR=./rag_storage

9.4 测试用例矩阵

测试场景 预期结果 验证方法
创建Agent A 返回唯一agent_id 检查agents_meta.json
创建同名Agent 返回400错误 断言HTTP状态码
上传文档到Agent A 文档存储在agent_A目录 检查文件系统
在Agent A查询 只返回Agent A的文档 检查reference_id
在Agent B查询 不返回Agent A的文档 检查结果为空
删除空Agent 成功删除,doc_count=0 检查元数据移除
删除有文档的Agent 所有数据清除 检查目录、数据库、VDB
并发创建10个Agent 全部成功 压力测试
并发删除同一Agent 只有一个成功 锁机制测试

文档结束

下一步行动

  1. 评审本文档,确认技术方案
  2. 开始实施"第一阶段Day 1"任务
  3. 建立代码审查流程
  4. 配置测试环境

联系方式:如有疑问,请参考本文档第7节"关键代码审查"

相关推荐
RestCloud1 个月前
谷云科技发布 API × AI 战略:让 AI 从“理解数据”走向“驱动业务能力”
人工智能·科技·api·数据集成·ipaas·aiagent·ai网关
沛沛老爹1 个月前
LightRAG 系列 5:核心技术解析——HNSW 索引机制与 Web 应用中的毫秒级检索
faiss·hnsw·rag·lightrag·动态调整·索引机制·预热索引
沛沛老爹1 个月前
LightRAG 系列 7:核心技术解析——整合检索与生成模块,完整走通 LightRAG 的端到端工作流
工作流·rag·端到端·lightrag·知识注入·查询响应
沛沛老爹1 个月前
LightRAG系列3:LightRAG 环境准备与快速启动
大模型·llm·安装·helloworld·rag·lightrag·ai入门
沛沛老爹1 个月前
ightRAG 系列 4:核心技术解析——检索模块详解(上)
llm·rag·lightrag·ai入门·向量化原理·向量化流程
梵得儿SHI2 个月前
AI Agent 深度解析:高级架构、优化策略与行业实战指南(多智能体 + 分层决策 + 人类在环)
人工智能·多智能体系统·aiagent·分层决策系统·人类在环机制·agent系统完整解决方案·aiagent底层原理
沛沛老爹2 个月前
AI入门之GraphRAG企业级部署性能优化策略:从索引到检索的全链路提效实践
人工智能·ai·性能优化·rag·入门知识·graphrag·lightrag
RestCloud10 个月前
AI大模型本地化&谷云科技全域集成能力重构企业数智化生态
人工智能·ai·数智化·智能体·aiagent·deepseek·集成平台
RestCloud1 年前
DeepSeek+谷云科技智能体,快速构建企业知识问答
人工智能·科技·数据集成·ipaas·aiagent·deepseek