init
This commit is contained in:
137
vw-agentic-rag/docs/topics/CHAT_UI_LINK_FIX.md
Normal file
137
vw-agentic-rag/docs/topics/CHAT_UI_LINK_FIX.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Chat UI 链接渲染问题修复报告
|
||||
|
||||
## 📝 问题描述
|
||||
|
||||
用户报告Chat UI上的链接没有正确被渲染,从截图中可以看到:
|
||||
- 内容中包含HTML格式的`<a>`标签而不是markdown格式的链接
|
||||
- 链接文本显示但不可点击
|
||||
- HTML代码直接显示在UI中
|
||||
|
||||
## 🔍 根本原因分析
|
||||
|
||||
1. **组件配置冲突**:
|
||||
- `MyChat`组件同时配置了`assistantMessage: { components: { Text: MarkdownText } }`
|
||||
- 又使用了自定义的`AiAssistantMessage`组件
|
||||
- `AiAssistantMessage`使用默认的`<AssistantMessage.Content />`,忽略了MarkdownText配置
|
||||
|
||||
2. **Agent输出格式问题**:
|
||||
- Agent生成HTML格式的链接而不是Markdown格式
|
||||
- 后端citations处理正确生成Markdown,但Agent本身输出了HTML
|
||||
|
||||
3. **前端处理能力不足**:
|
||||
- `MarkdownTextPrimitive`只能处理markdown,不能处理HTML
|
||||
- 缺少`@tailwindcss/typography`插件支持prose样式
|
||||
- 没有DOMPurify来安全处理HTML内容
|
||||
|
||||
## ✅ 解决方案
|
||||
|
||||
### 1. 修复组件配置冲突
|
||||
```tsx
|
||||
// AiAssistantMessage.tsx - 直接指定MarkdownText组件
|
||||
<AssistantMessage.Content components={{ Text: MarkdownText }} />
|
||||
|
||||
// mychat.tsx - 移除重复配置
|
||||
config={{
|
||||
welcome: { message: t.welcomeMessage },
|
||||
// 移除了 assistantMessage 配置
|
||||
}}
|
||||
```
|
||||
|
||||
### 2. 增强MarkdownText组件
|
||||
```tsx
|
||||
// 智能检测内容类型并相应处理
|
||||
const containsHTMLLinks = typeof content === 'string' && /<a\s+[^>]*href/i.test(content);
|
||||
|
||||
if (containsHTMLLinks) {
|
||||
// HTML内容:使用DOMPurify清理后直接渲染
|
||||
return <div dangerouslySetInnerHTML={{ __html: sanitizedHTML }} />;
|
||||
} else {
|
||||
// Markdown内容:使用标准的markdown处理器
|
||||
return <MarkdownTextPrimitive ... />;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 添加必要的依赖
|
||||
```bash
|
||||
pnpm add @tailwindcss/typography # Prose样式支持
|
||||
pnpm add isomorphic-dompurify # 安全HTML清理
|
||||
pnpm add rehype-external-links # 外部链接处理
|
||||
```
|
||||
|
||||
### 4. 更新Agent系统提示
|
||||
```yaml
|
||||
agent_system_prompt: |
|
||||
# Response Format Requirements:
|
||||
- Use ONLY Markdown formatting (headers, lists, emphasis, etc.)
|
||||
- DO NOT use HTML tags like <a>, <href>, etc. Use only Markdown link syntax
|
||||
- DO NOT generate HTML anchor tags - the system will convert markdown links automatically
|
||||
```
|
||||
|
||||
### 5. 增强Tailwind配置
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
plugins: [
|
||||
require("tailwindcss-animate"),
|
||||
require("@tailwindcss/typography"), // 新增
|
||||
require("@assistant-ui/react-ui/tailwindcss")({...})
|
||||
],
|
||||
```
|
||||
|
||||
## 🎯 修复效果
|
||||
|
||||
现在Chat UI应该能够:
|
||||
|
||||
1. ✅ **正确渲染链接**:无论是Markdown还是HTML格式
|
||||
2. ✅ **安全处理**:DOMPurify清理恶意HTML内容
|
||||
3. ✅ **外部链接安全**:自动添加`target="_blank"`和`rel="noopener noreferrer"`
|
||||
4. ✅ **视觉样式**:链接显示为蓝色,有适当的悬停效果
|
||||
5. ✅ **保持功能**:typing indicator等现有功能不受影响
|
||||
|
||||
## 🔧 技术实现细节
|
||||
|
||||
### 智能内容检测
|
||||
```typescript
|
||||
const containsHTMLLinks = /<a\s+[^>]*href/i.test(content);
|
||||
```
|
||||
|
||||
### HTML属性确保
|
||||
```typescript
|
||||
processedContent = processedContent.replace(
|
||||
/<a\s+([^>]*?)href\s*=\s*["']([^"']+)["']([^>]*?)>/gi,
|
||||
(match, before, href, after) => {
|
||||
const isExternal = href.startsWith('http://') || href.startsWith('https://');
|
||||
if (isExternal) {
|
||||
// 确保安全属性存在
|
||||
let attributes = before + after;
|
||||
if (!attributes.includes('target=')) attributes += ' target="_blank"';
|
||||
if (!attributes.includes('rel=')) attributes += ' rel="noopener noreferrer"';
|
||||
return `<a href="${href}"${attributes}>`;
|
||||
}
|
||||
return match;
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
### DOMPurify安全清理
|
||||
```typescript
|
||||
const sanitizedHTML = DOMPurify.sanitize(processedContent, {
|
||||
ALLOWED_TAGS: ['a', 'p', 'div', 'span', 'strong', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ul', 'ol', 'li', 'br'],
|
||||
ALLOWED_ATTR: ['href', 'target', 'rel', 'title', 'class']
|
||||
});
|
||||
```
|
||||
|
||||
## 📋 测试验证
|
||||
|
||||
1. **服务器状态**:✅ 后端服务运行在 http://127.0.0.1:8000
|
||||
2. **前端状态**:✅ 前端开发服务器运行在 http://localhost:3001
|
||||
3. **构建测试**:✅ 所有组件正常构建
|
||||
4. **依赖完整**:✅ 所有必要的npm包已安装
|
||||
|
||||
## 🔮 下一步
|
||||
|
||||
1. 在浏览器中访问 http://localhost:3001 测试Chat UI
|
||||
2. 发送包含引用的查询验证链接渲染
|
||||
3. 检查链接是否可点击且在新标签页打开
|
||||
4. 验证typing indicator等功能正常工作
|
||||
|
||||
这个解决方案提供了向后兼容性,能够处理两种内容格式,并确保了安全性和用户体验。
|
||||
Reference in New Issue
Block a user