From 15dfbe7f823ed16b98909a61383c6b69e2409b88 Mon Sep 17 00:00:00 2001 From: z30057876 Date: Thu, 9 Oct 2025 20:40:03 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4Knowledge=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=9B=E8=A1=A5=E5=85=85=E7=89=88=E6=9D=83=E5=A3=B0=E6=98=8E?= =?UTF-8?q?=EF=BC=9B=E6=9B=B4=E6=96=B0=E6=A8=A1=E5=9D=97=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/__init__.py | 1 + apps/common/oidc_provider/__init__.py | 1 + apps/common/postgres.py | 1 + apps/constants.py | 7 +- apps/exceptions.py | 7 +- apps/llm/embedding.py | 6 + apps/llm/providers/__init__.py | 1 + apps/llm/providers/ollama.py | 1 + apps/main.py | 11 +- apps/models/__init__.py | 1 + apps/models/app.py | 2 + apps/models/base.py | 5 +- apps/models/blacklist.py | 1 + apps/models/comment.py | 1 + apps/models/conversation.py | 1 + apps/models/document.py | 2 + apps/models/flow.py | 2 + apps/models/llm.py | 1 + apps/models/mcp.py | 1 + apps/models/node.py | 1 + apps/models/record.py | 1 + apps/models/service.py | 1 + apps/models/session.py | 1 + apps/models/tag.py | 1 + apps/models/task.py | 1 + apps/models/user.py | 1 + apps/routers/__init__.py | 7 +- apps/routers/appcenter.py | 2 +- apps/routers/document.py | 7 +- apps/routers/knowledge.py | 58 ---- apps/routers/mcp_service.py | 2 +- apps/routers/parameter.py | 1 + apps/routers/service.py | 2 +- apps/routers/tag.py | 2 +- apps/scheduler/call/cmd/prompt.py | 1 + apps/scheduler/call/cmd/schema.py | 1 + apps/scheduler/call/graph/prompt.py | 1 + apps/scheduler/call/rag/prompt.py | 1 + apps/scheduler/call/summary/prompt.py | 1 + apps/scheduler/executor/prompt.py | 1 + apps/scheduler/executor/qa.py | 2 +- apps/scheduler/scheduler/prompt.py | 1 + apps/schemas/appcenter.py | 2 +- apps/schemas/comment.py | 1 + apps/schemas/conversation.py | 1 + apps/schemas/parameters.py | 1 + apps/schemas/record.py | 2 - apps/schemas/service.py | 2 +- apps/schemas/user.py | 2 +- apps/services/__init__.py | 2 - apps/services/appcenter.py | 2 +- apps/services/knowledge.py | 58 ---- apps/services/mcp_service.py | 2 +- apps/services/service.py | 4 +- apps/services/session.py | 2 +- design/call/slot.md | 90 +----- design/call/summary.md | 1 - design/services/personal_token.md | 164 +++++++++++ design/services/session.md | 267 +++++++++++++++++ design/services/tag.md | 118 +++----- design/services/user.md | 404 ++++++++++++++++++++++++++ 61 files changed, 948 insertions(+), 327 deletions(-) delete mode 100644 apps/routers/knowledge.py delete mode 100644 apps/services/knowledge.py create mode 100644 design/services/personal_token.md create mode 100644 design/services/session.md create mode 100644 design/services/user.md diff --git a/apps/__init__.py b/apps/__init__.py index a640c44c..7cdecb87 100644 --- a/apps/__init__.py +++ b/apps/__init__.py @@ -1 +1,2 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """openEuler Intelligence Framework""" diff --git a/apps/common/oidc_provider/__init__.py b/apps/common/oidc_provider/__init__.py index 28375f5c..f84ba720 100644 --- a/apps/common/oidc_provider/__init__.py +++ b/apps/common/oidc_provider/__init__.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """OIDC Provider""" from .authhub import AuthhubOIDCProvider diff --git a/apps/common/postgres.py b/apps/common/postgres.py index 6631714d..c0d11824 100644 --- a/apps/common/postgres.py +++ b/apps/common/postgres.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Postgres连接器""" import logging diff --git a/apps/constants.py b/apps/constants.py index 6f301fd5..4e8a2ed2 100644 --- a/apps/constants.py +++ b/apps/constants.py @@ -1,8 +1,5 @@ -""" -常量数据 - -Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -""" +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""常量数据""" from anyio import Path diff --git a/apps/exceptions.py b/apps/exceptions.py index d546520f..56419681 100644 --- a/apps/exceptions.py +++ b/apps/exceptions.py @@ -1,8 +1,5 @@ -""" -自定义异常类 - -Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -""" +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""自定义异常类""" class InstancePermissionError(Exception): diff --git a/apps/llm/embedding.py b/apps/llm/embedding.py index 61162a0b..82f3db13 100644 --- a/apps/llm/embedding.py +++ b/apps/llm/embedding.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Embedding模型""" import logging @@ -19,6 +20,7 @@ _flow_pool_vector_table = { "appId": Column(UUID(as_uuid=True), ForeignKey("framework_app.id"), nullable=False), "id": Column(String(255), ForeignKey("framework_flow.id"), primary_key=True), "__table_args__": ( + {"extend_existing": True}, Index( "hnsw_index", "embedding", @@ -32,6 +34,7 @@ _service_pool_vector_table = { "__tablename__": "framework_service_vector", "id": Column(UUID(as_uuid=True), ForeignKey("framework_service.id"), primary_key=True), "__table_args__": ( + {"extend_existing": True}, Index( "hnsw_index", "embedding", @@ -46,6 +49,7 @@ _node_pool_vector_table = { "id": Column(String(255), ForeignKey("framework_node.id"), primary_key=True), "serviceId": Column(UUID(as_uuid=True), ForeignKey("framework_service.id"), nullable=True), "__table_args__": ( + {"extend_existing": True}, Index( "hnsw_index", "embedding", @@ -59,6 +63,7 @@ _mcp_vector_table = { "__tablename__": "framework_mcp_vector", "id": Column(String(255), ForeignKey("framework_mcp.id"), primary_key=True), "__table_args__": ( + {"extend_existing": True}, Index( "hnsw_index", "embedding", @@ -73,6 +78,7 @@ _mcp_tool_vector_table = { "id": Column(String(255), ForeignKey("framework_mcp_tool.id"), primary_key=True), "mcpId": Column(String(255), ForeignKey("framework_mcp.id"), nullable=False), "__table_args__": ( + {"extend_existing": True}, Index( "hnsw_index", "embedding", diff --git a/apps/llm/providers/__init__.py b/apps/llm/providers/__init__.py index 11c35e88..0a52fa35 100644 --- a/apps/llm/providers/__init__.py +++ b/apps/llm/providers/__init__.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """大模型提供商""" from .base import BaseProvider diff --git a/apps/llm/providers/ollama.py b/apps/llm/providers/ollama.py index e4935561..d0df83c7 100644 --- a/apps/llm/providers/ollama.py +++ b/apps/llm/providers/ollama.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Ollama大模型服务""" import logging diff --git a/apps/main.py b/apps/main.py index eca90cf9..51eb1220 100644 --- a/apps/main.py +++ b/apps/main.py @@ -1,10 +1,5 @@ -""" -主程序 - -Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -""" - -from __future__ import annotations +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""主程序""" import asyncio import logging @@ -30,7 +25,6 @@ from .routers import ( document, flow, health, - knowledge, llm, mcp_service, parameter, @@ -64,7 +58,6 @@ app.include_router(conversation.router) app.include_router(document.router) app.include_router(flow.router) app.include_router(health.router) -app.include_router(knowledge.router) app.include_router(llm.router) app.include_router(llm.admin_router) app.include_router(mcp_service.router) diff --git a/apps/models/__init__.py b/apps/models/__init__.py index 899b564b..8db4b839 100644 --- a/apps/models/__init__.py +++ b/apps/models/__init__.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """SQLAlchemy 数据库表结构""" from .app import App, AppACL, AppHashes, AppMCP, AppType, PermissionType diff --git a/apps/models/app.py b/apps/models/app.py index 00f8e9f4..68ff16c5 100644 --- a/apps/models/app.py +++ b/apps/models/app.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """应用 数据库表""" import uuid @@ -57,6 +58,7 @@ class App(Base): ) """权限类型""" __table_args__ = ( + {"extend_existing": True}, Index("idx_published_updated_at", "isPublished", "updatedAt"), Index("idx_author_id_name", "author", "id", "name"), ) diff --git a/apps/models/base.py b/apps/models/base.py index 432e5647..14ce5183 100644 --- a/apps/models/base.py +++ b/apps/models/base.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """SQLAlchemy模型基类""" from typing import Any, ClassVar @@ -9,5 +10,7 @@ class Base(MappedAsDataclass, DeclarativeBase): """SQLAlchemy模型基类""" # 生成文档时需要启动这个参数,否则会触发重复导入告警 - __table_args__: ClassVar[dict[str, Any]] = {"extend_existing": True} + __table_args__: ClassVar[tuple[Any, ...]] = ( + {"extend_existing": True}, + ) diff --git a/apps/models/blacklist.py b/apps/models/blacklist.py index 9acf1fc1..878b41d4 100644 --- a/apps/models/blacklist.py +++ b/apps/models/blacklist.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """黑名单 数据库表结构""" import uuid diff --git a/apps/models/comment.py b/apps/models/comment.py index 000c2497..0c438c20 100644 --- a/apps/models/comment.py +++ b/apps/models/comment.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """评论 数据库表""" import uuid diff --git a/apps/models/conversation.py b/apps/models/conversation.py index 5b411ba2..82645b91 100644 --- a/apps/models/conversation.py +++ b/apps/models/conversation.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """对话 数据库表""" import uuid diff --git a/apps/models/document.py b/apps/models/document.py index 6fe501f8..7d7cb48b 100644 --- a/apps/models/document.py +++ b/apps/models/document.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """文件 数据库表""" import uuid @@ -37,5 +38,6 @@ class Document(Base): ) """文件的创建时间""" __table_args__ = ( + {"extend_existing": True}, Index("idx_user_sub_conversation_id", "userSub", "conversationId"), ) diff --git a/apps/models/flow.py b/apps/models/flow.py index 43e37992..599c0fae 100644 --- a/apps/models/flow.py +++ b/apps/models/flow.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Flow 数据库表""" import uuid @@ -41,6 +42,7 @@ class Flow(Base): ) """Flow的更新时间""" __table_args__ = ( + {"extend_existing": True}, Index("idx_app_id_id", "appId", "id"), Index("idx_app_id_name", "appId", "name"), ) diff --git a/apps/models/llm.py b/apps/models/llm.py index 422721b5..cb7324f7 100644 --- a/apps/models/llm.py +++ b/apps/models/llm.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """大模型信息 数据库表""" from datetime import UTC, datetime diff --git a/apps/models/mcp.py b/apps/models/mcp.py index 827414af..d48c97b4 100644 --- a/apps/models/mcp.py +++ b/apps/models/mcp.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """MCP 相关 数据库表""" from datetime import UTC, datetime diff --git a/apps/models/node.py b/apps/models/node.py index 8f6331f9..a629d2dc 100644 --- a/apps/models/node.py +++ b/apps/models/node.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """节点 数据库表""" import uuid diff --git a/apps/models/record.py b/apps/models/record.py index 2bc80d84..0645fde9 100644 --- a/apps/models/record.py +++ b/apps/models/record.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """问答对 数据库表""" import uuid diff --git a/apps/models/service.py b/apps/models/service.py index 71201869..714fb463 100644 --- a/apps/models/service.py +++ b/apps/models/service.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """插件 数据库表""" import uuid diff --git a/apps/models/session.py b/apps/models/session.py index 5d8f0f52..d25a3e33 100644 --- a/apps/models/session.py +++ b/apps/models/session.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """会话相关 数据库表""" import secrets diff --git a/apps/models/tag.py b/apps/models/tag.py index 3476c852..0fe5be59 100644 --- a/apps/models/tag.py +++ b/apps/models/tag.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """用户标签 数据库表""" from datetime import UTC, datetime diff --git a/apps/models/task.py b/apps/models/task.py index 61f12b78..397d604f 100644 --- a/apps/models/task.py +++ b/apps/models/task.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """任务 数据库表""" import uuid diff --git a/apps/models/user.py b/apps/models/user.py index 278456a3..11a24b7c 100644 --- a/apps/models/user.py +++ b/apps/models/user.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """用户表""" import enum diff --git a/apps/routers/__init__.py b/apps/routers/__init__.py index b4dfdfda..5d0de86f 100644 --- a/apps/routers/__init__.py +++ b/apps/routers/__init__.py @@ -1,5 +1,2 @@ -""" -FastAPI 路由 - -Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -""" +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""FastAPI 路由""" diff --git a/apps/routers/appcenter.py b/apps/routers/appcenter.py index 5e644977..e744dcd7 100644 --- a/apps/routers/appcenter.py +++ b/apps/routers/appcenter.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """FastAPI 应用中心相关路由""" import logging diff --git a/apps/routers/document.py b/apps/routers/document.py index 2e816fe5..daf1de36 100644 --- a/apps/routers/document.py +++ b/apps/routers/document.py @@ -1,8 +1,5 @@ -""" -FastAPI文件上传路由 - -Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -""" +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. +"""FastAPI文件上传路由""" import uuid from typing import Annotated diff --git a/apps/routers/knowledge.py b/apps/routers/knowledge.py deleted file mode 100644 index b3aeadf4..00000000 --- a/apps/routers/knowledge.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -"""FastAPI 用户资产库路由""" - -from fastapi import APIRouter, Depends, Request, status -from fastapi.responses import JSONResponse - -from apps.dependency import verify_personal_token, verify_session -from apps.schemas.request_data import ( - UpdateUserKnowledgebaseReq, -) -from apps.schemas.response_data import ( - ListTeamKnowledgeMsg, - ListTeamKnowledgeRsp, - ResponseData, -) -from apps.services import KnowledgeBaseManager - -router = APIRouter( - prefix="/api/knowledge", - tags=["knowledge"], - dependencies=[ - Depends(verify_session), - Depends(verify_personal_token), - ], -) - - -@router.get("", response_model=ListTeamKnowledgeRsp, responses={ - status.HTTP_404_NOT_FOUND: {"model": ResponseData}, - }, -) -async def list_kb(request: Request) -> JSONResponse: - """GET /knowledge: 获取当前用户选择的知识库ID列表""" - kb_list = await KnowledgeBaseManager.get_selected_kb(request.state.user_sub) - return JSONResponse( - status_code=status.HTTP_200_OK, - content=ListTeamKnowledgeRsp( - code=status.HTTP_200_OK, - message="success", - result=ListTeamKnowledgeMsg(teamKbList=kb_list), - ).model_dump(exclude_none=True, by_alias=True), - ) - - -@router.put("", response_model=ResponseData) -async def update_kb(request: Request, put_body: UpdateUserKnowledgebaseReq) -> JSONResponse: - """PUT /knowledge: 更新当前用户选择的知识库ID列表""" - kb_ids_update_success = await KnowledgeBaseManager.save_selected_kb( - request.state.user_sub, put_body.kb_ids, - ) - return JSONResponse( - status_code=status.HTTP_200_OK, - content=ResponseData( - code=status.HTTP_200_OK, - message="success", - result=kb_ids_update_success, - ).model_dump(exclude_none=True, by_alias=True), - ) diff --git a/apps/routers/mcp_service.py b/apps/routers/mcp_service.py index 25127158..a370da3e 100644 --- a/apps/routers/mcp_service.py +++ b/apps/routers/mcp_service.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """FastAPI 语义接口中心相关路由""" import logging diff --git a/apps/routers/parameter.py b/apps/routers/parameter.py index 53686ba4..bfc5c106 100644 --- a/apps/routers/parameter.py +++ b/apps/routers/parameter.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """步骤参数相关路由""" import uuid diff --git a/apps/routers/service.py b/apps/routers/service.py index d5fa7aa9..6e428540 100644 --- a/apps/routers/service.py +++ b/apps/routers/service.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """FastAPI 语义接口中心相关路由""" import logging diff --git a/apps/routers/tag.py b/apps/routers/tag.py index 59dc9349..fb566b30 100644 --- a/apps/routers/tag.py +++ b/apps/routers/tag.py @@ -10,7 +10,7 @@ from apps.schemas.response_data import ResponseData from apps.services import TagManager admin_router = APIRouter( - prefix="/api/admin/tag", + prefix="/api/tag", tags=["tag"], dependencies=[ Depends(verify_session), diff --git a/apps/scheduler/call/cmd/prompt.py b/apps/scheduler/call/cmd/prompt.py index 12db5f7d..6172fbd4 100644 --- a/apps/scheduler/call/cmd/prompt.py +++ b/apps/scheduler/call/cmd/prompt.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """命令行生成器相关提示词""" from textwrap import dedent diff --git a/apps/scheduler/call/cmd/schema.py b/apps/scheduler/call/cmd/schema.py index 039e00ae..107032df 100644 --- a/apps/scheduler/call/cmd/schema.py +++ b/apps/scheduler/call/cmd/schema.py @@ -1 +1,2 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """命令行生成工具 数据结构""" diff --git a/apps/scheduler/call/graph/prompt.py b/apps/scheduler/call/graph/prompt.py index 6c44a509..92916422 100644 --- a/apps/scheduler/call/graph/prompt.py +++ b/apps/scheduler/call/graph/prompt.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """图表相关提示词""" from apps.models import LanguageType diff --git a/apps/scheduler/call/rag/prompt.py b/apps/scheduler/call/rag/prompt.py index f3232261..cc869146 100644 --- a/apps/scheduler/call/rag/prompt.py +++ b/apps/scheduler/call/rag/prompt.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """RAG工具的提示词""" from textwrap import dedent diff --git a/apps/scheduler/call/summary/prompt.py b/apps/scheduler/call/summary/prompt.py index 453e251f..0690cb06 100644 --- a/apps/scheduler/call/summary/prompt.py +++ b/apps/scheduler/call/summary/prompt.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """总结工具的提示词""" from textwrap import dedent diff --git a/apps/scheduler/executor/prompt.py b/apps/scheduler/executor/prompt.py index cd50338f..c29dad68 100644 --- a/apps/scheduler/executor/prompt.py +++ b/apps/scheduler/executor/prompt.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Executor相关大模型提示词""" from textwrap import dedent diff --git a/apps/scheduler/executor/qa.py b/apps/scheduler/executor/qa.py index e529cfc8..51595710 100644 --- a/apps/scheduler/executor/qa.py +++ b/apps/scheduler/executor/qa.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """用于执行智能问答的Executor""" import logging @@ -10,7 +11,6 @@ from apps.scheduler.call.rag.schema import DocItem, RAGOutput from apps.schemas.document import DocumentInfo from apps.schemas.enum_var import EventType, SpecialCallType from apps.schemas.flow import Step -from apps.schemas.message import DocumentAddContent from apps.schemas.task import StepQueueItem from .base import BaseExecutor diff --git a/apps/scheduler/scheduler/prompt.py b/apps/scheduler/scheduler/prompt.py index 5f97b33c..12eb4e08 100644 --- a/apps/scheduler/scheduler/prompt.py +++ b/apps/scheduler/scheduler/prompt.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """Scheduler相关的大模型提示词""" from apps.models import LanguageType diff --git a/apps/schemas/appcenter.py b/apps/schemas/appcenter.py index d549ef56..090909b4 100644 --- a/apps/schemas/appcenter.py +++ b/apps/schemas/appcenter.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """应用中心相关 API 基础数据结构定义""" import uuid diff --git a/apps/schemas/comment.py b/apps/schemas/comment.py index 1111f209..2191cba1 100644 --- a/apps/schemas/comment.py +++ b/apps/schemas/comment.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """评论相关的数据结构""" from pydantic import BaseModel, Field diff --git a/apps/schemas/conversation.py b/apps/schemas/conversation.py index b43e5c51..74364d3e 100644 --- a/apps/schemas/conversation.py +++ b/apps/schemas/conversation.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """对话相关数据结构""" import uuid diff --git a/apps/schemas/parameters.py b/apps/schemas/parameters.py index 31714faa..9b769a2d 100644 --- a/apps/schemas/parameters.py +++ b/apps/schemas/parameters.py @@ -1,3 +1,4 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """步骤参数相关""" from enum import Enum diff --git a/apps/schemas/record.py b/apps/schemas/record.py index 9cfb87c7..b8da8bd2 100644 --- a/apps/schemas/record.py +++ b/apps/schemas/record.py @@ -64,8 +64,6 @@ class RecordMetadata(BaseModel): output_tokens: int = Field(default=0, alias="outputTokens") time_cost: float = Field(default=0, alias="timeCost") feature: dict[str, Any] = {} - foot_note_metadata_list: list[FootNoteMetaData] = Field( - default=[], alias="footNoteMetadataList", description="脚注元信息列表") class RecordComment(BaseModel): diff --git a/apps/schemas/service.py b/apps/schemas/service.py index 7a2c2c78..bce4e0b2 100644 --- a/apps/schemas/service.py +++ b/apps/schemas/service.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """语义接口中心相关数据结构""" import uuid diff --git a/apps/schemas/user.py b/apps/schemas/user.py index 61aa2587..24de0aec 100644 --- a/apps/schemas/user.py +++ b/apps/schemas/user.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """User用户信息数据结构""" from pydantic import BaseModel, Field diff --git a/apps/services/__init__.py b/apps/services/__init__.py index 6662cb5a..e4900137 100644 --- a/apps/services/__init__.py +++ b/apps/services/__init__.py @@ -8,7 +8,6 @@ from .conversation import ConversationManager from .document import DocumentManager from .flow import FlowManager from .flow_service import FlowServiceManager -from .knowledge import KnowledgeBaseManager from .knowledge_service import KnowledgeBaseService from .llm import LLMManager from .mcp_service import MCPServiceManager @@ -33,7 +32,6 @@ __all__ = [ "DocumentManager", "FlowManager", "FlowServiceManager", - "KnowledgeBaseManager", "KnowledgeBaseService", "LLMManager", "MCPServiceManager", diff --git a/apps/services/appcenter.py b/apps/services/appcenter.py index 9bb8615b..aa82d140 100644 --- a/apps/services/appcenter.py +++ b/apps/services/appcenter.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """应用中心 Manager""" import logging diff --git a/apps/services/knowledge.py b/apps/services/knowledge.py deleted file mode 100644 index 4f2402c7..00000000 --- a/apps/services/knowledge.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -"""用户资产库管理""" - -import logging -import uuid - -from sqlalchemy import select - -from apps.common.postgres import postgres -from apps.models import User - -logger = logging.getLogger(__name__) - - -class KnowledgeBaseManager: - """用户资产库管理""" - - @staticmethod - async def get_selected_kb(user_sub: str) -> list[uuid.UUID]: - """ - 获取当前用户的知识库ID - - :param user_sub: 用户sub - :return: 知识库ID列表 - """ - async with postgres.session() as session: - selected_kbs = (await session.scalars( - select(User.selectedKB).where(User.userSub == user_sub), - )).one_or_none() - - if not selected_kbs: - logger.error("[KnowledgeBaseManager] 用户 %s 未选择知识库", user_sub) - return [] - - # 所有KB的列表在前端获取 - return selected_kbs - - - @staticmethod - async def save_selected_kb(user_sub: str, kb_ids: list[uuid.UUID]) -> None: - """ - 更新用户当前选择的知识库 - - :param user_sub: 用户sub - :param kb_list: 知识库列表 - :return: 是否更新成功 - """ - async with postgres.session() as session: - user = (await session.scalars( - select(User).where(User.userSub == user_sub), - )).one_or_none() - - if not user: - logger.error("[KnowledgeBaseManager]") - return - - user.selectedKB = kb_ids - await session.commit() diff --git a/apps/services/mcp_service.py b/apps/services/mcp_service.py index 14cd6230..3b999b10 100644 --- a/apps/services/mcp_service.py +++ b/apps/services/mcp_service.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """MCP服务(插件中心)管理器""" import logging diff --git a/apps/services/service.py b/apps/services/service.py index 0741c9fd..2caa9442 100644 --- a/apps/services/service.py +++ b/apps/services/service.py @@ -1,4 +1,4 @@ -# Copyright (c) Huawei Technologies Co., Ltd. 2024-2025. All rights reserved. +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. """语义接口中心 Manager""" import logging @@ -341,7 +341,6 @@ class ServiceCenterManager: id=service_id, name=validated_data.id, description=validated_data.description, - version=validated_data.version, author=user_sub, api=ServiceApiConfig(server=validated_data.servers), permission=Permission(type=PermissionType.PUBLIC), # 默认公开 @@ -380,7 +379,6 @@ class ServiceCenterManager: id=service_id, name=validated_data.id, description=validated_data.description, - version=validated_data.version, author=user_sub, api=ServiceApiConfig(server=validated_data.servers), ) diff --git a/apps/services/session.py b/apps/services/session.py index 70e3c199..94d377f9 100644 --- a/apps/services/session.py +++ b/apps/services/session.py @@ -1,5 +1,5 @@ # Copyright (c) Huawei Technologies Co., Ltd. 2023-2025. All rights reserved. -"""浏览器Session Manager""" +"""会话 Manager""" import logging from datetime import UTC, datetime, timedelta diff --git a/design/call/slot.md b/design/call/slot.md index c738d943..164e19b0 100644 --- a/design/call/slot.md +++ b/design/call/slot.md @@ -2,16 +2,13 @@ ## 概述 -Slot工具是一个智能参数自动填充工具,它通过分析历史步骤数据、背景信息和用户问题,自动生成符合JSON Schema要求的参数对象。该工具支持两阶段填充策略:首先使用大语言模型进行初步填充,如果存在剩余参数则使用FunctionCall进行精确填充。 +Slot工具是一个智能参数自动填充工具,它通过分析历史步骤数据、背景信息和用户问题,自动生成符合JSON Schema要求的参数对象。该工具使用FunctionCall进行精确的剩余参数填充。 ## 功能特性 - **智能参数填充**:基于历史步骤和背景信息自动填充工具参数 -- **两阶段填充策略**:LLM初步填充 + FunctionCall精确填充 - **Schema验证**:支持JSON Schema验证和错误检测 -- **多语言支持**:支持中文和英文两种语言 - **模板化提示词**:使用Jinja2模板引擎动态生成提示词 -- **流式输出**:支持实时流式输出填充结果 - **结构化数据**:基于Pydantic模型进行数据验证和序列化 ## 核心组件 @@ -97,7 +94,6 @@ classDiagram - **DataBase**: 所有Call的输入基类,提供通用的数据验证和序列化功能 - **SlotInput**: 继承自DataBase,包含剩余需要填充的Schema信息 - **SlotOutput**: 继承自DataBase,包含填充后的数据和剩余Schema -- **Slot**: 主要的工具类,负责参数填充的整个流程 - **SlotProcessor**: 参数槽处理器,负责JSON Schema验证和数据转换 ### 数据流转关系 @@ -153,7 +149,6 @@ Slot工具使用Jinja2模板引擎生成提示词,支持中英文两种语言 - **结构化指令**:使用XML标签清晰分隔不同部分 - **动态内容渲染**:通过Jinja2循环语法动态生成历史工具数据 -- **多语言适配**:根据系统语言自动选择合适的模板 - **输出格式控制**:明确指定JSON输出要求和限制 ### 提示词模板结构 @@ -353,48 +348,7 @@ graph TD ### 基本使用 -```python -# 创建Slot工具实例 -slot_tool = await Slot.instance(executor, node) - -# 执行参数填充 -async for chunk in slot_tool.exec(executor, input_data): - if chunk.type == CallOutputType.DATA: - slot_output = chunk.content - print(f"填充数据: {slot_output['slot_data']}") - print(f"剩余Schema: {slot_output['remaining_schema']}") -``` - -### 输入数据示例 - -```python -# Slot工具输入数据结构示例 -slot_input = SlotInput( - remaining_schema={ - "type": "object", - "properties": { - "city": { - "type": "string", - "description": "城市名称" - }, - "date": { - "type": "string", - "description": "查询日期" - } - }, - "required": ["city", "date"] - } -) - -# 上下文数据 -context_data = { - "data": {}, - "current_schema": {...}, - "summary": "用户询问天气信息", - "facts": ["用户对杭州天气感兴趣"], - "step_num": 1 -} -``` +Slot工具是系统内置的隐藏工具,不可由用户直接使用。 ### 输出数据示例 @@ -437,39 +391,6 @@ Slot工具包含以下错误处理机制: - 验证器初始化失败处理 - 字段验证失败时的错误提取 -### 3. 模板渲染错误 - -- Jinja2模板渲染异常处理 -- 变量未定义时的默认值处理 -- 模板语法错误检测 - -### 4. LLM调用异常 - -- 大模型调用失败处理 -- 网络超时和重试机制 -- 响应格式验证 - -## 性能与扩展性 - -### 性能考虑 - -Slot工具在性能方面进行了以下优化: - -- **两阶段填充策略**:优先使用LLM快速填充,必要时使用FunctionCall精确填充 -- **流式输出**:支持实时流式输出,提升用户体验 -- **模板缓存**:Jinja2模板环境复用,减少重复创建开销 -- **Schema验证优化**:使用高效的JSON Schema验证器 - -### 扩展性设计 - -Slot工具设计具有良好的扩展性: - -1. **多语言支持**:可轻松添加新的语言模板 -2. **Schema扩展**:支持自定义JSON Schema验证规则 -3. **填充策略**:可扩展更多填充策略和算法 -4. **数据转换**:支持自定义数据转换器 -5. **集成接口**:基于CoreCall基类,易于集成到调度系统 - ## 依赖关系 - `CoreCall`: 基础调用框架 @@ -479,10 +400,3 @@ Slot工具设计具有良好的扩展性: - `FunctionLLM`: 大语言模型接口和JSON处理 - `jsonschema`: JSON Schema验证库 - `CallVars`: 调用变量和上下文信息 - -## 相关模块 - -- `apps/scheduler/slot/slot.py`: 核心SlotProcessor实现 -- `apps/scheduler/call/core.py`: CoreCall基类 -- `apps/llm/function.py`: FunctionLLM接口 -- `apps/schemas/scheduler.py`: 调度器相关Schema定义 diff --git a/design/call/summary.md b/design/call/summary.md index d24fa403..c4cf0020 100644 --- a/design/call/summary.md +++ b/design/call/summary.md @@ -46,7 +46,6 @@ classDiagram class Summary { +context: ExecutorBackground - +Field(description="对话上下文") +info() CallInfo +instance() Self +_init() DataBase diff --git a/design/services/personal_token.md b/design/services/personal_token.md new file mode 100644 index 00000000..c06651cc --- /dev/null +++ b/design/services/personal_token.md @@ -0,0 +1,164 @@ +# 个人令牌(API Key)服务设计 + +本文档描述 Euler Copilot Framework 中与账号 API Key(Personal Token)相关的鉴权策略、核心流程、接口规范以及错误返回约定。实现参考: + +- `apps/services/personal_token.py`:个人令牌生成、校验 +- `apps/dependency/user.py`:请求依赖校验(`verify_personal_token`、`verify_session`) +- `apps/routers/auth.py`:重置个人令牌接口 `/api/auth/key` +- 使用举例:`apps/routers/user.py` 等路由均依赖 `verify_personal_token` + +## 架构与职责 + +- 个人令牌用于对用户调用进行鉴权,是接口级依赖;受保护路由在鉴权通过后再处理请求。 +- 生效范围与优先级约定: + - 会话(Session):仅在浏览器场景生效(前端 Web 应用)。 + - 个人令牌(API Key):在客户端与 Shell 场景生效(CLI、Agent、集成脚本等)。 + - 二者不能组合使用;若请求同时携带,会优先以 API Key 进行鉴权并忽略会话态。 +- 个人令牌的生成与更新由 `PersonalTokenManager.update_personal_token` 负责;校验由 `verify_personal_token` 委托 `PersonalTokenManager.get_user_by_personal_token` 完成。 + +## 流程图(重置 API Key) + +```mermaid +flowchart TD + A[客户端: POST /api/auth/key] --> B[依赖注入: verify_session] + B --> C[依赖注入: verify_personal_token] + C --> D[AuthRouter.change_personal_token] + D --> E[PersonalTokenManager.update_personal_token] + E -->|成功| F[DB: 更新 User.personalToken] + F --> G[返回新 api_key] + E -->|失败| H[记录异常并返回 500] +``` + +## 时序图(受保护资源访问) + +```mermaid +sequenceDiagram + participant Client + participant Router as FastAPI Router + participant Dep as Dependencies + participant PTM as PersonalTokenManager + participant DB + + Client->>Router: 调用受保护接口(携带 Authorization ) + Router->>Dep: verify_session + Dep-->>Router: 注入 request.state.session_id / user_sub(可选) + Router->>Dep: verify_personal_token + Dep->>PTM: get_user_by_personal_token(token) + PTM->>DB: SELECT userSub WHERE personalToken == token + DB-->>PTM: userSub 或 None + PTM-->>Dep: userSub 或 None + alt token 有效 + Dep-->>Router: 注入 request.state.user_sub + Router-->>Client: 200 成功响应 + else token 无效 + Dep-->>Router: 抛出 401 Personal Token 无效 + Router-->>Client: 401 错误响应 + end +``` + +## 数据模型摘要 + +- 用户表 `User` 至少包含:`userSub`(用户唯一标识)、`personalToken`(个人令牌)。 +- 个人令牌生成逻辑:`sha256(uuid4().hex)[:16]`(16 位十六进制字符串)。 + +## 接口规范 + +### 1) 重置个人令牌 + +- 路径:`POST /api/auth/key` +- 认证:依赖 `verify_session` 与 `verify_personal_token` +- 作用:为当前用户生成新的 API Key,并写入数据库,返回给客户端。 + +请求示例(当前实现中 Authorization 仅用于携带个人令牌;会话头可不传): + +```bash +curl -X POST \ + -H "Authorization: " \ + https://your-host/api/auth/key +``` + +成功响应(200): + +```json +{ + "code": 200, + "message": "success", + "result": { + "api_key": "9f1a2b3c4d5e6f70" + } +} +``` + +失败响应(500,示例): + +```json +{ + "code": 500, + "message": "failed to update personal token", + "result": {} +} +``` + +错误场景(401 未通过鉴权,示例): + +```json +{ + "detail": "Personal Token 无效" +} +``` + +### 2) 受保护资源的通用调用方式 + +- 多数路由(如 `GET /api/user`、`PUT /api/user/llm` 等)要求通过任一鉴权方式方可访问。 +- 使用与优先级: + - 客户端/Shell:仅携带 API Key;`Authorization: `。 + - 浏览器:由会话完成鉴权;`Authorization: Bearer ` 由前端/网关注入。 + - 若两者同时出现,以 API Key 优先,忽略会话态。 + +请求示例(以 `GET /api/user` 为例,客户端/Shell): + +```bash +curl -X GET \ + -H "Authorization: " \ + "https://your-host/api/user?page_size=10&page_num=1" +``` + +成功响应(节选): + +```json +{ + "code": 200, + "message": "用户数据详细信息获取成功", + "result": { + "userInfoList": [ + { "userName": "alice", "userSub": "alice" } + ], + "total": 42 + } +} +``` + +## 安全与最佳实践 + +- 会话仅在浏览器场景生效,API Key 仅在客户端与 Shell 场景生效;不要同时携带,若同时携带则以 API Key 为准。 +- 后端不回显旧密钥,仅在重置操作时返回新密钥一次;客户端需妥善保存。 +- 个人令牌长度固定 16 位,可按需在前后端增加强度与轮换策略。 +- 服务侧可结合访问频率限制与审计日志,及时发现异常使用。 + +## 关键实现参考 + +为避免直接引用代码,这里以自然语言描述关键逻辑: + +- 个人令牌校验(路由依赖) + - 从请求头读取 `Authorization`,将其作为个人令牌使用;若缺失则返回未授权错误。 + - 通过个人令牌查询对应的用户唯一标识;若查无此人则返回未授权错误。 + - 校验通过后,将用户唯一标识写入请求上下文,供后续处理使用。 + +- 重置个人令牌(POST /api/auth/key) + - 在受保护路由中,由会话与个人令牌依赖共同保护;请求到达后,为当前用户生成新令牌。 +- 生成方式为对随机 UUID 进行哈希处理并截取固定长度(16 位十六进制字符串)。 + - 将新令牌写入数据库并作为响应返回;若数据库更新失败,返回服务器错误。 + +- 令牌-用户映射与更新 + - “令牌查用户”:按“令牌等于用户表中的个人令牌字段”的条件检索,返回匹配到的用户标识;异常会被记录并视为查找失败。 + - “更新令牌”:按用户标识定位记录并写入新生成的令牌;更新异常会被记录并返回失败。 diff --git a/design/services/session.md b/design/services/session.md new file mode 100644 index 00000000..abb7289b --- /dev/null +++ b/design/services/session.md @@ -0,0 +1,267 @@ +# Session模块设计文档 + +## 概述 + +Session模块是Euler Copilot框架中的会话管理系统,负责创建、删除和验证用户会话。该模块实现了基于数据库的会话存储机制,支持会话创建、会话删除、用户信息获取以及黑名单用户检查功能,确保系统安全性和用户身份验证的可靠性。 + +## 核心功能 + +- **会话创建**: 为用户创建新的浏览器会话 +- **会话删除**: 删除指定的会话记录 +- **用户信息获取**: 从会话中获取用户标识 +- **黑名单检查**: 验证用户是否在黑名单中 +- **会话查询**: 根据用户标识查询会话 + +## 数据模型 + +### Session实体 + +- **表名**: `framework_session` +- **主键**: `id` (String(255), 默认为随机生成的16字节十六进制字符串) +- **字段**: + - `userSub`: 用户标识 (String(50), 外键关联framework_user.userSub) + - `ip`: IP地址 (String(255), 可为空) + - `pluginId`: 插件ID (String(255), 可为空) + - `token`: Token信息 (String(2000), 可为空) + - `validUntil`: 有效期 (DateTime, 时区感知) + - `sessionType`: 会话类型 (Enum(SessionType)) + +### SessionType枚举 + +- `ACCESS_TOKEN`: 访问令牌 +- `REFRESH_TOKEN`: 刷新令牌 +- `PLUGIN_TOKEN`: 插件令牌 +- `CODE`: 代码类型会话 + +## 配置常量 + +- `SESSION_TTL`: 会话有效期,单位为分钟 (默认: 30 \* 24 \* 60,即30天) + +## 服务层 + +### SessionManager类 + +#### 静态方法 + +- `create_session(user_sub, ip)`: 创建浏览器会话 +- `delete_session(session_id)`: 删除浏览器会话 +- `get_user(session_id)`: 从会话中获取用户 +- `get_session_by_user_sub(user_sub)`: 根据用户标识获取会话 + +## 时序图 + +```mermaid +sequenceDiagram + participant Client as 客户端 + participant SessionMgr as SessionManager + participant BlacklistMgr as UserBlacklistManager + participant DB as 数据库 + + Note over Client, DB: 创建会话流程 + Client->>SessionMgr: create_session(user_sub, ip) + SessionMgr->>SessionMgr: 验证参数 + alt 参数无效 + SessionMgr-->>Client: 抛出ValueError + else 参数有效 + SessionMgr->>DB: 创建Session对象 + Note over SessionMgr, DB: 设置会话有效期为当前时间+SESSION_TTL + SessionMgr->>DB: session.merge(data) + SessionMgr->>DB: session.commit() + DB-->>SessionMgr: 提交成功 + SessionMgr-->>Client: 返回session_id + end + + Note over Client, DB: 获取用户流程 + Client->>SessionMgr: get_user(session_id) + SessionMgr->>DB: 查询Session.userSub + DB-->>SessionMgr: 返回user_sub或None + + alt 用户不存在 + SessionMgr-->>Client: 返回None + else 用户存在 + SessionMgr->>BlacklistMgr: check_blacklisted_users(user_sub) + BlacklistMgr->>DB: 查询用户黑名单状态 + DB-->>BlacklistMgr: 返回黑名单状态 + BlacklistMgr-->>SessionMgr: 返回是否在黑名单中 + + alt 用户在黑名单中 + SessionMgr->>SessionMgr: 记录错误日志 + SessionMgr->>SessionMgr: delete_session(session_id) + SessionMgr->>DB: 删除会话 + DB-->>SessionMgr: 删除成功 + SessionMgr-->>Client: 返回None + else 用户不在黑名单中 + SessionMgr-->>Client: 返回user_sub + end + end + + Note over Client, DB: 删除会话流程 + Client->>SessionMgr: delete_session(session_id) + alt session_id为空 + SessionMgr-->>Client: 直接返回 + else session_id有效 + SessionMgr->>DB: 查询Session + DB-->>SessionMgr: 返回session_data或None + alt 会话存在 + SessionMgr->>DB: session.delete(session_data) + DB-->>SessionMgr: 删除成功 + end + SessionMgr->>DB: session.commit() + DB-->>SessionMgr: 提交成功 + SessionMgr-->>Client: 返回None + end + + Note over Client, DB: 根据用户查询会话流程 + Client->>SessionMgr: get_session_by_user_sub(user_sub) + SessionMgr->>DB: 查询Session.id + DB-->>SessionMgr: 返回session_id或None + SessionMgr-->>Client: 返回session_id或None +``` + +## ER图 + +```mermaid +erDiagram + User ||--o{ Session : "用户拥有会话" + User ||--o{ SessionActivity : "用户产生活动" + + User { + string userSub PK "用户标识" + boolean isWhitelisted "是否白名单" + integer credit "信用分" + string personalToken "个人令牌" + } + + Session { + string id PK "会话ID" + string userSub FK "用户标识" + string ip "IP地址" + string pluginId "插件ID" + string token "Token信息" + datetime validUntil "有效期" + enum sessionType "会话类型" + } + + SessionActivity { + BigInteger id PK + string userSub FK "用户标识" + datetime timestamp "活动时间戳" + } +``` + +## 流程图 + +```mermaid +flowchart TD + subgraph "创建会话流程" + A1[客户端请求创建会话] --> B1{验证参数} + B1 -->|参数无效| C1[抛出ValueError] + B1 -->|参数有效| D1[创建Session对象] + D1 --> E1[设置会话有效期] + E1 --> F1[保存到数据库] + F1 --> G1[返回session_id] + end + + subgraph "获取用户流程" + A2[客户端请求获取用户] --> B2[查询会话] + B2 --> C2{会话存在?} + C2 -->|不存在| D2[返回None] + C2 -->|存在| E2[查询黑名单] + E2 --> F2{用户在黑名单?} + F2 -->|是| G2[记录错误日志] + G2 --> H2[删除会话] + H2 --> I2[返回None] + F2 -->|否| J2[返回user_sub] + end + + subgraph "删除会话流程" + A3[客户端请求删除会话] --> B3{session_id为空?} + B3 -->|是| C3[直接返回] + B3 -->|否| D3[查询会话] + D3 --> E3{会话存在?} + E3 -->|是| F3[删除会话] + E3 -->|否| G3[提交事务] + F3 --> G3 + G3 --> H3[返回None] + end + + subgraph "根据用户查询会话流程" + A4[客户端请求查询会话] --> B4[查询数据库] + B4 --> C4[返回session_id或None] + end + + style A1 fill:#e1f5fe + style G1 fill:#c8e6c9 + style A2 fill:#e1f5fe + style D2 fill:#fff3e0 + style I2 fill:#fff3e0 + style J2 fill:#c8e6c9 + style A3 fill:#e1f5fe + style H3 fill:#c8e6c9 + style A4 fill:#e1f5fe + style C4 fill:#c8e6c9 +``` + +## 安全考虑 + +1. **会话有效期**: 会话设置了30天的默认有效期,防止长期未使用的会话被滥用 +2. **IP地址验证**: 创建会话时验证IP地址,防止无效请求 +3. **用户黑名单检查**: 获取用户信息时检查用户是否在黑名单中,增强系统安全性 +4. **会话自动清理**: 对于黑名单用户的会话自动删除,防止未授权访问 +5. **参数验证**: 对输入参数进行严格验证,防止无效数据 + +## 性能优化 + +1. **数据库索引**: 对userSub和id字段建立索引,提高查询效率 +2. **异步操作**: 所有数据库操作使用异步方式,提高并发性能 +3. **连接池管理**: 使用数据库连接池管理连接,减少连接开销 +4. **最小化查询**: get_user方法只查询必要的userSub字段,而非整个Session对象 + +## 与其他模块的交互 + +1. **UserBlacklistManager**: 用于检查用户是否在黑名单中 +2. **PostgreSQL数据库**: 用于存储和检索会话数据 +3. **认证系统**: 提供会话创建和验证功能 +4. **路由层**: 使用会话管理功能进行用户身份验证 + +## 异常处理 + +### ValueError异常 + +- **触发条件**: 当创建会话时提供的IP地址或用户标识为空 +- **错误信息**: "用户IP错误!" 或 "用户名错误!" +- **处理方式**: 向上层抛出异常,由调用方处理 + +## 配置说明 + +```toml +# 会话配置 +SESSION_TTL = 43200 # 会话有效期(分钟),默认30天 +``` + +## 使用示例 + +```python +# 创建会话 +session_id = await SessionManager.create_session(user_sub="user123", ip="192.168.1.1") + +# 获取用户信息 +user_sub = await SessionManager.get_user(session_id) +if user_sub: + # 用户有效,处理业务逻辑 +else: + # 用户无效或在黑名单中 + +# 删除会话 +await SessionManager.delete_session(session_id) + +# 根据用户查询会话 +session_id = await SessionManager.get_session_by_user_sub(user_sub) +``` + +## 扩展性 + +1. **会话类型扩展**: SessionType枚举可以扩展支持更多会话类型 +2. **会话属性扩展**: Session模型可以添加更多字段以支持额外功能 +3. **验证机制扩展**: 可以增加更多的验证逻辑,如设备指纹验证 +4. **分布式会话**: 可以扩展支持分布式环境下的会话管理 diff --git a/design/services/tag.md b/design/services/tag.md index 21af2aa8..8b840dcf 100644 --- a/design/services/tag.md +++ b/design/services/tag.md @@ -2,7 +2,7 @@ ## 概述 -Tag模块是Euler Copilot框架中的用户标签管理系统,用于管理用户分类标签的定义、创建、更新和删除操作。该模块支持标签的CRUD操作,并提供用户标签关联功能。 +Tag模块是openEuler Intelligence框架中的用户标签管理系统,用于管理用户分类标签的定义、创建、更新和删除操作。该模块支持标签的CRUD操作,并提供用户标签关联功能。 ## 核心功能 @@ -13,35 +13,56 @@ Tag模块是Euler Copilot框架中的用户标签管理系统,用于管理用 ## 数据模型 -### Tag实体 - -- **表名**: `framework_tag` -- **主键**: `id` (BigInteger, 自增) -- **字段**: - - `name`: 标签名称 (String(255), 唯一索引) - - `definition`: 标签定义 (String(2000)) - - `updatedAt`: 更新时间 (DateTime, 时区感知) +```mermaid +erDiagram + framework_user ||--o{ framework_user_tag : "用户拥有标签" + framework_tag ||--o{ framework_user_tag : "标签被用户使用" + + framework_user { + BigInteger id PK "主键" + string userSub UK "用户标识" + datetime lastLogin "最后登录时间" + boolean isActive "是否活跃" + boolean isWhitelisted "是否白名单" + integer credit "风控分" + string personalToken "个人令牌" + string functionLLM "函数模型ID" + string embeddingLLM "向量模型ID" + boolean autoExecute "自动执行" + } + + framework_tag { + BigInteger id PK "主键" + string name UK "标签名称(唯一索引)" + string definition "标签定义" + datetime updatedAt "更新时间(时区感知)" + } + + framework_user_tag { + BigInteger id PK "主键" + string userSub FK "用户标识(外键)" + BigInteger tag FK "标签ID(外键)" + integer count "标签使用频次(默认0)" + } +``` -### UserTag关联实体 +### 数据表说明 -- **表名**: `framework_user_tag` -- **主键**: `id` (BigInteger, 自增) -- **字段**: - - `userSub`: 用户标识 (String(50), 外键关联framework_user.userSub) - - `tag`: 标签ID (BigInteger, 外键关联framework_tag.id) - - `count`: 标签使用频次 (Integer, 默认0) +- **framework_tag**: 标签基础信息表,存储标签的定义和元数据 +- **framework_user_tag**: 用户标签关联表,记录用户与标签的多对多关系及使用频次 +- **framework_user**: 用户基础信息表,通过userSub字段与标签系统关联 ## API接口 ### 管理接口 (需要管理员权限) -#### GET /api/admin/tag +#### GET /api/tag - **功能**: 获取所有标签列表 - **权限**: 管理员 - **返回**: 标签信息列表 -#### POST /api/admin/tag +#### POST /api/tag - **功能**: 添加或更新标签 - **权限**: 管理员 @@ -50,7 +71,7 @@ Tag模块是Euler Copilot框架中的用户标签管理系统,用于管理用 - `description`: 标签描述 - **逻辑**: 如果标签不存在则创建,存在则更新 -#### DELETE /api/admin/tag +#### DELETE /api/tag - **功能**: 删除标签 - **权限**: 管理员 @@ -80,7 +101,7 @@ sequenceDiagram participant DB as 数据库 Note over Client, DB: 标签查询流程 - Client->>Router: GET /api/admin/tag + Client->>Router: GET /api/tag Router->>Service: get_all_tag() Service->>DB: SELECT * FROM framework_tag DB-->>Service: 返回标签列表 @@ -88,7 +109,7 @@ sequenceDiagram Router-->>Client: 返回JSON响应 Note over Client, DB: 标签创建/更新流程 - Client->>Router: POST /api/admin/tag + Client->>Router: POST /api/tag Router->>Service: update_tag_by_name(data) Service->>DB: SELECT * FROM framework_tag WHERE name=? DB-->>Service: 返回查询结果 @@ -102,7 +123,7 @@ sequenceDiagram Router-->>Client: 返回成功响应 Note over Client, DB: 标签删除流程 - Client->>Router: DELETE /api/admin/tag + Client->>Router: DELETE /api/tag Router->>Service: delete_tag(data) Service->>DB: SELECT * FROM framework_tag WHERE name=? DB-->>Service: 返回查询结果 @@ -116,7 +137,7 @@ sequenceDiagram Router-->>Client: 返回响应结果 Note over Client, DB: 用户标签查询流程 - Client->>Router: GET /api/admin/tag?userSub=xxx + Client->>Router: GET /api/user/tag Router->>Service: get_tag_by_user_sub(user_sub) Service->>DB: SELECT * FROM framework_user_tag WHERE userSub=? DB-->>Service: 返回用户标签关联 @@ -128,41 +149,6 @@ sequenceDiagram Router-->>Client: 返回JSON响应 ``` -## ER图 - -```mermaid -erDiagram - User ||--o{ UserTag : "用户拥有标签" - Tag ||--o{ UserTag : "标签被用户使用" - - User { - BigInteger id PK - string userSub UK "用户标识" - datetime lastLogin "最后登录时间" - boolean isActive "是否活跃" - boolean isWhitelisted "是否白名单" - integer credit "风控分" - string personalToken "个人令牌" - string functionLLM "函数模型ID" - string embeddingLLM "向量模型ID" - boolean autoExecute "自动执行" - } - - Tag { - BigInteger id PK - string name UK "标签名称" - string definition "标签定义" - datetime updatedAt "更新时间" - } - - UserTag { - BigInteger id PK - string userSub FK "用户标识" - BigInteger tag FK "标签ID" - integer count "使用频次" - } -``` - ## 流程图 ```mermaid @@ -257,19 +243,3 @@ flowchart LR 1. **权限控制**: 所有标签管理操作需要管理员权限 2. **数据验证**: 输入数据长度和格式验证 -3. **错误处理**: 完善的异常处理和错误信息返回 -4. **SQL注入防护**: 使用SQLAlchemy ORM防止SQL注入 - -## 性能优化 - -1. **索引优化**: 标签名称建立唯一索引,提高查询效率 -2. **连接池**: 使用数据库连接池管理连接 -3. **异步操作**: 所有数据库操作使用异步方式 -4. **缓存策略**: 可考虑对频繁查询的标签信息进行缓存 - -## 扩展性 - -1. **标签分类**: 可扩展支持标签分类和层级结构 -2. **标签权限**: 可扩展支持标签级别的权限控制 -3. **标签统计**: 可扩展更丰富的标签使用统计分析 -4. **批量操作**: 可扩展支持批量标签管理操作 diff --git a/design/services/user.md b/design/services/user.md new file mode 100644 index 00000000..742d6bd7 --- /dev/null +++ b/design/services/user.md @@ -0,0 +1,404 @@ +# User模块设计文档 + +## 概述 + +User模块是Euler Copilot框架中的核心用户管理模块,负责处理用户信息的CRUD操作、用户LLM配置管理、用户标签管理等功能。该模块采用分层架构设计,包含数据模型层、服务层和路由层。 + +## 架构设计 + +### 模块结构 + +```text +apps/ +├── models/user.py # 用户数据模型 +├── services/user.py # 用户服务层 +├── routers/user.py # 用户路由层 +├── schemas/ +│ ├── user.py # 用户响应数据结构 +│ ├── request_data.py # 用户请求数据结构 +│ └── response_data.py # 通用响应数据结构 +└── services/ + ├── user_tag.py # 用户标签服务 + ├── llm.py # LLM管理服务 + └── personal_token.py # 个人令牌服务 +``` + +### 数据模型关系 + +```mermaid +erDiagram + User ||--o{ UserFavorite : "用户收藏" + User ||--o{ UserAppUsage : "应用使用" + User ||--o{ UserTag : "用户标签" + User ||--o{ Conversation : "对话记录" + + User { + bigint id PK "用户ID" + string userSub UK "用户标识" + datetime lastLogin "最后登录时间" + boolean isActive "是否活跃" + boolean isWhitelisted "是否白名单" + int credit "风控分" + string personalToken "个人令牌" + string functionLLM "函数模型ID" + string embeddingLLM "向量模型ID" + boolean autoExecute "自动执行" + } + + UserFavorite { + bigint id PK "收藏ID" + string userSub FK "用户标识" + enum favouriteType "收藏类型" + uuid itemId "项目ID" + } + + UserAppUsage { + bigint id PK "使用记录ID" + string userSub FK "用户标识" + uuid appId FK "应用ID" + int usageCount "使用次数" + datetime lastUsed "最后使用时间" + } + + UserTag { + bigint id PK "标签ID" + string userSub FK "用户标识" + bigint tag FK "标签ID" + int count "标签归类次数" + } + + Tag { + bigint id PK "标签ID" + string name "标签名称" + string description "标签描述" + } + + LLMData { + string id PK "模型ID" + string baseUrl "API地址" + string apiKey "API密钥" + string modelName "模型名称" + int maxTokens "最大Token" + string provider "提供商" + int ctxLength "上下文长度" + } +``` + +## 核心功能 + +### 1. 用户管理 (UserManager) + +#### 功能流程图 + +```mermaid +flowchart TD + A[用户请求] --> B{操作类型} + + B -->|获取用户列表| C[list_user] + B -->|获取单个用户| D[get_user] + B -->|更新用户信息| E[update_user] + B -->|删除用户| F[delete_user] + + C --> C1[查询用户总数] + C1 --> C2[分页查询用户列表] + C2 --> C3[返回用户列表和总数] + + D --> D1[根据userSub查询用户] + D1 --> D2[返回用户信息或None] + + E --> E1{用户是否存在} + E1 -->|不存在| E2[创建新用户] + E1 -->|存在| E3[更新用户字段] + E2 --> E4[保存到数据库] + E3 --> E5[更新lastLogin时间] + E5 --> E4 + + F --> F1{用户是否存在} + F1 -->|不存在| F2[直接返回] + F1 -->|存在| F3[删除用户记录] + F3 --> F4[删除相关对话记录] + + style A fill:#e1f5fe + style E2 fill:#fff3e0 + style E3 fill:#e8f5e8 + style F3 fill:#ffebee +``` + +#### 主要方法 + +1. **list_user(n, page)**: 分页获取用户列表 +2. **get_user(user_sub)**: 根据用户标识获取用户信息 +3. **update_user(user_sub, data)**: 更新用户信息,支持创建新用户 +4. **delete_user(user_sub)**: 删除用户及相关数据 + +### 2. 用户LLM配置管理 + +#### LLM配置更新时序图 + +```mermaid +sequenceDiagram + participant Client as 客户端 + participant Router as 用户路由 + participant LLMManager as LLM管理器 + participant DB as 数据库 + participant Pool as 向量池 + participant Embedding as 向量模型 + + Client->>Router: PUT /api/user/llm + Router->>LLMManager: update_user_selected_llm(user_sub, request) + + LLMManager->>DB: 查询用户信息 + DB-->>LLMManager: 返回用户数据 + + alt 用户不存在 + LLMManager-->>Router: 抛出ValueError异常 + Router-->>Client: 返回500错误 + else 用户存在 + LLMManager->>DB: 更新用户的functionLLM和embeddingLLM + DB-->>LLMManager: 更新成功 + + alt embedding模型发生变化 + LLMManager->>LLMManager: 获取新embedding模型配置 + LLMManager->>Embedding: 创建Embedding实例 + Embedding->>Embedding: 初始化模型 + LLMManager->>Pool: 设置新的向量模型 + Pool->>Pool: 触发向量化过程 + end + + LLMManager-->>Router: 更新完成 + Router-->>Client: 返回成功响应 + end +``` + +#### 核心逻辑 + +1. **模型验证**: 验证用户选择的LLM模型是否存在 +2. **数据更新**: 更新用户表中的functionLLM和embeddingLLM字段 +3. **向量化处理**: 当embedding模型变化时,自动触发向量化过程 + +### 3. 用户标签管理 + +#### 用户标签获取流程 + +```mermaid +flowchart TD + A[客户端请求] --> B[GET /api/user/tag] + B --> C[UserTagManager.get_user_domain_by_user_sub_and_topk] + + C --> D[查询用户标签记录] + D --> E{是否有topk限制} + E -->|是| F[按count降序排列,限制topk条] + E -->|否| G[按count降序排列,返回全部] + + F --> H[遍历用户标签记录] + G --> H + H --> I[根据tag ID查询标签详情] + I --> J[构建UserTagInfo对象] + J --> K[返回标签列表] + + style A fill:#e1f5fe + style K fill:#e8f5e8 +``` + +#### 标签更新流程 + +```mermaid +flowchart TD + A[标签更新请求] --> B[update_user_domain_by_user_sub_and_domain_name] + B --> C[根据domain_name查询Tag] + + C --> D{Tag是否存在} + D -->|不存在| E[抛出ValueError异常] + D -->|存在| F[查询用户标签记录] + + F --> G{用户标签记录是否存在} + G -->|不存在| H[创建新的UserTag记录] + G -->|存在| I[增加count计数] + + H --> J[保存到数据库] + I --> J + J --> K[更新完成] + + style E fill:#ffebee + style K fill:#e8f5e8 +``` + +## API接口设计 + +### 路由配置 + +```python +router = APIRouter( + prefix="/api/user", + tags=["user"], + dependencies=[Depends(verify_session), Depends(verify_personal_token)], +) +``` + +### 接口列表 + +| 方法 | 路径 | 功能 | 描述 | +|------|------|------|------| +| POST | `/api/user/user` | 更新用户信息 | 更新当前登录用户的基本信息 | +| GET | `/api/user` | 获取用户列表 | 分页获取除当前用户外的所有用户 | +| PUT | `/api/user/llm` | 更新用户LLM配置 | 更新用户选择的Function和Embedding模型 | +| GET | `/api/user/tag` | 获取用户标签 | 获取用户最常涉及的领域标签 | + +### 请求响应结构 + +#### 更新用户信息请求 + +```json +{ + "userName": "用户名", + "autoExecute": false, + "agreementConfirmed": true, + "lastLogin": "2024-01-01T00:00:00Z" +} +``` + +#### 更新LLM配置请求 + +```json +{ + "functionLLM": "function-model-id", + "embeddingLLM": "embedding-model-id" +} +``` + +#### 用户列表响应 + +```json +{ + "code": 200, + "message": "用户数据详细信息获取成功", + "result": { + "total": 100, + "userInfoList": [ + { + "userSub": "user-123", + "userName": "张三" + } + ] + } +} +``` + +## 数据流转图 + +```mermaid +graph LR + A[客户端请求] --> B[路由层] + B --> C[依赖验证] + C --> D[服务层] + D --> E[数据模型层] + E --> F[数据库] + + F --> E + E --> D + D --> B + B --> A + + subgraph "路由层" + B1[用户路由] + B2[会话验证] + B3[令牌验证] + end + + subgraph "服务层" + D1[UserManager] + D2[LLMManager] + D3[UserTagManager] + D4[PersonalTokenManager] + end + + subgraph "数据层" + E1[User模型] + E2[UserTag模型] + E3[UserFavorite模型] + E4[UserAppUsage模型] + end + + style A fill:#e1f5fe + style F fill:#e8f5e8 +``` + +## 安全机制 + +### 1. 身份验证 + +- **会话验证**: 通过`verify_session`依赖验证用户会话 +- **个人令牌**: 通过`verify_personal_token`依赖验证个人访问令牌 + +### 2. 数据隔离 + +- 用户只能访问和修改自己的数据 +- 用户列表接口排除当前用户,避免自我操作 + +### 3. 数据完整性 + +- 用户删除时自动清理相关对话记录 +- LLM配置更新时验证模型存在性 +- 标签更新时验证标签有效性 + +## 性能优化 + +### 1. 数据库优化 + +- 用户标识(userSub)建立唯一索引 +- 分页查询避免一次性加载大量数据 +- 使用数据库事务确保数据一致性 + +### 2. 缓存策略 + +- 用户信息可以考虑缓存,减少数据库查询 +- 标签数据可以定期更新,避免实时计算 + +### 3. 异步处理 + +- 向量化过程异步执行,不阻塞用户请求 +- 使用异步数据库会话提高并发性能 + +## 错误处理 + +### 常见错误场景 + +1. **用户不存在**: 返回404状态码 +2. **LLM模型不存在**: 返回500状态码,包含错误信息 +3. **标签不存在**: 返回500状态码 +4. **权限不足**: 返回403状态码 +5. **数据验证失败**: 返回400状态码 + +### 错误响应格式 + +```json +{ + "code": 500, + "message": "具体错误信息", + "result": null +} +``` + +## 扩展性设计 + +### 1. 模块化设计 + +- 服务层独立,便于单元测试 +- 数据模型与业务逻辑分离 +- 支持插件式扩展 + +### 2. 配置化 + +- 用户权限配置化 +- LLM模型配置化 +- 标签系统可扩展 + +### 3. 监控和日志 + +- 完整的操作日志记录 +- 性能指标监控 +- 错误追踪和告警 + +## 总结 + +User模块作为openEuler Intelligence框架的核心组件,提供了完整的用户管理功能。通过分层架构设计、完善的错误处理机制和良好的扩展性,确保了系统的稳定性和可维护性。模块支持用户信息管理、LLM配置、标签系统等核心功能,为用户提供了个性化的AI助手体验。 -- Gitee