[modify] app_api

This commit is contained in:
Mark
2025-12-26 10:24:36 +08:00
parent dd18e2f599
commit 553e658e05
3 changed files with 76 additions and 43 deletions

View File

@@ -1,30 +1,28 @@
"""App 服务接口 - 基于 API Key 认证"""
import uuid
from typing import Annotated
from fastapi import APIRouter, Depends, Request, Body
from sqlalchemy.orm import Session
from typing import Optional, Annotated
from starlette.responses import StreamingResponse
from app.core.api_key_auth import require_api_key
from app.db import get_db
from app.core.response_utils import success
from app.core.error_codes import BizCode
from app.core.exceptions import BusinessException
from app.core.logging_config import get_business_logger
from app.core.response_utils import success
from app.db import get_db
from app.dependencies import get_app_or_workspace
from app.models import AppRelease
from app.repositories import knowledge_repository
from app.schemas import AppChatRequest, conversation_schema
from app.models.app_model import App
from app.models.app_model import AppType
from app.repositories import knowledge_repository
from app.repositories.end_user_repository import EndUserRepository
from app.core.exceptions import BusinessException
from app.core.error_codes import BizCode
from app.schemas import AppChatRequest, conversation_schema
from app.schemas.api_key_schema import ApiKeyAuth
from app.services import workspace_service
from app.services.app_chat_service import AppChatService, get_app_chat_service
from app.services.app_service import AppService
from app.services.conversation_service import ConversationService, get_conversation_service
from app.services.workflow_service import WorkflowService, get_workflow_service
from app.utils.app_config_utils import dict_to_multi_agent_config,dict_to_workflow_config,agent_config_4_app_release
from app.utils.app_config_utils import dict_to_multi_agent_config, dict_to_workflow_config, agent_config_4_app_release
from app.services.app_service import get_app_service, AppService
router = APIRouter(prefix="/app", tags=["V1 - App API"])
logger = get_business_logger()
@@ -37,8 +35,9 @@ async def list_apps():
# /v1/apps/{resource_id}/chat
# async def chat(
# @router.post("/chat")
# @require_api_key(scopes=["app"])
# async def chat2(
# request: Request,
# api_key_auth: ApiKeyAuth = None,
# db: Session = Depends(get_db),
@@ -57,7 +56,6 @@ async def list_apps():
# db: db_session
# """
# logger.info(f"API Key Auth: {api_key_auth}")
# logger.info(f"Resource ID: {resource_id}")
# logger.info(f"Message: {message}")
# return success(data={"received": True}, msg="消息已接收")
@@ -76,15 +74,21 @@ def _checkAppConfig(app: App):
raise BusinessException("不支持的应用类型", BizCode.AGENT_CONFIG_MISSING)
@router.post("/chat")
# @require_api_key(scopes=["app"])
@require_api_key(scopes=["app"])
async def chat(
payload: AppChatRequest,
app: App = Depends(get_app_or_workspace),
request:Request,
api_key_auth: ApiKeyAuth = None,
db: Session = Depends(get_db),
conversation_service: Annotated[ConversationService, Depends(get_conversation_service)] = None,
app_chat_service: Annotated[AppChatService, Depends(get_app_chat_service)] = None,
app_service: Annotated[AppService, Depends(get_app_service)] = None,
message: str = Body(..., description="聊天消息内容"),
):
body = await request.json()
payload = AppChatRequest(**body)
other_id = payload.user_id
app = app_service.get_app(api_key_auth.resource_id, api_key_auth.workspace_id)
other_id = payload.user_id
workspace_id = app.workspace_id
end_user_repo = EndUserRepository(db)
@@ -176,7 +180,7 @@ async def chat(
storage_type=storage_type,
user_rag_memory_id=user_rag_memory_id
)
return success(data=conversation_schema.ChatResponse(**result))
return success(data=conversation_schema.ChatResponse(**result).model_dump(mode="json"))
elif app_type == AppType.MULTI_AGENT:
# 多 Agent 流式返回
config = dict_to_multi_agent_config(app.current_release.config,app.id)
@@ -220,7 +224,7 @@ async def chat(
user_rag_memory_id=user_rag_memory_id
)
return success(data=conversation_schema.ChatResponse(**result))
return success(data=conversation_schema.ChatResponse(**result).model_dump(mode="json"))
elif app_type == AppType.WORKFLOW:
# 多 Agent 流式返回
config = dict_to_workflow_config(app.current_release.config,app.id)
@@ -264,7 +268,7 @@ async def chat(
user_rag_memory_id=user_rag_memory_id
)
return success(data=conversation_schema.ChatResponse(**result))
return success(data=conversation_schema.ChatResponse(**result).model_dump(mode="json"))
else:
from app.core.exceptions import BusinessException
from app.core.error_codes import BizCode

View File

