Merge branch 'develop' into feature/multimodel_memory

# Conflicts:
#	api/app/core/memory/storage_services/extraction_engine/knowledge_extraction/embedding_generation.py
#	api/app/repositories/neo4j/add_nodes.py
#	api/app/repositories/neo4j/cypher_queries.py
#	api/app/repositories/neo4j/graph_saver.py
#	api/app/services/memory_agent_service.py
#	api/app/services/multimodal_service.py
This commit is contained in:
Eternity
2026-03-24 14:15:18 +08:00
61 changed files with 1707 additions and 694 deletions

View File

@@ -0,0 +1,53 @@
"""应用日志消息记录Schema"""
import uuid
import datetime
from typing import Optional, Dict, Any, List
from pydantic import BaseModel, Field, ConfigDict, field_serializer
class AppLogMessage(BaseModel):
"""单条消息记录"""
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
conversation_id: uuid.UUID
role: str = Field(description="角色: user / assistant / system")
content: str
meta_data: Optional[Dict[str, Any]] = None
created_at: datetime.datetime
@field_serializer("created_at", when_used="json")
def _serialize_created_at(self, dt: datetime.datetime):
return int(dt.timestamp() * 1000) if dt else None
@field_serializer("meta_data", when_used="json")
def _serialize_meta_data(self, data: Optional[Dict[str, Any]]):
return data or {}
class AppLogConversation(BaseModel):
"""会话摘要(用于列表)"""
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
app_id: uuid.UUID
user_id: Optional[str] = None
title: Optional[str] = None
message_count: int = 0
is_draft: bool
created_at: datetime.datetime
updated_at: datetime.datetime
@field_serializer("created_at", when_used="json")
def _serialize_created_at(self, dt: datetime.datetime):
return int(dt.timestamp() * 1000) if dt else None
@field_serializer("updated_at", when_used="json")
def _serialize_updated_at(self, dt: datetime.datetime):
return int(dt.timestamp() * 1000) if dt else None
class AppLogConversationDetail(AppLogConversation):
"""会话详情(包含消息列表)"""
messages: List[AppLogMessage] = Field(default_factory=list)

View File

@@ -149,18 +149,26 @@ class FileUploadConfig(BaseModel):
)
# 通用文件PDF/DOCX/XLSX/TXT/CSV/JSON最大 100MB
document_enabled: bool = Field(default=False)
document_max_size_mb: int = Field(default=100)
document_max_size_mb: int = Field(default=50)
document_allowed_extensions: List[str] = Field(
default=["pdf", "docx", "xlsx", "txt", "csv", "json", "md"]
default=["pdf", "docx", "doc", "xlsx", "xls", "txt", "csv", "json", "md"]
)
# 视频文件MP4/MOV/AVI/WebM最大 500MB
video_enabled: bool = Field(default=False)
video_max_size_mb: int = Field(default=500)
video_max_size_mb: int = Field(default=50)
video_allowed_extensions: List[str] = Field(
default=["mp4", "mov"]
default=["mp4"]
)
# 最大文件数量
max_file_count: int = Field(default=5, ge=1, le=20)
max_file_count: int = Field(default=5, ge=1)
@field_validator("max_file_count")
@classmethod
def validate_max_file_count(cls, v: int) -> int:
from app.core.config import settings
if v > settings.MAX_FILE_COUNT:
raise ValueError(f"max_file_count 不能超过 {settings.MAX_FILE_COUNT}")
return v
class OpeningStatementConfig(BaseModel):