Merge branch 'release/v0.3.2' into feature/rag2
* release/v0.3.2: (245 commits) fix(conversation_schema): refine citations field type to Dict[str, Any] fix(tool_controller): re-raise HTTPException to preserve original status codes fix(workflow): add reasoning content, suggested questions, citations and audio status support feat(workflow): augment logging queries and ameliorate error handling fix(api_key): bypass publication check for SERVICE type API keys fix(multimodal_service): add '文档内容:' prefix to document text and simplify image placeholder text fix(api): convert config_id to string in write_router fix(api): convert end_user_id to string in write_router fix(multimodal_service): refactor image processing to use intermediate list before extending result fix(web): node status ui fix(api): correct import paths in memory_read and celery task command fix(api): correct import paths in memory_read and celery task command refactor(tool): flatten request body parameters for model exposure fix(api): correct import paths in memory_read and celery task command refactor(workflow): streamline node execution handling and log service logic feat(web): http request add process feat(web): workflow app logs fix(app_chat_service,draft_run_service): move system_prompt augmentation before LangChainAgent instantiation fix(app_chat_service,draft_run_service): move system_prompt augmentation before LangChainAgent instantiation refactor(http_request): simplify request handling and remove unused fields ... # Conflicts: # api/app/controllers/file_controller.py # api/app/tasks.py
This commit is contained in:
@@ -15,8 +15,8 @@ class ApiKeyCreate(BaseModel):
|
||||
type: ApiKeyType = Field(..., description="API Key 类型")
|
||||
scopes: List[str] = Field(default_factory=list, description="权限范围列表")
|
||||
resource_id: Optional[uuid.UUID] = Field(None, description="关联资源ID")
|
||||
rate_limit: Optional[int] = Field(100, ge=1, le=1000, description="QPS限制(请求/秒)")
|
||||
daily_request_limit: Optional[int] = Field(10000, description="日请求限制", ge=1)
|
||||
rate_limit: Optional[int] = Field(50, ge=1, le=1000, description="QPS限制(请求/秒)")
|
||||
daily_request_limit: Optional[int] = Field(100000, description="日请求限制", ge=1)
|
||||
quota_limit: Optional[int] = Field(None, description="配额限制(总请求数)", ge=1)
|
||||
expires_at: Optional[datetime.datetime] = Field(None, description="过期时间")
|
||||
|
||||
@@ -55,7 +55,7 @@ class ApiKeyUpdate(BaseModel):
|
||||
description: Optional[str] = Field(None, description="描述")
|
||||
scopes: Optional[List[str]] = Field(None, description="权限范围列表")
|
||||
rate_limit: Optional[int] = Field(None, description="速率限制(请求/分钟)", ge=1)
|
||||
daily_request_limit: Optional[int] = Field(10000, description="每日请求数限制", ge=1)
|
||||
daily_request_limit: Optional[int] = Field(100000, description="每日请求数限制", ge=1)
|
||||
quota_limit: Optional[int] = Field(None, description="配额限制(总请求数)", ge=1)
|
||||
is_active: Optional[bool] = Field(None, description="是否激活")
|
||||
expires_at: Optional[datetime.datetime] = Field(None, description="过期时间")
|
||||
|
||||
@@ -14,6 +14,7 @@ class AppLogMessage(BaseModel):
|
||||
conversation_id: uuid.UUID
|
||||
role: str = Field(description="角色: user / assistant / system")
|
||||
content: str
|
||||
status: Optional[str] = Field(default=None, description="执行状态(工作流专用): completed / failed")
|
||||
meta_data: Optional[Dict[str, Any]] = None
|
||||
created_at: datetime.datetime
|
||||
|
||||
@@ -48,6 +49,22 @@ class AppLogConversation(BaseModel):
|
||||
return int(dt.timestamp() * 1000) if dt else None
|
||||
|
||||
|
||||
class AppLogNodeExecution(BaseModel):
|
||||
"""工作流节点执行记录"""
|
||||
node_id: str
|
||||
node_type: str
|
||||
node_name: Optional[str] = None
|
||||
status: str = "pending"
|
||||
error: Optional[str] = None
|
||||
input: Optional[Any] = None
|
||||
process: Optional[Any] = None
|
||||
output: Optional[Any] = None
|
||||
cycle_items: Optional[List[Any]] = None
|
||||
elapsed_time: Optional[float] = None
|
||||
token_usage: Optional[Dict[str, Any]] = None
|
||||
|
||||
|
||||
class AppLogConversationDetail(AppLogConversation):
|
||||
"""会话详情(包含消息列表)"""
|
||||
messages: List[AppLogMessage] = Field(default_factory=list)
|
||||
node_executions_map: Dict[str, List[AppLogNodeExecution]] = Field(default_factory=dict, description="按消息ID分组的节点执行记录")
|
||||
|
||||
@@ -3,7 +3,7 @@ import uuid
|
||||
from typing import Optional, Any, List, Dict, Union
|
||||
from enum import Enum, StrEnum
|
||||
|
||||
from pydantic import BaseModel, Field, ConfigDict, field_serializer, field_validator
|
||||
from pydantic import BaseModel, Field, ConfigDict, field_serializer, field_validator, model_serializer
|
||||
|
||||
from app.schemas.workflow_schema import WorkflowConfigCreate
|
||||
|
||||
@@ -44,6 +44,8 @@ class FileInput(BaseModel):
|
||||
upload_file_id: Optional[uuid.UUID] = Field(None, description="已上传文件ID(local_file时必填)")
|
||||
url: Optional[str] = Field(None, description="远程URL(remote_url时必填)")
|
||||
file_type: Optional[str] = Field(None, description="具体文件格式(如image/jpg、audio/wav、document/docx、video/mp4)")
|
||||
name: Optional[str] = Field(None, description="文件名")
|
||||
size: Optional[int] = Field(None, description="文件大小(字节)")
|
||||
|
||||
_content = None
|
||||
|
||||
@@ -153,6 +155,10 @@ class FileUploadConfig(BaseModel):
|
||||
document_allowed_extensions: List[str] = Field(
|
||||
default=["pdf", "docx", "doc", "xlsx", "xls", "txt", "csv", "json", "md"]
|
||||
)
|
||||
document_image_recognition: bool = Field(
|
||||
default=False,
|
||||
description="是否识别文档中的图片(需配置视觉模型)"
|
||||
)
|
||||
# 视频文件:MP4/MOV/AVI/WebM,最大 500MB
|
||||
video_enabled: bool = Field(default=False)
|
||||
video_max_size_mb: int = Field(default=50)
|
||||
@@ -194,6 +200,7 @@ class TextToSpeechConfig(BaseModel):
|
||||
class CitationConfig(BaseModel):
|
||||
"""引用和归属配置"""
|
||||
enabled: bool = Field(default=False)
|
||||
allow_download: bool = Field(default=False, description="是否允许下载引用文档")
|
||||
|
||||
|
||||
class Citation(BaseModel):
|
||||
@@ -201,6 +208,7 @@ class Citation(BaseModel):
|
||||
file_name: str
|
||||
knowledge_id: str
|
||||
score: float
|
||||
download_url: Optional[str] = Field(default=None, description="引用文档下载链接(allow_download 开启时返回)")
|
||||
|
||||
|
||||
class WebSearchConfig(BaseModel):
|
||||
@@ -243,6 +251,7 @@ class ModelParameters(BaseModel):
|
||||
stop: Optional[List[str]] = Field(default=None, description="停止序列")
|
||||
deep_thinking: bool = Field(default=False, description="是否启用深度思考模式(需模型支持,如 DeepSeek-R1、QwQ 等)")
|
||||
thinking_budget_tokens: Optional[int] = Field(default=None, ge=1024, le=131072, description="深度思考 token 预算(仅部分模型支持)")
|
||||
json_output: bool = Field(default=False, description="是否强制 JSON 格式输出(需模型支持 json_output 能力)")
|
||||
|
||||
|
||||
class VariableDefinition(BaseModel):
|
||||
@@ -650,11 +659,13 @@ class DraftRunResponse(BaseModel):
|
||||
usage: Optional[Dict[str, Any]] = Field(default=None, description="Token 使用情况")
|
||||
elapsed_time: Optional[float] = Field(default=None, description="耗时(秒)")
|
||||
suggested_questions: List[str] = Field(default_factory=list, description="下一步建议问题")
|
||||
citations: List[CitationSource] = Field(default_factory=list, description="引用来源")
|
||||
citations: List[Dict[str, Any]] = Field(default_factory=list, description="引用来源")
|
||||
audio_url: Optional[str] = Field(default=None, description="TTS 语音URL")
|
||||
audio_status: Optional[str] = Field(default=None, description="TTS 语音状态")
|
||||
|
||||
def model_dump(self, **kwargs):
|
||||
data = super().model_dump(**kwargs)
|
||||
@model_serializer(mode="wrap")
|
||||
def _serialize(self, handler):
|
||||
data = handler(self)
|
||||
if not data.get("reasoning_content"):
|
||||
data.pop("reasoning_content", None)
|
||||
return data
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import uuid
|
||||
import datetime
|
||||
from typing import Optional, Dict, Any, List
|
||||
from pydantic import BaseModel, Field, ConfigDict, field_serializer
|
||||
from pydantic import BaseModel, Field, ConfigDict, field_serializer, model_serializer
|
||||
|
||||
# 导入 FileInput(用于体验运行)
|
||||
from app.schemas.app_schema import FileInput
|
||||
@@ -94,6 +94,18 @@ class ChatResponse(BaseModel):
|
||||
message_id: str
|
||||
usage: Optional[Dict[str, Any]] = None
|
||||
elapsed_time: Optional[float] = None
|
||||
reasoning_content: Optional[str] = None
|
||||
suggested_questions: Optional[List[str]] = None
|
||||
citations: Optional[List[Dict[str, Any]]] = None
|
||||
audio_url: Optional[str] = None
|
||||
audio_status: Optional[str] = None
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def _serialize(self, handler):
|
||||
data = handler(self)
|
||||
if not data.get("reasoning_content"):
|
||||
data.pop("reasoning_content", None)
|
||||
return data
|
||||
|
||||
|
||||
# ---------- Conversation Summary Schemas ----------
|
||||
|
||||
@@ -4,9 +4,10 @@ This module defines Pydantic schemas for the Memory API Service endpoints,
|
||||
including request validation and response structures for read and write operations.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, List, Optional
|
||||
from typing import Any, Dict, List, Literal, Optional
|
||||
import uuid
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
|
||||
class MemoryWriteRequest(BaseModel):
|
||||
@@ -110,6 +111,30 @@ class MemoryReadRequest(BaseModel):
|
||||
class MemoryWriteResponse(BaseModel):
|
||||
"""Response schema for memory write operation.
|
||||
|
||||
Attributes:
|
||||
task_id: task ID for status polling
|
||||
status: Initial task status (QUEUED)
|
||||
end_user_id: End user ID the write was submitted for
|
||||
"""
|
||||
task_id: str = Field(..., description="task ID for polling")
|
||||
status: str = Field(..., description="Task status: QUEUED")
|
||||
end_user_id: str = Field(..., description="End user ID")
|
||||
|
||||
|
||||
class TaskStatusResponse(BaseModel):
|
||||
"""Response schema for task status check.
|
||||
|
||||
Attributes:
|
||||
status: Task status (PENDING, STARTED, SUCCESS, FAILURE, SKIPPED)
|
||||
result: Task result data (available when status is SUCCESS or FAILURE)
|
||||
"""
|
||||
status: str = Field(..., description="Task status")
|
||||
result: Optional[Dict[str, Any]] = Field(None, description="Task result when completed")
|
||||
|
||||
|
||||
class MemoryWriteSyncResponse(BaseModel):
|
||||
"""Response schema for synchronous memory write.
|
||||
|
||||
Attributes:
|
||||
status: Operation status (success or failed)
|
||||
end_user_id: End user ID that was written to
|
||||
@@ -118,8 +143,8 @@ class MemoryWriteResponse(BaseModel):
|
||||
end_user_id: str = Field(..., description="End user ID")
|
||||
|
||||
|
||||
class MemoryReadResponse(BaseModel):
|
||||
"""Response schema for memory read operation.
|
||||
class MemoryReadSyncResponse(BaseModel):
|
||||
"""Response schema for synchronous memory read.
|
||||
|
||||
Attributes:
|
||||
answer: Generated answer from memory retrieval
|
||||
@@ -128,12 +153,25 @@ class MemoryReadResponse(BaseModel):
|
||||
"""
|
||||
answer: str = Field(..., description="Generated answer")
|
||||
intermediate_outputs: List[Dict[str, Any]] = Field(
|
||||
default_factory=list,
|
||||
default_factory=list,
|
||||
description="Intermediate retrieval outputs"
|
||||
)
|
||||
end_user_id: str = Field(..., description="End user ID")
|
||||
|
||||
|
||||
class MemoryReadResponse(BaseModel):
|
||||
"""Response schema for memory read operation.
|
||||
|
||||
Attributes:
|
||||
task_id: Celery task ID for status polling
|
||||
status: Initial task status (PENDING)
|
||||
end_user_id: End user ID the read was submitted for
|
||||
"""
|
||||
task_id: str = Field(..., description="Celery task ID for polling")
|
||||
status: str = Field(..., description="Task status: PENDING")
|
||||
end_user_id: str = Field(..., description="End user ID")
|
||||
|
||||
|
||||
class CreateEndUserRequest(BaseModel):
|
||||
"""Request schema for creating an end user.
|
||||
|
||||
@@ -141,10 +179,12 @@ class CreateEndUserRequest(BaseModel):
|
||||
other_id: External user identifier (required)
|
||||
other_name: Display name for the end user
|
||||
memory_config_id: Optional memory config ID. If not provided, uses workspace default.
|
||||
app_id: Optional app ID to bind the end user to.
|
||||
"""
|
||||
other_id: str = Field(..., description="External user identifier (required)")
|
||||
other_name: Optional[str] = Field("", description="Display name")
|
||||
memory_config_id: Optional[str] = Field(None, description="Memory config ID. Falls back to workspace default if not provided.")
|
||||
app_id: Optional[str] = Field(None, description="App ID to bind the end user to")
|
||||
|
||||
@field_validator("other_id")
|
||||
@classmethod
|
||||
@@ -192,6 +232,7 @@ class MemoryConfigItem(BaseModel):
|
||||
created_at: Optional[str] = Field(None, description="Creation timestamp")
|
||||
updated_at: Optional[str] = Field(None, description="Last update timestamp")
|
||||
|
||||
# ========== V1 记忆配置管理接口 Schema ==========
|
||||
|
||||
class ListConfigsResponse(BaseModel):
|
||||
"""Response schema for listing memory configs.
|
||||
@@ -202,3 +243,203 @@ class ListConfigsResponse(BaseModel):
|
||||
"""
|
||||
configs: List[MemoryConfigItem] = Field(default_factory=list, description="List of configs")
|
||||
total: int = Field(0, description="Total number of configs")
|
||||
|
||||
class ConfigCreateRequest(BaseModel):
|
||||
"""Request schema for creating a new memory config."""
|
||||
config_name: str = Field(..., description="Configuration name")
|
||||
config_desc: Optional[str] = Field("", description="Configuration description")
|
||||
scene_id: uuid.UUID = Field(..., description="Associated ontology scene ID (UUID, required)")
|
||||
|
||||
llm_id: Optional[str] = Field(None, description="LLM model configuration ID")
|
||||
embedding_id: Optional[str] = Field(None, description="Embedding model configuration ID")
|
||||
rerank_id: Optional[str] = Field(None, description="Reranking model configuration ID")
|
||||
reflection_model_id: Optional[str] = Field(None, description="Reflection model ID")
|
||||
emotion_model_id: Optional[str] = Field(None, description="Emotion analysis model ID")
|
||||
|
||||
@field_validator("config_name")
|
||||
@classmethod
|
||||
def validate_config_name(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_name is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
class ConfigUpdateRequest(BaseModel):
|
||||
"""Request schema for updating memory config basic info.
|
||||
|
||||
Attributes:
|
||||
config_id: Configuration UUID to update (required)
|
||||
config_name: New configuration name
|
||||
config_desc: New configuration description
|
||||
scene_id: New associated ontology scene ID
|
||||
"""
|
||||
config_id: str = Field(..., description="Configuration ID to update")
|
||||
config_name: Optional[str] = Field(None, description="Configuration name")
|
||||
config_desc: Optional[str] = Field(None, description="Configuration description")
|
||||
scene_id: Optional[uuid.UUID] = Field(None, description="Associated ontology scene ID")
|
||||
|
||||
@field_validator("config_id")
|
||||
@classmethod
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
"""Validate that config_id is not empty."""
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
class ConfigUpdateExtractedRequest(BaseModel):
|
||||
"""Request schema for updating memory config extracted parameters.
|
||||
|
||||
Attributes:
|
||||
config_id: Configuration UUID to update (required)
|
||||
llm_id: Optional LLM model configuration ID
|
||||
audio_id: Optional audio model configuration ID
|
||||
vision_id: Optional vision model configuration ID
|
||||
video_id: Optional video model configuration ID
|
||||
embedding_id: Optional embedding model configuration ID
|
||||
rerank_id: Optional reranking model configuration ID
|
||||
enable_llm_dedup_blockwise: Optional toggle for LLM decision deduplication
|
||||
enable_llm_disambiguation: Optional toggle for LLM decision disambiguation
|
||||
deep_retrieval: Optional toggle for deep retrieval
|
||||
|
||||
t_type_strict: Optional float (0-1) for type strictness threshold
|
||||
t_name_strict: Optional float (0-1) for name strictness threshold
|
||||
t_overall: Optional float (0-1) for overall strictness threshold
|
||||
state: Optional boolean for config active state
|
||||
chunker_strategy: Optional string for memory chunking strategy
|
||||
statement_granularity: Optional int (1-3) for statement extraction granularity
|
||||
include_dialogue_context: Optional boolean for including dialogue context in retrieval
|
||||
max_context: Optional int for maximum dialogue context length in characters
|
||||
pruning_enabled: Optional boolean to enable intelligent semantic pruning
|
||||
pruning_scene: Optional string for semantic pruning scene
|
||||
pruning_threshold: Optional float (0-0.9) for semantic pruning threshold
|
||||
enable_self_reflexion: Optional boolean to enable self-reflexion
|
||||
iteration_period: Optional string for reflexion iteration period in hours (1, 3, 6, 12, 24)
|
||||
reflexion_range: Optional string for reflexion range (partial or all)
|
||||
baseline: Optional string for baseline (TIME/FACT/TIME-FACT)
|
||||
|
||||
"""
|
||||
config_id: str = Field(..., description="Configuration ID (UUID)")
|
||||
llm_id: Optional[str] = Field(None, description="LLM model configuration ID")
|
||||
audio_id: Optional[str] = Field(None, description="Audio model ID")
|
||||
vision_id: Optional[str] = Field(None, description="Vision model ID")
|
||||
video_id: Optional[str] = Field(None, description="Video model ID")
|
||||
embedding_id: Optional[str] = Field(None, description="Embedding model configuration ID")
|
||||
rerank_id: Optional[str] = Field(None, description="Reranking model configuration ID")
|
||||
enable_llm_dedup_blockwise: Optional[bool] = Field(None, description="Enable LLM decision deduplication")
|
||||
enable_llm_disambiguation: Optional[bool] = Field(None, description="Enable LLM decision disambiguation")
|
||||
deep_retrieval: Optional[bool] = Field(None, description="Deep retrieval toggle")
|
||||
|
||||
t_type_strict: Optional[float] = Field(None, ge=0.0, le=1.0, description="type strictness threshold")
|
||||
t_name_strict: Optional[float] = Field(None, ge=0.0, le=1.0, description="name strictness threshold")
|
||||
t_overall: Optional[float] = Field(None, ge=0.0, le=1.0, description="overall strictness threshold")
|
||||
state: Optional[bool] = Field(None, description="config active state")
|
||||
# 句子提取
|
||||
chunker_strategy: Optional[str] = Field(None, description="memory chunking strategy")
|
||||
statement_granularity: Optional[int] = Field(None, ge=1, le=3, description="statement extraction granularity")
|
||||
include_dialogue_context: Optional[bool] = Field(None, description="whether to include dialogue context in retrieval")
|
||||
max_context: Optional[int] = Field(None, gt=100, description="maximum dialogue context length in characters")
|
||||
# 剪枝配置:与 runtime.json 中 pruning 段对应
|
||||
pruning_enabled: Optional[bool] = Field(None, description="whether to enable intelligent semantic pruning")
|
||||
pruning_scene: Optional[str] = Field(None, description="semantic pruning scene")
|
||||
pruning_threshold: Optional[float] = Field(None, ge=0.0, le=0.9, description="semantic pruning threshold (0-0.9)")
|
||||
enable_self_reflexion: Optional[bool] = Field(None, description="whether to enable self-reflexion")
|
||||
iteration_period: Optional[Literal["1", "3", "6", "12", "24"]] = Field(None, description="reflexion iteration period in hours (1, 3, 6, 12, 24)")
|
||||
reflexion_range: Optional[Literal["partial", "all"]] = Field(None, description="reflexion range: partial/all")
|
||||
baseline: Optional[Literal["TIME", "FACT", "TIME-FACT"]] = Field(None, description="baseline: TIME/FACT/TIME-FACT")
|
||||
|
||||
@field_validator("config_id")
|
||||
@classmethod
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
class ConfigUpdateForgettingRequest(BaseModel):
|
||||
"""Request schema for updating memory config forgetting parameters.
|
||||
|
||||
Attributes:
|
||||
config_id: Configuration UUID to update (required)
|
||||
decay_constant: Decay constant for forgetting
|
||||
lambda_time: Time decay parameter
|
||||
lambda_mem: Memory decay parameter
|
||||
offset: Offset for forgetting curve
|
||||
max_history_length: Maximum history length to consider for forgetting
|
||||
forgetting_threshold: Threshold for forgetting
|
||||
min_days_since_access: Minimum days since last access to trigger forgetting
|
||||
enable_llm_summary: Whether to use LLM-generated summaries for forgetting
|
||||
max_merge_batch_size: Maximum batch size for merging nodes during forgetting
|
||||
forgetting_interval_hours: Interval in hours for periodic forgetting
|
||||
|
||||
"""
|
||||
model_config = ConfigDict(populate_by_name=True, extra="forbid")
|
||||
config_id: str = Field(..., description="Configuration ID (UUID)")
|
||||
decay_constant: Optional[float] = Field(None, ge=0.0, le=1.0, description="Decay constant for forgetting")
|
||||
lambda_time: Optional[float] = Field(None, ge=0.0, le=1.0, description="Time decay parameter")
|
||||
lambda_mem: Optional[float] = Field(None, ge=0.0, le=1.0, description="Memory decay parameter")
|
||||
offset: Optional[float] = Field(None, ge=0.0, le=1.0, description="Offset for forgetting curve")
|
||||
max_history_length: Optional[int] = Field(None, ge=10, le=1000, description="Maximum history length to consider for forgetting")
|
||||
forgetting_threshold: Optional[float] = Field(None, ge=0.0, le=1.0, description="Forgetting threshold")
|
||||
min_days_since_access: Optional[int] = Field(None, ge=1, le=365, description="Minimum days since last access to trigger forgetting")
|
||||
enable_llm_summary: Optional[bool] = Field(None, description="Whether to use LLM-generated summaries for forgetting")
|
||||
max_merge_batch_size: Optional[int] = Field(None, ge=1, le=1000, description="Maximum batch size for merging nodes during forgetting")
|
||||
forgetting_interval_hours: Optional[int] = Field(None, ge=1, le=168, description="Interval in hours for periodic forgetting")
|
||||
|
||||
@field_validator("config_id")
|
||||
@classmethod
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
class EmotionConfigUpdateRequest(BaseModel):
|
||||
"""Request schema for updating memory config emotion parameters.
|
||||
|
||||
Attributes:
|
||||
config_id: Configuration UUID to update (required)
|
||||
emotion_enabled: Whether to enable emotion extraction
|
||||
emotion_model_id: Emotion analysis model ID
|
||||
emotion_extract_keywords: Whether to extract emotion keywords
|
||||
emotion_min_intensity: Minimum emotion intensity threshold (0.0-1.0)
|
||||
emotion_enable_subject: Whether to enable subject classification for emotions
|
||||
"""
|
||||
config_id: str = Field(..., description="Configuration ID (UUID)")
|
||||
emotion_enabled: bool = Field(..., description="Whether to enable emotion extraction")
|
||||
emotion_model_id: Optional[str] = Field(None, description="Emotion analysis model ID")
|
||||
emotion_extract_keywords: bool = Field(..., description="Whether to extract emotion keywords")
|
||||
emotion_min_intensity: float = Field(..., ge=0.0, le=1.0, description="Minimum emotion intensity threshold")
|
||||
emotion_enable_subject: bool = Field(..., description="Whether to enable subject classification for emotions")
|
||||
|
||||
@field_validator("config_id")
|
||||
@classmethod
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
class ReflectionConfigUpdateRequest(BaseModel):
|
||||
"""Request schema for updating memory config reflection parameters.
|
||||
|
||||
Attributes:
|
||||
config_id: Configuration UUID to update (required)
|
||||
reflection_enabled: Whether to enable self-reflection
|
||||
reflection_period_in_hours: Reflection iteration period in hours
|
||||
reflexion_range: Reflection range (partial or all)
|
||||
baseline: Baseline for reflection (TIME/FACT/TIME-FACT)
|
||||
reflection_model_id: Reflection model ID
|
||||
memory_verify: Whether to enable memory verification
|
||||
quality_assessment: Whether to enable quality assessment
|
||||
"""
|
||||
config_id: str = Field(..., description="Configuration ID (UUID)")
|
||||
reflection_enabled: bool = Field(..., description="Whether to enable self-reflection")
|
||||
reflection_period_in_hours: str = Field(..., description="Reflection iteration period in hours")
|
||||
reflexion_range: Literal["partial", "all"] = Field(..., description="Reflection range: partial/all")
|
||||
baseline: Literal["TIME", "FACT", "TIME-FACT"] = Field(..., description="Baseline: TIME/FACT/TIME-FACT")
|
||||
reflection_model_id: str = Field(..., description="Reflection model ID")
|
||||
memory_verify: bool = Field(..., description="Whether to enable memory verification")
|
||||
quality_assessment: bool = Field(..., description="Whether to enable quality assessment")
|
||||
|
||||
@field_validator("config_id")
|
||||
@classmethod
|
||||
def validate_config_id(cls, v: str) -> str:
|
||||
if not v or not v.strip():
|
||||
raise ValueError("config_id is required and cannot be empty")
|
||||
return v.strip()
|
||||
|
||||
@@ -291,7 +291,7 @@ class ConfigUpdateExtracted(BaseModel): # 更新记忆萃取引擎配置参数
|
||||
pruning_threshold: Optional[float] = Field(
|
||||
None, ge=0.0, le=0.9, description="智能语义剪枝阈值(0-0.9)"
|
||||
)
|
||||
|
||||
#TODO:萃取引擎的更新的更新会带有反思引擎的参数,需判断业务是否需要,不需要可以重构
|
||||
# 反思配置
|
||||
enable_self_reflexion: Optional[bool] = Field(None, description="是否启用自我反思")
|
||||
iteration_period: Optional[Literal["1", "3", "6", "12", "24"]] = Field(
|
||||
|
||||
Reference in New Issue
Block a user