@@ -1,26 +1,42 @@
"""多 Agent 相关数据模型"""
import datetime
import uuid
from enum import StrEnum
from sqlalchemy import Column, String, Boolean, DateTime, Integer, Float, Text, ForeignKey
from sqlalchemy.dialects.postgresql import UUID, JSON
from sqlalchemy.orm import relationship
from app.db import Base
class OrchestrationMode(StrEnum):
"""图标类型枚举"""
SEQUENTIAL = "sequential"
PARALLEL = "parallel"
CONDITIONAL = "conditional"
class AggregationStrategy(StrEnum):
"""图标类型枚举"""
MERGE = "merge"
VOTE = "vote"
PRIORITY = "priority"
class MultiAgentConfig(Base):
"""多 Agent 配置表"""
__tablename__ = "multi_agent_configs"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
# 关联应用
app_id = Column(UUID(as_uuid=True), ForeignKey("apps.id"), nullable=False, unique=True, index=True, comment="关联应用")
# 主 Agent (存储发布版本 ID)
master_agent_id = Column(UUID(as_uuid=True), ForeignKey("app_releases.id"), nullable=False, comment="主 Agent 发布版本 ID")
master_agent_id = Column(UUID(as_uuid=True), ForeignKey("app_releases.id"), nullable=True, comment="主 Agent 发布版本 ID")
master_agent_name = Column(String(100), comment="主 Agent 名称")
default_model_config_id = Column(UUID(as_uuid=True), ForeignKey("model_configs.id"), nullable=False,server_default=str(uuid.UUID(int=0)), index=True, comment="默认模型配置ID")
# 结构化配置(直接存储 JSON
model_parameters = Column(JSON, nullable=True, comment="模型参数配置temperature、max_tokens等")
# 协作模式
orchestration_mode = Column(
String(20),
@@ -28,7 +44,7 @@ class MultiAgentConfig(Base):
default="conditional",
comment="协作模式: sequential|parallel|conditional|loop"
)
# 子 Agent 列表
sub_agents = Column(
JSON,
@@ -36,13 +52,13 @@ class MultiAgentConfig(Base):
default=list,
comment="子 Agent 列表: [{'agent_id': 'uuid', 'name': '...', 'role': '...', 'priority': 1}]"
)
# 路由规则
routing_rules = Column(
JSON,
comment="路由规则: [{'condition': '...', 'target_agent_id': 'uuid', 'priority': 1}]"
)
# 执行配置
execution_config = Column(
JSON,
@@ -50,7 +66,7 @@ class MultiAgentConfig(Base):
default=dict,
comment="执行配置: {'max_iterations': 5, 'timeout': 60, 'parallel_limit': 3}"
)
# 结果整合策略
aggregation_strategy = Column(
String(20),
@@ -58,12 +74,12 @@ class MultiAgentConfig(Base):
default="merge",
comment="结果整合策略: merge|vote|priority|custom"
)
# 状态
is_active = Column(Boolean, default=True, nullable=False)
created_at = Column(DateTime, default=datetime.datetime.now)
updated_at = Column(DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now)
# 关系
app = relationship("App")
master_agent_release = relationship("AppRelease", foreign_keys=[master_agent_id])
@@ -77,7 +93,7 @@ class AgentInvocation(Base):
__tablename__ = "agent_invocations"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
# 调用关系
caller_agent_id = Column(
UUID(as_uuid=True),
@@ -93,7 +109,7 @@ class AgentInvocation(Base):
index=True,
comment="被调用者 Agent ID"
)
# 关联信息
conversation_id = Column(
UUID(as_uuid=True),
@@ -106,12 +122,12 @@ class AgentInvocation(Base):
index=True,
comment="父调用 ID用于追踪调用链"
)
# 输入输出
input_message = Column(Text, nullable=False, comment="输入消息")
output_message = Column(Text, comment="输出消息")
context = Column(JSON, comment="上下文信息")
# 状态
status = Column(
String(20),
@@ -121,18 +137,18 @@ class AgentInvocation(Base):
comment="状态: pending|running|completed|failed"
)
error_message = Column(Text, comment="错误信息")
# 性能指标
started_at = Column(DateTime, nullable=False, default=datetime.datetime.now, index=True)
completed_at = Column(DateTime)
elapsed_time = Column(Float, comment="耗时(秒)")
token_usage = Column(JSON, comment="Token 使用情况")
# 元数据
meta_data = Column(JSON, comment="额外元数据")
created_at = Column(DateTime, default=datetime.datetime.now)
# 关系
caller = relationship("AgentConfig", foreign_keys=[caller_agent_id])
callee = relationship("AgentConfig", foreign_keys=[callee_agent_id])

View File

@@ -9,8 +9,9 @@
"""
import datetime
import uuid
from typing import Optional, List, Dict, Any, Tuple
from typing import Optional, List, Dict, Any, Tuple, Annotated
from fastapi import Depends
from sqlalchemy import select, func, or_, and_
from sqlalchemy.orm import Session
@@ -20,6 +21,7 @@ from app.core.exceptions import (
BusinessException,
)
from app.core.logging_config import get_business_logger
from app.db import get_db
from app.models import App, AgentConfig, AppRelease, MultiAgentConfig, WorkflowConfig
from app.models.app_model import AppStatus, AppType
from app.repositories.app_repository import get_apps_by_id
@@ -1407,7 +1409,7 @@ class AppService:
ResourceNotFoundException: 当应用不存在时
BusinessException: 当应用不在指定工作空间或目标工作空间无效时
"""
logger.info(
"分享应用",
@@ -2095,3 +2097,14 @@ async def draft_run_stream(
workspace_id=workspace_id
):
yield event
# ==================== 依赖注入函数 ====================
def get_app_service(
db: Annotated[Session, Depends(get_db)]
) -> AppService:
"""获取工作流服务(依赖注入)"""
return AppService(db)