Feature/memory work (#61)

* refactor(conversation): separate service and repository layers for conversation module

- Split ConversationService and repository/UnitOfWork layers
- Service layer now only handles business logic and orchestration
- Repository layer handles all direct database operations
- UnitOfWork encapsulates transactional operations for messages
- Ensured all public methods have clear English docstrings with arguments, return values, and exceptions

* feat(memory): implement work memory endpoints and services

- Added API routes for conversation count, conversation list, messages, and detail.
- Integrated ConversationService for database queries and LLM-based summary generation.

* feat(memory): implement work memory endpoints and services

- Added API routes for conversation count, conversation list, messages, and detail.
- Integrated ConversationService for database queries and LLM-based summary generation.

* feat(workflow): fix issues causing workflow failures

if-else None value error
knowledge empty list rerank
end node output none node value
assigner input none value

* feat(memory): convert memory file creation time to timestamp and include title and first-line fields in file type

* fix(memory): fix serialization output and default value issues

* fix(workflow): fix issue with hybrid search logic in knowledge retrieval node
This commit is contained in:
Eternity
2026-01-08 18:48:29 +08:00
committed by GitHub
parent 009ceefa30
commit c5dd09cf50
23 changed files with 1050 additions and 203 deletions

View File

@@ -35,14 +35,14 @@ class ChatRequest(BaseModel):
class Message(BaseModel):
"""消息输出"""
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
conversation_id: uuid.UUID
role: str
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
@@ -51,7 +51,7 @@ class Message(BaseModel):
class Conversation(BaseModel):
"""会话输出"""
model_config = ConfigDict(from_attributes=True)
id: uuid.UUID
app_id: uuid.UUID
workspace_id: uuid.UUID
@@ -63,11 +63,11 @@ class Conversation(BaseModel):
is_active: 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
@@ -84,3 +84,12 @@ class ChatResponse(BaseModel):
message: str
usage: Optional[Dict[str, Any]] = None
elapsed_time: Optional[float] = None
# ---------- Conversation Summary Schemas ----------
class ConversationOut(BaseModel):
theme: str
theme_intro: str
summary: str
takeaways: list[str]
info_score: int

View File

@@ -39,10 +39,11 @@ class PerceptualMemoryItem(BaseModel):
id: uuid.UUID = Field(..., description="Unique memory ID")
perceptual_type: PerceptualType = Field(..., description="Type of perception, e.g., text, audio, or video")
file_path: str = Field(..., description="File path in the storage service")
file_ext: str = Field(..., description="File extension")
file_name: str = Field(..., description="File name")
summary: Optional[str] = Field(None, description="摘要")
summary: Optional[str] = Field(None, description="summary")
storage_type: FileStorageType = Field(..., description="Storage type for file")
created_time: Optional[datetime] = Field(None, description="创建时间")
created_time: int = Field(..., description="create time")
class Config:
from_attributes = True
@@ -114,6 +115,8 @@ class AudioModal(BaseModel):
class TextModal(BaseModel):
section_count: int
title: str
first_line: str
class Asset(BaseModel):