fix(workflow): add reasoning content, suggested questions, citations and audio status support

- Introduce `reasoning_content`, `suggested_questions`, `citations`, and `audio_status` fields in conversation and app response schemas
- Conditionally set `audio_status` to `"pending"` only when `audio_url` is present
- Replace `model_dump` override with `@model_serializer(mode="wrap")` for cleaner serialization logic
- Change knowledge base validation failure from `RuntimeError` to warning + `continue` to avoid halting retrieval on invalid KB
This commit is contained in:
Timebomb2018
2026-04-27 15:35:26 +08:00
parent a268d0f7f1
commit faf8d1a51a
5 changed files with 22 additions and 7 deletions

View File

@@ -334,7 +334,8 @@ class KnowledgeRetrievalNode(BaseNode):
for kb_config in knowledge_bases: for kb_config in knowledge_bases:
db_knowledge = knowledge_repository.get_knowledge_by_id(db=db, knowledge_id=kb_config.kb_id) db_knowledge = knowledge_repository.get_knowledge_by_id(db=db, knowledge_id=kb_config.kb_id)
if not (db_knowledge and db_knowledge.chunk_num > 0 and db_knowledge.status == 1): if not (db_knowledge and db_knowledge.chunk_num > 0 and db_knowledge.status == 1):
raise RuntimeError("The knowledge base does not exist or access is denied.") logger.warning("The knowledge base does not exist or access is denied.")
continue
tasks.append(self.knowledge_retrieval(db, query, db_knowledge, kb_config)) tasks.append(self.knowledge_retrieval(db, query, db_knowledge, kb_config))
if tasks: if tasks:
result = await asyncio.gather(*tasks) result = await asyncio.gather(*tasks)

View File

@@ -3,7 +3,7 @@ import uuid
from typing import Optional, Any, List, Dict, Union from typing import Optional, Any, List, Dict, Union
from enum import Enum, StrEnum 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 from app.schemas.workflow_schema import WorkflowConfigCreate
@@ -661,9 +661,11 @@ class DraftRunResponse(BaseModel):
suggested_questions: List[str] = Field(default_factory=list, description="下一步建议问题") suggested_questions: List[str] = Field(default_factory=list, description="下一步建议问题")
citations: List[Dict[str, Any]] = 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_url: Optional[str] = Field(default=None, description="TTS 语音URL")
audio_status: Optional[str] = Field(default=None, description="TTS 语音状态")
def model_dump(self, **kwargs): @model_serializer(mode="wrap")
data = super().model_dump(**kwargs) def _serialize(self, handler):
data = handler(self)
if not data.get("reasoning_content"): if not data.get("reasoning_content"):
data.pop("reasoning_content", None) data.pop("reasoning_content", None)
return data return data

View File

@@ -2,7 +2,7 @@
import uuid import uuid
import datetime import datetime
from typing import Optional, Dict, Any, List 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用于体验运行 # 导入 FileInput用于体验运行
from app.schemas.app_schema import FileInput from app.schemas.app_schema import FileInput
@@ -94,6 +94,18 @@ class ChatResponse(BaseModel):
message_id: str message_id: str
usage: Optional[Dict[str, Any]] = None usage: Optional[Dict[str, Any]] = None
elapsed_time: Optional[float] = None elapsed_time: Optional[float] = None
reasoning_content: Optional[str] = None
suggested_questions: Optional[List[str]] = None
citations: Optional[List[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 ---------- # ---------- Conversation Summary Schemas ----------

View File

@@ -317,7 +317,7 @@ class AppChatService:
"suggested_questions": suggested_questions, "suggested_questions": suggested_questions,
"citations": filtered_citations, "citations": filtered_citations,
"audio_url": audio_url, "audio_url": audio_url,
"audio_status": "pending" "audio_status": "pending" if audio_url else None
} }
async def agnet_chat_stream( async def agnet_chat_stream(

View File

@@ -754,7 +754,7 @@ class AgentRunService:
) if not sub_agent else [], ) if not sub_agent else [],
"citations": filtered_citations, "citations": filtered_citations,
"audio_url": audio_url, "audio_url": audio_url,
"audio_status": "pending" "audio_status": "pending" if audio_url else None
} }
logger.info( logger.info(