fix: 更新聊天代理处理逻辑,增强敏感内容检测和中断提示
- 在 chat_agent 函数中,优化了敏感内容检测后的响应,添加了时间成本的记录。 - 修改了前端 AgentChatComponent 和 AgentMessageComponent,以正确处理和显示敏感内容中断的提示信息。 - 移除了不必要的代码注释和冗余逻辑,提升了代码可读性。
This commit is contained in:
parent
685f48272b
commit
214bcb8d3e
@ -375,7 +375,6 @@ async def get_agent(current_user: User = Depends(get_required_user)):
|
|||||||
return {"agents": agents}
|
return {"agents": agents}
|
||||||
|
|
||||||
|
|
||||||
# TODO:[未完成]这个thread_id在前端是直接生成的1234,最好传入thread_id时做校验只允许uuid4
|
|
||||||
@chat.post("/agent/{agent_id}")
|
@chat.post("/agent/{agent_id}")
|
||||||
async def chat_agent(
|
async def chat_agent(
|
||||||
agent_id: str,
|
agent_id: str,
|
||||||
@ -472,7 +471,8 @@ async def chat_agent(
|
|||||||
if conf.enable_content_guard and await content_guard.check_with_keywords(full_msg.content[-20:]):
|
if conf.enable_content_guard and await content_guard.check_with_keywords(full_msg.content[-20:]):
|
||||||
logger.warning("Sensitive content detected in stream")
|
logger.warning("Sensitive content detected in stream")
|
||||||
await save_partial_message(conv_manager, thread_id, full_msg, "content_guard_blocked")
|
await save_partial_message(conv_manager, thread_id, full_msg, "content_guard_blocked")
|
||||||
yield make_chunk(message="检测到敏感内容,已中断输出", status="error")
|
meta["time_cost"] = asyncio.get_event_loop().time() - start_time
|
||||||
|
yield make_chunk(status="interrupted", message="检测到敏感内容,已中断输出", meta=meta)
|
||||||
return
|
return
|
||||||
|
|
||||||
yield make_chunk(content=msg.content, msg=msg.model_dump(), metadata=metadata, status="loading")
|
yield make_chunk(content=msg.content, msg=msg.model_dump(), metadata=metadata, status="loading")
|
||||||
@ -487,7 +487,8 @@ async def chat_agent(
|
|||||||
):
|
):
|
||||||
logger.warning("Sensitive content detected in final message")
|
logger.warning("Sensitive content detected in final message")
|
||||||
await save_partial_message(conv_manager, thread_id, full_msg, "content_guard_blocked")
|
await save_partial_message(conv_manager, thread_id, full_msg, "content_guard_blocked")
|
||||||
yield make_chunk(message="检测到敏感内容,已中断输出", status="error")
|
meta["time_cost"] = asyncio.get_event_loop().time() - start_time
|
||||||
|
yield make_chunk(status="interrupted", message="检测到敏感内容,已中断输出", meta=meta)
|
||||||
return
|
return
|
||||||
|
|
||||||
# After streaming finished, check for interrupts and save messages
|
# After streaming finished, check for interrupts and save messages
|
||||||
@ -512,16 +513,6 @@ async def chat_agent(
|
|||||||
# 客户端主动中断连接,检查中断并保存已生成的部分内容
|
# 客户端主动中断连接,检查中断并保存已生成的部分内容
|
||||||
logger.warning(f"Client disconnected, cancelling stream: {e}")
|
logger.warning(f"Client disconnected, cancelling stream: {e}")
|
||||||
|
|
||||||
# 断开连接时不检查中断,直接保存部分消息
|
|
||||||
langgraph_config = {"configurable": input_context}
|
|
||||||
|
|
||||||
# 尝试从 LangGraph state 保存消息(可能没有,因为中断了)
|
|
||||||
await save_messages_from_langgraph_state(
|
|
||||||
agent_instance=agent,
|
|
||||||
thread_id=thread_id,
|
|
||||||
conv_mgr=conv_manager,
|
|
||||||
config_dict=langgraph_config,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 如果有手动维护的 full_msg,直接保存到数据库
|
# 如果有手动维护的 full_msg,直接保存到数据库
|
||||||
if full_msg:
|
if full_msg:
|
||||||
@ -539,16 +530,6 @@ async def chat_agent(
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error streaming messages: {e}, {traceback.format_exc()}")
|
logger.error(f"Error streaming messages: {e}, {traceback.format_exc()}")
|
||||||
|
|
||||||
# 异常情况下也不检查中断,直接保存部分消息
|
|
||||||
langgraph_config = {"configurable": input_context}
|
|
||||||
|
|
||||||
# 尝试从 LangGraph state 保存消息(可能没有,因为异常了)
|
|
||||||
await save_messages_from_langgraph_state(
|
|
||||||
agent_instance=agent,
|
|
||||||
thread_id=thread_id,
|
|
||||||
conv_mgr=conv_manager,
|
|
||||||
config_dict=langgraph_config,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 如果有手动维护的 full_msg,直接保存到数据库
|
# 如果有手动维护的 full_msg,直接保存到数据库
|
||||||
if full_msg:
|
if full_msg:
|
||||||
|
|||||||
@ -64,7 +64,7 @@ class AttachmentMiddleware(AgentMiddleware[AttachmentState]):
|
|||||||
self, request: ModelRequest, handler: Callable[[ModelRequest], ModelResponse]
|
self, request: ModelRequest, handler: Callable[[ModelRequest], ModelResponse]
|
||||||
) -> ModelResponse:
|
) -> ModelResponse:
|
||||||
# Read from State: get uploaded files metadata
|
# Read from State: get uploaded files metadata
|
||||||
logger.debug(f"inject_attachment_context: request.state = {request.state}")
|
# logger.debug(f"inject_attachment_context: request.state = {request.state}")
|
||||||
attachments = request.state.get("attachments", [])
|
attachments = request.state.get("attachments", [])
|
||||||
|
|
||||||
if attachments:
|
if attachments:
|
||||||
|
|||||||
@ -470,7 +470,7 @@ const resetOnGoingConv = (threadId = null, preserveMessages = false) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const _processStreamChunk = (chunk, threadId) => {
|
const _processStreamChunk = (chunk, threadId) => {
|
||||||
const { status, msg, request_id, message } = chunk;
|
const { status, msg, request_id, message: chunkMessage } = chunk;
|
||||||
const threadState = getThreadState(threadId);
|
const threadState = getThreadState(threadId);
|
||||||
// console.log('Processing stream chunk:', chunk, 'for thread:', threadId);
|
// console.log('Processing stream chunk:', chunk, 'for thread:', threadId);
|
||||||
|
|
||||||
@ -489,7 +489,7 @@ const _processStreamChunk = (chunk, threadId) => {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case 'error':
|
case 'error':
|
||||||
handleChatError({ message }, 'stream');
|
handleChatError({ message: chunkMessage }, 'stream');
|
||||||
// Stop the loading indicator
|
// Stop the loading indicator
|
||||||
if (threadState) {
|
if (threadState) {
|
||||||
threadState.isStreaming = false;
|
threadState.isStreaming = false;
|
||||||
@ -525,6 +525,10 @@ const _processStreamChunk = (chunk, threadId) => {
|
|||||||
if (threadState) {
|
if (threadState) {
|
||||||
threadState.isStreaming = false;
|
threadState.isStreaming = false;
|
||||||
}
|
}
|
||||||
|
// 如果有 message 字段,显示提示(例如:敏感内容检测)
|
||||||
|
if (chunkMessage) {
|
||||||
|
message.info(chunkMessage);
|
||||||
|
}
|
||||||
fetchThreadMessages({ agentId: currentAgentId.value, threadId: threadId })
|
fetchThreadMessages({ agentId: currentAgentId.value, threadId: threadId })
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
resetOnGoingConv(threadId, true);
|
resetOnGoingConv(threadId, true);
|
||||||
|
|||||||
@ -30,9 +30,10 @@
|
|||||||
<div v-else-if="parsedData.reasoning_content" class="empty-block"></div>
|
<div v-else-if="parsedData.reasoning_content" class="empty-block"></div>
|
||||||
|
|
||||||
<!-- 错误提示块 -->
|
<!-- 错误提示块 -->
|
||||||
<div v-if="message.error_type" class="error-hint" :class="{ 'error-interrupted': message.error_type === 'interrupted', 'error-unexpect': message.error_type === 'unexpect' }">
|
<div v-if="message.error_type" class="error-hint">
|
||||||
<span v-if="message.error_type === 'interrupted'">回答生成已中断</span>
|
<span v-if="message.error_type === 'interrupted'">回答生成已中断</span>
|
||||||
<span v-else-if="message.error_type === 'unexpect'">生成过程中出现异常</span>
|
<span v-else-if="message.error_type === 'unexpect'">生成过程中出现异常</span>
|
||||||
|
<span v-else-if="message.error_type === 'content_guard_blocked'">检测到敏感内容,已中断输出</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="validToolCalls && validToolCalls.length > 0" class="tool-calls-container">
|
<div v-if="validToolCalls && validToolCalls.length > 0" class="tool-calls-container">
|
||||||
@ -365,19 +366,9 @@ const toggleToolCall = (toolCallId) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
|
||||||
&.error-interrupted {
|
|
||||||
background-color: #fffbeb;
|
|
||||||
// border: 1px solid #fbbf24;
|
|
||||||
color: #92400e;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.error-unexpect {
|
|
||||||
background-color: #fef2f2;
|
background-color: #fef2f2;
|
||||||
// border: 1px solid #f87171;
|
// border: 1px solid #f87171;
|
||||||
color: #991b1b;
|
color: #991b1b;
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
span {
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user