diff --git a/backend/gateway/platforms/deepview_sse.py b/backend/gateway/platforms/deepview_sse.py index 0aaf000..0f612a7 100644 --- a/backend/gateway/platforms/deepview_sse.py +++ b/backend/gateway/platforms/deepview_sse.py @@ -592,6 +592,9 @@ class DeepviewSSEServer: else: systemPrompt += f"\n\n## 通用模式\n企业知识库目录:{orgDir}/wiki/\n平台规则参考:{platformDir}/wiki/\n" + # 强调输出纪律,从源头杜绝输出底层 JSON 结构给前端 + systemPrompt += "\n\n【严格输出规范】\n严禁在最终回答中输出任何 JSON 结构、工具调用过程记录、文件读取错误等底层调试信息。你必须将系统结果和发现转化为专业、流畅的文档级 Markdown 给医生阅读!\n" + # 3. 加载上下文履历,实现真正的 Stateful Context history = db.get_messages_as_conversation(chatId) diff --git a/src/app/app.css b/src/app/app.css index 20f8dc4..34c1ee6 100644 --- a/src/app/app.css +++ b/src/app/app.css @@ -395,28 +395,44 @@ .chat-send-btn:disabled { background: #cbd5e1; color: #f1f5f9; } /* Markdown in Chat */ .markdown-body { - font-family: inherit; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; line-height: 1.6; + font-size: 15px; + color: #1e293b; + letter-spacing: 0.01em; } .markdown-body p { - margin-bottom: 8px; + margin-bottom: 12px; } .markdown-body p:last-child { margin-bottom: 0; } .markdown-body strong { font-weight: 700; + color: #0f172a; } .markdown-body ul, .markdown-body ol { - padding-left: 20px; - margin-bottom: 8px; + padding-left: 24px; + margin-bottom: 12px; + margin-top: 4px; +} +.markdown-body ul { + list-style-type: disc; +} +.markdown-body ol { + list-style-type: decimal; } .markdown-body li { - margin-bottom: 4px; + margin-bottom: 6px; + display: list-item; } .markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4 { - margin-top: 12px; - margin-bottom: 8px; + margin-top: 16px; + margin-bottom: 10px; font-weight: 700; - line-height: 1.4; + line-height: 1.3; + color: #0f172a; +} +.markdown-body h3, .markdown-body h4 { + font-size: 16px; } diff --git a/src/app/app.html b/src/app/app.html index 68d29b1..4005853 100644 --- a/src/app/app.html +++ b/src/app/app.html @@ -136,7 +136,7 @@
- +
diff --git a/src/app/app.ts b/src/app/app.ts index 07eb4df..3af5762 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -127,7 +127,8 @@ export class App implements OnDestroy, OnInit { const currentStreamingMsg = this.chatMessages.find(m => m.isStreaming && m.role === 'agent'); if (currentStreamingMsg) { currentStreamingMsg.rawContent = (currentStreamingMsg.rawContent || '') + payload.text; - currentStreamingMsg.htmlContent = marked.parse(currentStreamingMsg.rawContent) as string; + const displayStr = this.sanitizeStreamingContent(currentStreamingMsg.rawContent); + currentStreamingMsg.htmlContent = marked.parse(displayStr) as string; } break; case 'agent:thinking': @@ -141,7 +142,11 @@ export class App implements OnDestroy, OnInit { activeStreamingMsg.isStreaming = false; if (payload.fullAnswer) { activeStreamingMsg.rawContent = payload.fullAnswer; - activeStreamingMsg.htmlContent = marked.parse(activeStreamingMsg.rawContent || '') as string; + const finalStr = this.sanitizeStreamingContent(activeStreamingMsg.rawContent || ''); + activeStreamingMsg.htmlContent = marked.parse(finalStr) as string; + } else { + const finalFallbackStr = this.sanitizeStreamingContent(activeStreamingMsg.rawContent || ''); + activeStreamingMsg.htmlContent = marked.parse(finalFallbackStr) as string; } } break; @@ -458,7 +463,8 @@ export class App implements OnDestroy, OnInit { if (res && res.messages && res.messages.length > 0) { this.chatMessages = res.messages.map((m: any) => { const rawContent = m.content || ''; - const htmlContent = marked.parse(rawContent) as string; + const displayStr = this.sanitizeStreamingContent(rawContent); + const htmlContent = marked.parse(displayStr) as string; return { role: m.role, rawContent: rawContent, @@ -509,4 +515,16 @@ export class App implements OnDestroy, OnInit { } } + private sanitizeStreamingContent(raw: string): string { + if (!raw) return ''; + let text = raw; + // Strip markdown JSON block wrappings entirely + text = text.replace(/```json\s*\{[\s\S]*?\}\s*```/g, ''); + // Strip bare unescaped JSON tool reports which match specific sigs + text = text.replace(/\{"content":[\s\S]*?\}/g, ''); + text = text.replace(/\{"total_count":[\s\S]*?\}/g, ''); + // Strip trailing tool garbage that might be partially yielded + return text.trim(); + } + }