AI 交互架构
1. RAG(检索增强生成)
题目:什么是 RAG(检索增强生成)?前端在 RAG 应用中需要承担哪些工作?
答案要点:
RAG 通过检索外部知识库来弥补模型时效性不足,前端主要负责知识溯源的展示和交互。
- 引用标注: 在 AI 回复中高亮显示引用来源,点击可跳转到原始文档片段
- 文档切片预览: 展示向量数据库检索出的 Top-K 片段,并支持用户反馈相关性
- 预处理: 在上传文档时,前端可进行初步的格式清洗或分段预览
- 交互链路: 处理"检索中 -> 思考中 -> 生成中"的复杂状态流转
前端架构设计:
typescript
interface RAGResponse {
answer: string
sources: {
id: string
content: string
document: string
page?: number
relevance: number
}[]
}
// 引用高亮组件
function CitationHighlight({ text, citations }: { text: string; citations: Citation[] }) {
return (
<div className="rag-answer">
{parseTextWithCitations(text).map((part, idx) =>
part.type === 'citation' ? (
<sup key={idx} className="citation">
[{part.id}]
</sup>
) : (
<span key={idx}>{part.text}</span>
),
)}
</div>
)
}常见坑:
- 引用链接失效或索引偏移导致的标注错误
题目:谈谈 RAG(检索增强生成)在前端侧可以做哪些优化?
答案要点:
- 检索结果预览: 在发送问题前,展示可能相关的文档片段
- 引用交互: 支持点击引用跳转到原文,悬浮显示上下文
- 相关性反馈: 让用户标记检索结果的相关性,用于优化向量模型
- 文档预处理: 上传时进行 OCR、格式转换、自动分段
2. Prompt Engineering
题目:谈谈你对 Prompt Engineering(提示工程)在前端业务代码中封装的理解?
答案要点:
在前端侧封装 Prompt 主要是为了屏蔽模型差异,并根据用户交互动态构建上下文。
- 模板化: 将 Prompt 定义为模板字符串,通过占位符注入变量(如用户输入、历史记录)
- 角色隔离: 明确 System Prompt(约束行为)、User Prompt(具体指令)和 Few-shot(示例)
- 结构化输出: 在 Prompt 中强制要求模型返回特定格式(如 JSON),方便前端解析
- 版本管理: 将 Prompt 逻辑从业务代码中抽离,支持根据模型版本动态切换
代码示例:
typescript
// Prompt 模板管理
class PromptTemplate {
private templates: Map<string, string> = new Map()
register(name: string, template: string) {
this.templates.set(name, template)
}
render(name: string, variables: Record<string, any>): string {
const template = this.templates.get(name)
if (!template) throw new Error(`Template ${name} not found`)
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return variables[key] ?? match
})
}
}
// 使用
const promptManager = new PromptTemplate()
promptManager.register(
'code-review',
`
你是一位资深前端工程师,请对以下代码进行审查:
文件:{{filename}}
代码:
\`\`\`{{language}}
{{code}}
\`\`\`
请从以下方面给出建议:
1. 代码规范
2. 性能优化
3. 潜在 Bug
`,
)
const prompt = promptManager.render('code-review', {
filename: 'utils.ts',
language: 'typescript',
code: 'function add(a, b) { return a + b; }',
})常见坑:
- Prompt 过长导致 Token 浪费和响应延迟
题目:在前端如何实现 Prompt 的版本管理和动态替换变量?
答案要点:
- 配置化存储: 将 Prompt 存储在 JSON/YAML 配置文件中
- 版本控制: 使用 Git 管理 Prompt 变更,支持 A/B 测试
- 热更新: 支持不重启服务更新 Prompt
- 变量注入: 使用模板引擎(如 Handlebars、Mustache)进行变量替换
3. AI Agent 架构
题目:谈谈 AI Agent 的基本架构,以及前端如何实现一个简单的 Agent 闭环?
答案要点:
AI Agent 是能够自主决策并执行任务的智能体,通常包含感知、思考、行动三个模块。
基本架构:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 感知层 │ -> │ 思考层 │ -> │ 行动层 │
│ (Input) │ │ (LLM) │ │ (Tools) │
└─────────┘ └─────────┘ └─────────┘
↑ │
└────────────┬───────────────┘
↓
┌─────────┐
│ 记忆层 │
│(Memory) │
└─────────┘前端实现:
typescript
interface Agent {
perceive(input: string): Observation
think(observation: Observation): Action
act(action: Action): Result
remember(interaction: Interaction): void
}
class SimpleAgent implements Agent {
private memory: Interaction[] = []
private tools: Map<string, Tool> = new Map()
async run(input: string): Promise<string> {
// 1. 感知
const observation = this.perceive(input)
// 2. 思考(调用 LLM)
const action = await this.think(observation)
// 3. 行动
const result = await this.act(action)
// 4. 记忆
this.remember({ input, action, result })
return result
}
private async think(observation: Observation): Promise<Action> {
const response = await llm.chat({
messages: [
{ role: 'system', content: '你是一个助手,可以使用以下工具...' },
...this.memoryToContext(),
{ role: 'user', content: observation.text },
],
tools: Array.from(this.tools.values()),
})
return this.parseAction(response)
}
}4. 低代码 AI Agent 编排
题目:设计一个低代码 AI Agent 编排画布(类似 LangFlow),你会如何选型和设计架构?
答案要点:
- 节点设计: 定义各种节点类型(输入、LLM、工具、条件、输出)
- 数据流: 基于 DAG(有向无环图)的数据流转
- 状态管理: 使用 Redux/MobX 管理画布状态
- 执行引擎: 前端负责编排,后端负责实际执行
- 可视化: 使用 React Flow、X6 等库实现节点拖拽和连线
架构设计:
typescript
// 节点定义
interface Node {
id: string
type: 'input' | 'llm' | 'tool' | 'condition' | 'output'
position: { x: number; y: number }
data: Record<string, any>
inputs: Port[]
outputs: Port[]
}
// 边定义
interface Edge {
id: string
source: string
target: string
sourcePort: string
targetPort: string
}
// 工作流定义
interface Workflow {
nodes: Node[]
edges: Edge[]
}
// 执行引擎
class WorkflowEngine {
async execute(workflow: Workflow, input: any): Promise<any> {
const graph = this.buildGraph(workflow)
const executionOrder = this.topologicalSort(graph)
const context = new ExecutionContext()
context.set('input', input)
for (const nodeId of executionOrder) {
const node = graph.getNode(nodeId)
const result = await this.executeNode(node, context)
context.set(nodeId, result)
}
return context.get('output')
}
}5. 上下文管理
题目:如何处理大模型对话中的上下文管理(Context Window)?
答案要点:
上下文窗口有限,需要智能地管理历史对话。
- 滑动窗口: 只保留最近的 N 轮对话
- 摘要压缩: 对早期对话进行摘要,减少 Token 占用
- 关键信息提取: 提取用户偏好、重要事实存储在记忆库中
- 向量化检索: 将历史对话向量化,按需检索相关上下文
代码示例:
typescript
class ContextManager {
private maxTokens: number = 4000
private messages: Message[] = []
addMessage(message: Message) {
this.messages.push(message)
this.optimizeContext()
}
private optimizeContext() {
const totalTokens = this.estimateTokens(this.messages)
if (totalTokens > this.maxTokens) {
// 策略1:删除最早的对话
// this.messages = this.messages.slice(-10);
// 策略2:摘要早期对话
const toSummarize = this.messages.slice(0, -5)
const summary = this.summarize(toSummarize)
this.messages = [
{ role: 'system', content: `历史摘要:${summary}` },
...this.messages.slice(-5),
]
}
}
private estimateTokens(messages: Message[]): number {
// 简单估算:1 token ≈ 4 个字符
return messages.reduce((acc, msg) => acc + Math.ceil(msg.content.length / 4), 0)
}
}6. 多模态输入
题目:前端如何实现多模态输入(图片、语音)的预处理?
答案要点:
- 图片处理: 压缩、格式转换、Base64 编码
- 语音处理: 录音、降噪、转文字(ASR)
- 文件上传: 分片上传、断点续传
- 预览展示: 图片预览、音频播放
代码示例:
typescript
class MultimodalPreprocessor {
// 图片压缩
async compressImage(file: File, maxSize: number): Promise<string> {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = (e) => {
const img = new Image()
img.onload = () => {
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')!
// 计算压缩后的尺寸
let { width, height } = img
if (width > height && width > maxSize) {
height *= maxSize / width
width = maxSize
} else if (height > maxSize) {
width *= maxSize / height
height = maxSize
}
canvas.width = width
canvas.height = height
ctx.drawImage(img, 0, 0, width, height)
resolve(canvas.toDataURL('image/jpeg', 0.8))
}
img.src = e.target!.result as string
}
reader.readAsDataURL(file)
})
}
// 语音转文字(使用 Web Speech API)
async speechToText(): Promise<string> {
return new Promise((resolve, reject) => {
const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)()
recognition.lang = 'zh-CN'
recognition.onresult = (event) => {
resolve(event.results[0][0].transcript)
}
recognition.onerror = reject
recognition.start()
})
}
}7. AI 组件库设计
题目:如果让你从零搭建一个前端 AI 组件库,你会包含哪些核心组件?
答案要点:
核心组件列表:
| 组件 | 功能 |
|---|---|
| Chat | 聊天对话容器 |
| Message | 消息气泡(支持 Markdown) |
| StreamingText | 流式文本显示 |
| CodeBlock | 代码块(支持复制、高亮) |
| PromptInput | 提示词输入框 |
| ModelSelector | 模型选择器 |
| TokenCounter | Token 计数器 |
| Citation | 引用标注 |
| Thinking | 思考过程展示 |
| FileUploader | 文件上传(支持多模态) |
设计原则:
- 可组合性: 组件可以灵活组合
- 可定制性: 支持主题定制
- 性能优化: 虚拟列表、懒加载
- 无障碍: ARIA 支持
