前言
大家好,我是木斯佳。
相信很多人都感受到了,在AI浪潮的席卷之下,前端领域的门槛在变高,纯粹的"增删改查"岗位正在肉眼可见地减少。曾经热闹非凡的面经分享,如今也沉寂了许多。但我们都知道,市场的潮水退去,留下的才是真正在踏实准备、努力沉淀的人。学习的需求,从未消失,只是变得更加务实和深入。
这个专栏的初衷很简单:拒绝过时的、流水线式的PDF引流贴,专注于收集和整理当下最新、最真实的前端面试资料。我会在每一份面经和八股文的基础上,尝试从面试官的角度去拆解问题背后的逻辑,而不仅仅是提供一份静态的背诵答案。无论你是校招还是社招,目标是中大厂还是新兴团队,只要是真实发生、有价值的面试经历,我都会在这个专栏里为你沉淀下来。专栏快速链接

温馨提示:市面上的面经鱼龙混杂,甄别真伪、把握时效,是我们对抗内卷最有效的武器。
面经原文内容
📍面试公司:阿里云
🕐面试时间:近期,用户上传于2026-03-21
💻面试岗位:AI应用开发前端二面
⏱️面试时长:未提及
📝面试体验:整体面试不错,但没后续了,不知道哪里出了问题
❓面试问题:
- 在构建AIChat应用时,长列表的性能优化有哪些核心方案?
- 请详细说明RAG(检索增强生成)前端链路中,如何处理文档上传、切片与向量化的交互流程?
- 谈谈你对Prompt Engineering的理解,前端如何通过工程化手段提升Prompt的质量和安全性?
- 如何设计一个通用的AI组件库(AIUIKit)?需要考虑哪些特殊组件?
- 在AI应用中,如何优化首屏加载速度,特别是涉及大型WebAssembly模块(如本地向量化模型)时?
- 解释一下Function Calling(函数调用)的原理,前端如何配合模型完成一次完整的工具调用?
- 你们项目中是如何处理AI生成内容的持久化和多端同步的?
- 谈谈Web Worker在AI前端应用中的实际应用场景。
来源:牛客网 关关过_关关过
💡 木木有话说(刷前先看)
这是一份非常典型的AI前端面试题。涵盖了AI前端开发的所有关键技术点。这份面经值得反复推敲,每个问题都能延伸出一个完整的技术方案。
📝 阿里云AI应用开发二面·深度解析
🎯 面试整体画像
| 维度 | 特征 |
|---|---|
| 面试风格 | 场景驱动型 + 架构设计型 + 深度追问型 |
| 难度评级 | ⭐⭐⭐⭐(四星,AI前端专项深度考察) |
| 考察重心 | AI应用工程化、RAG链路、性能优化、组件设计、WebAssembly |
| 特殊之处 | 聚焦AI应用前端场景,问题之间环环相扣,考察系统设计能力 |
🔍 逐题深度解析
一、AIChat应用长列表性能优化
问题:在构建AIChat应用时,长列表的性能优化有哪些核心方案?
AIChat应用的消息列表是典型的长列表场景,随着对话进行,消息数量可能达到数百甚至上千条。优化方案需要从渲染、滚动、内存等多个维度考虑。
javascript
// 1. 虚拟滚动(核心方案)
// 只渲染可视区域内的消息,大幅减少DOM节点数量
import { FixedSizeList, VariableSizeList } from 'react-window'
// 固定高度消息
const MessageList = ({ messages }) => (
<FixedSizeList
height={600}
itemCount={messages.length}
itemSize={80}
width="100%"
>
{({ index, style }) => (
<MessageItem
style={style}
message={messages[index]}
/>
)}
</FixedSizeList>
)
// 可变高度消息(需要预先测量高度)
const VariableMessageList = ({ messages }) => {
const listRef = useRef()
return (
<VariableSizeList
ref={listRef}
height={600}
itemCount={messages.length}
itemSize={index => getMessageHeight(messages[index])}
width="100%"
>
{({ index, style }) => (
<MessageItem
style={style}
message={messages[index]}
/>
)}
</VariableSizeList>
)
}
// 2. 消息缓存与分页
// 2.1 虚拟滚动 + 无限加载
const useInfiniteMessages = () => {
const [messages, setMessages] = useState([])
const [hasMore, setHasMore] = useState(true)
const [page, setPage] = useState(1)
const loadMore = async () => {
if (!hasMore) return
const newMessages = await fetchMessages({ page, limit: 50 })
setMessages(prev => [...prev, ...newMessages])
setHasMore(newMessages.length === 50)
setPage(p => p + 1)
}
return { messages, loadMore, hasMore }
}
// 3. 滚动性能优化
// 3.1 滚动事件防抖/节流
const handleScroll = throttle((e) => {
const { scrollTop, scrollHeight, clientHeight } = e.target
const isNearBottom = scrollHeight - scrollTop - clientHeight < 100
if (isNearBottom) {
loadMore()
}
}, 100)
// 3.2 使用passive事件监听
useEffect(() => {
const container = scrollRef.current
container.addEventListener('scroll', handleScroll, { passive: true })
return () => container.removeEventListener('scroll', handleScroll)
}, [])
// 4. 消息渲染优化
// 4.1 消息项组件优化
const MessageItem = React.memo(({ message, style }) => {
// 使用useMemo缓存复杂计算
const formattedTime = useMemo(() => {
return formatTime(message.timestamp)
}, [message.timestamp])
// 代码高亮等耗时操作
const highlightedContent = useMemo(() => {
return highlightCode(message.content)
}, [message.content])
return (
<div style={style} className="message-item">
<Avatar user={message.user} />
<div dangerouslySetInnerHTML={{ __html: highlightedContent }} />
<span>{formattedTime}</span>
</div>
)
})
// 4.2 消息分组渲染
const GroupedMessageList = ({ messages }) => {
// 按日期分组,减少渲染次数
const grouped = useMemo(() => {
return messages.reduce((groups, msg) => {
const date = formatDate(msg.timestamp)
if (!groups[date]) groups[date] = []
groups[date].push(msg)
return groups
}, {})
}, [messages])
return Object.entries(grouped).map(([date, msgs]) => (
<div key={date}>
<DateDivider>{date}</DateDivider>
{msgs.map(msg => <MessageItem key={msg.id} message={msg} />)}
</div>
))
}
// 5. 内存优化
// 5.1 限制历史消息数量
const MAX_MESSAGES = 1000
const addMessage = (newMessage) => {
setMessages(prev => {
const updated = [...prev, newMessage]
// 超出限制时移除最早的消息
if (updated.length > MAX_MESSAGES) {
return updated.slice(-MAX_MESSAGES)
}
return updated
})
}
// 5.2 图片/媒体懒加载
const LazyImage = ({ src, alt }) => {
const [isLoaded, setIsLoaded] = useState(false)
const imgRef = useRef()
useEffect(() => {
const observer = new IntersectionObserver(([entry]) => {
if (entry.isIntersecting) {
setIsLoaded(true)
observer.disconnect()
}
})
observer.observe(imgRef.current)
return () => observer.disconnect()
}, [])
return (
<div ref={imgRef}>
{isLoaded ? <img src={src} alt={alt} /> : <Placeholder />}
</div>
)
}
// 6. 性能监控
// 使用Performance API监控列表渲染时间
performance.mark('list-start')
// 渲染完成后
performance.mark('list-end')
performance.measure('list-render', 'list-start', 'list-end')
const duration = performance.getEntriesByName('list-render')[0].duration
if (duration > 100) {
// 上报性能问题
reportPerformance('list-slow', duration)
}
二、RAG前端链路:文档上传、切片与向量化
问题:请详细说明RAG(检索增强生成)前端链路中,如何处理文档上传、切片与向量化的交互流程?
RAG应用的前端链路涉及文档处理的全流程,需要设计良好的用户反馈和错误处理机制。
javascript
// 1. 完整流程图
// 用户选择文件 → 上传预览 → 分块处理 → 向量化 → 存储 → 索引完成
// 2. 文档上传组件
class RAGDocumentUploader {
constructor() {
this.chunkSize = 500 // 分块大小(字符数)
this.overlap = 50 // 重叠大小
this.supportedTypes = ['.pdf', '.txt', '.md', '.docx']
}
// 2.1 文件上传与验证
async uploadFile(file) {
// 文件类型验证
const ext = file.name.split('.').pop()
if (!this.supportedTypes.includes(`.${ext}`)) {
throw new Error(`不支持的文件类型: ${ext}`)
}
// 文件大小验证(限制50MB)
if (file.size > 50 * 1024 * 1024) {
throw new Error('文件大小不能超过50MB')
}
// 上传到临时存储
const uploadId = await this.initUpload(file)
// 分片上传(大文件)
if (file.size > 10 * 1024 * 1024) {
return this.chunkUpload(file, uploadId)
}
return this.simpleUpload(file, uploadId)
}
// 2.2 文档解析与分块
async parseAndChunk(fileId) {
// 显示解析进度
this.updateProgress('解析文档中...', 30)
// 解析文档内容(服务端或本地)
const content = await this.parseDocument(fileId)
// 智能分块
const chunks = await this.smartChunking(content)
this.updateProgress(`文档已分为 ${chunks.length} 个块`, 50)
return chunks
}
// 2.3 智能分块算法
async smartChunking(content) {
// 按段落分割
const paragraphs = content.split(/\n\s*\n/)
const chunks = []
let currentChunk = ''
let currentSize = 0
for (const para of paragraphs) {
const paraSize = para.length
// 如果段落本身超过块大小,需要进一步分割
if (paraSize > this.chunkSize) {
// 按句子分割
const sentences = para.split(/[。!?.!?]/)
for (const sentence of sentences) {
if (currentSize + sentence.length > this.chunkSize && currentChunk) {
chunks.push(currentChunk)
// 保留重叠部分
currentChunk = this.getOverlap(currentChunk, this.overlap)
currentSize = currentChunk.length
}
currentChunk += sentence
currentSize += sentence.length
}
} else if (currentSize + paraSize > this.chunkSize && currentChunk) {
// 当前块已满,保存
chunks.push(currentChunk)
// 保留重叠部分
currentChunk = this.getOverlap(currentChunk, this.overlap)
currentSize = currentChunk.length
currentChunk += para
currentSize += paraSize
} else {
currentChunk += (currentChunk ? '\n\n' : '') + para
currentSize += paraSize
}
}
if (currentChunk) {
chunks.push(currentChunk)
}
return chunks
}
// 2.4 向量化处理
async vectorizeChunks(chunks, onProgress) {
const vectors = []
const batchSize = 10 // 批量处理,避免阻塞
for (let i = 0; i < chunks.length; i += batchSize) {
const batch = chunks.slice(i, i + batchSize)
// 调用向量化API
const batchVectors = await Promise.all(
batch.map(chunk => this.embeddingAPI.embed(chunk))
)
vectors.push(...batchVectors)
// 更新进度
onProgress?.({
current: i + batch.length,
total: chunks.length,
percentage: Math.round((i + batch.length) / chunks.length * 100)
})
}
return vectors
}
// 2.5 存储到向量数据库
async storeVectors(chunks, vectors, documentId) {
const records = chunks.map((chunk, index) => ({
id: `${documentId}_${index}`,
documentId,
content: chunk,
vector: vectors[index],
metadata: {
index,
timestamp: Date.now()
}
}))
// 批量插入向量数据库
await this.vectorDB.batchInsert(records)
return records.length
}
// 2.6 完整流程串联
async processDocument(file) {
try {
// 1. 上传
this.setStatus('uploading')
const { fileId, url } = await this.uploadFile(file)
// 2. 解析分块
this.setStatus('parsing')
const chunks = await this.parseAndChunk(fileId)
// 3. 向量化
this.setStatus('vectorizing')
const vectors = await this.vectorizeChunks(chunks, (progress) => {
this.setProgress(progress)
})
// 4. 存储
this.setStatus('storing')
const count = await this.storeVectors(chunks, vectors, fileId)
this.setStatus('completed')
return { fileId, chunksCount: count }
} catch (error) {
this.setStatus('error')
this.setError(error.message)
throw error
}
}
}
// 3. UI状态管理
const useDocumentUpload = () => {
const [status, setStatus] = useState('idle')
const [progress, setProgress] = useState(0)
const [error, setError] = useState(null)
const process = async (file) => {
setStatus('processing')
setProgress(0)
try {
const uploader = new RAGDocumentUploader()
const result = await uploader.processDocument(file)
setStatus('success')
return result
} catch (err) {
setStatus('error')
setError(err.message)
}
}
return { status, progress, error, process }
}
// 4. 取消/中断处理
class AbortableUploader {
constructor() {
this.abortController = null
}
async upload(file) {
this.abortController = new AbortController()
try {
const response = await fetch('/api/upload', {
method: 'POST',
body: file,
signal: this.abortController.signal
})
return response
} catch (error) {
if (error.name === 'AbortError') {
console.log('上传已取消')
}
throw error
}
}
cancel() {
this.abortController?.abort()
}
}
三、Prompt Engineering与工程化
问题:谈谈你对Prompt Engineering的理解,前端如何通过工程化手段提升Prompt的质量和安全性?
Prompt Engineering是AI应用开发的核心能力,前端需要通过工程化手段来管理、优化和保障Prompt的质量与安全。
javascript
// 1. Prompt工程化架构
// 1.1 Prompt模板管理
// prompts/templates/
// ├── chat/
// │ ├── system.base.json
// │ ├── system.customer.json
// │ └── user.query.json
// ├── rag/
// │ ├── retrieval.prompt.json
// │ └── generation.prompt.json
// └── tool/
// ├── function.calling.json
// └── tool.result.json
// 1.2 Prompt版本控制
interface PromptTemplate {
id: string
name: string
version: string
content: string
variables: string[]
metadata: {
createdAt: Date
updatedAt: Date
author: string
description: string
tags: string[]
}
}
class PromptManager {
private templates: Map<string, PromptTemplate> = new Map()
// 加载模板
async loadTemplate(name: string, version?: string): Promise<PromptTemplate> {
const key = version ? `${name}@${version}` : name
if (!this.templates.has(key)) {
const template = await this.fetchTemplate(name, version)
this.templates.set(key, template)
}
return this.templates.get(key)!
}
// 渲染Prompt
render(template: PromptTemplate, variables: Record<string, any>): string {
let result = template.content
for (const [key, value] of Object.entries(variables)) {
result = result.replace(new RegExp(`{{${key}}}`, 'g'), value)
}
return result
}
// 验证模板
validate(template: PromptTemplate): ValidationResult {
const errors = []
// 检查变量是否都有默认值
for (const variable of template.variables) {
if (!template.content.includes(`{{${variable}}}`)) {
errors.push(`变量 ${variable} 在模板中未使用`)
}
}
return { valid: errors.length === 0, errors }
}
}
// 2. Prompt质量提升
// 2.1 结构化Prompt设计
const structuredPrompt = {
system: `你是一个专业的{{role}}助手。
能力范围:
- {{capability1}}
- {{capability2}}
约束条件:
- {{constraint1}}
- {{constraint2}}
回答格式:
{{format}}`,
user: `用户输入:{{input}}
请基于以下上下文回答:
{{context}}`,
// 输出格式约束
format: {
json: '请以JSON格式输出:{"answer": "...", "confidence": 0.9}',
markdown: '请使用Markdown格式组织回答',
simple: '请用简洁的语言回答'
}
}
// 2.2 Few-shot示例管理
class FewShotManager {
private examples: Map<string, Example[]> = new Map()
addExample(task: string, example: Example) {
if (!this.examples.has(task)) {
this.examples.set(task, [])
}
this.examples.get(task)!.push(example)
}
getExamples(task: string, limit: number = 3): Example[] {
const examples = this.examples.get(task) || []
// 动态选择最相关的示例(基于embedding相似度)
return this.selectRelevantExamples(examples, limit)
}
private selectRelevantExamples(examples: Example[], limit: number): Example[] {
// 根据当前上下文选择最相关的示例
return examples.slice(0, limit)
}
}
// 3. Prompt安全性保障
// 3.1 注入攻击防护
class PromptSanitizer {
// 过滤敏感信息
sanitize(input: string): string {
// 移除可能的注入模式
return input
.replace(/[\x00-\x1f\x7f-\x9f]/g, '') // 移除控制字符
.replace(/{{(.*?)}}/g, (match, content) => {
// 阻止模板注入
return `{${content.replace(/[{}]/g, '')}}`
})
.substring(0, 4000) // 限制长度
}
// 敏感信息检测
detectSensitiveInfo(input: string): SensitiveInfo[] {
const patterns = [
{ pattern: /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}/, type: 'email' },
{ pattern: /1[3-9]\d{9}/, type: 'phone' },
{ pattern: /(\d{15,19})/, type: 'credit_card' }
]
return patterns
.map(({ pattern, type }) => {
if (pattern.test(input)) {
return { type, detected: true }
}
return null
})
.filter(Boolean)
}
}
// 3.2 内容审核
class ContentModerator {
private bannedWords: Set<string>
async moderate(prompt: string): Promise<ModerationResult> {
// 敏感词过滤
const containsBanned = Array.from(this.bannedWords).some(word =>
prompt.toLowerCase().includes(word)
)
if (containsBanned) {
return { passed: false, reason: '包含敏感词' }
}
// 调用外部审核API
const externalResult = await this.callModerationAPI(prompt)
return externalResult
}
}
// 4. Prompt优化与A/B测试
class PromptOptimizer {
private metrics: Map<string, PromptMetrics> = new Map()
async runABTest(
variantA: PromptTemplate,
variantB: PromptTemplate,
testCases: TestCase[]
): Promise<ABTestResult> {
const results = {
A: await this.evaluate(variantA, testCases),
B: await this.evaluate(variantB, testCases)
}
return {
winner: results.A.score > results.B.score ? 'A' : 'B',
metrics: results
}
}
private async evaluate(template: PromptTemplate, testCases: TestCase[]): Promise<EvaluationResult> {
let totalScore = 0
for (const testCase of testCases) {
const prompt = this.render(template, testCase.variables)
const response = await this.callLLM(prompt)
const score = await this.evaluateResponse(response, testCase.expected)
totalScore += score
}
return {
averageScore: totalScore / testCases.length,
totalTests: testCases.length
}
}
}
// 5. Prompt监控与日志
class PromptLogger {
async logInteraction(data: {
prompt: string
response: string
latency: number
tokens: { input: number; output: number }
success: boolean
error?: string
}) {
await this.sendToAnalytics({
type: 'prompt_interaction',
timestamp: Date.now(),
...data,
// 脱敏处理
prompt: this.redactSensitive(data.prompt),
response: this.redactSensitive(data.response)
})
}
private redactSensitive(text: string): string {
// 脱敏处理
return text
.replace(/\b\d{15,19}\b/g, '****')
.replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g, '***@***.***')
}
}
四、通用AI组件库设计
问题:如何设计一个通用的AI组件库(AI UIKit)?需要考虑哪些特殊组件?
AI组件库需要封装AI应用中的常见交互模式,提供开箱即用的能力。
typescript
// 1. AI组件库架构设计
// 1.1 组件分类
const AIUIKit = {
// 对话类组件
Chat: {
ChatContainer: './Chat/ChatContainer',
MessageList: './Chat/MessageList',
MessageItem: './Chat/MessageItem',
InputArea: './Chat/InputArea',
StreamingText: './Chat/StreamingText'
},
// 输入类组件
Input: {
RichTextEditor: './Input/RichTextEditor',
VoiceInput: './Input/VoiceInput',
FileUpload: './Input/FileUpload',
MentionInput: './Input/MentionInput'
},
// 展示类组件
Display: {
MarkdownRenderer: './Display/MarkdownRenderer',
CodeHighlighter: './Display/CodeHighlighter',
ThinkingProcess: './Display/ThinkingProcess',
CitationPanel: './Display/CitationPanel'
},
// 反馈类组件
Feedback: {
Rating: './Feedback/Rating',
CopyButton: './Feedback/CopyButton',
RegenerateButton: './Feedback/RegenerateButton',
ReportButton: './Feedback/ReportButton'
},
// 工具类组件
Tools: {
FunctionCalling: './Tools/FunctionCalling',
KnowledgeBase: './Tools/KnowledgeBase',
ImageGenerator: './Tools/ImageGenerator'
}
}
// 2. 核心组件实现
// 2.1 流式文本组件
interface StreamingTextProps {
content: string | AsyncIterable<string>
speed?: 'slow' | 'normal' | 'fast'
onComplete?: () => void
onChar?: (char: string) => void
}
const StreamingText: React.FC<StreamingTextProps> = ({
content,
speed = 'normal',
onComplete
}) => {
const [displayText, setDisplayText] = useState('')
const [isComplete, setIsComplete] = useState(false)
useEffect(() => {
if (typeof content === 'string') {
// 静态内容,直接显示
setDisplayText(content)
setIsComplete(true)
onComplete?.()
return
}
// 流式内容处理
const processStream = async () => {
const speeds = { slow: 50, normal: 30, fast: 10 }
const delay = speeds[speed]
for await (const chunk of content) {
for (let i = 0; i < chunk.length; i++) {
setDisplayText(prev => prev + chunk[i])
await new Promise(r => setTimeout(r, delay))
}
}
setIsComplete(true)
onComplete?.()
}
processStream()
}, [content])
return (
<div className="streaming-text">
<MarkdownRenderer content={displayText} />
{!isComplete && <CursorBlinker />}
</div>
)
}
// 2.2 思考过程展示组件
interface ThinkingProcessProps {
steps: ThinkingStep[]
isThinking?: boolean
}
interface ThinkingStep {
id: string
type: 'thought' | 'action' | 'observation'
content: string
timestamp: Date
status: 'pending' | 'running' | 'completed' | 'error'
}
const ThinkingProcess: React.FC<ThinkingProcessProps> = ({
steps,
isThinking
}) => {
const [expanded, setExpanded] = useState(false)
return (
<div className="thinking-process">
<div className="header" onClick={() => setExpanded(!expanded)}>
<Icon name={expanded ? 'chevron-down' : 'chevron-right'} />
<span>思考过程</span>
{isThinking && <Spinner />}
</div>
{expanded && (
<div className="steps">
{steps.map(step => (
<div key={step.id} className={`step ${step.type}`}>
<div className="step-icon">
{step.type === 'thought' && '💭'}
{step.type === 'action' && '🔧'}
{step.type === 'observation' && '👁️'}
</div>
<div className="step-content">
<MarkdownRenderer content={step.content} />
<div className="step-time">
{formatTime(step.timestamp)}
</div>
</div>
</div>
))}
</div>
)}
</div>
)
}
// 2.3 引用面板组件
interface CitationPanelProps {
citations: Citation[]
onCitationClick?: (citation: Citation) => void
}
interface Citation {
id: string
content: string
source: string
relevance: number
position: number
}
const CitationPanel: React.FC<CitationPanelProps> = ({
citations,
onCitationClick
}) => {
const [hoveredId, setHoveredId] = useState<string | null>(null)
return (
<div className="citation-panel">
<h4>参考资料 ({citations.length})</h4>
{citations.map(citation => (
<div
key={citation.id}
className={`citation-item ${hoveredId === citation.id ? 'hovered' : ''}`}
onMouseEnter={() => setHoveredId(citation.id)}
onMouseLeave={() => setHoveredId(null)}
onClick={() => onCitationClick?.(citation)}
>
<div className="citation-content">
{citation.content.substring(0, 100)}...
</div>
<div className="citation-meta">
<span className="source">{citation.source}</span>
<span className="relevance">
相关度: {Math.round(citation.relevance * 100)}%
</span>
</div>
</div>
))}
</div>
)
}
// 2.4 函数调用组件
interface FunctionCallingProps {
functions: FunctionDefinition[]
onCall: (functionName: string, args: any) => Promise<any>
isCalling?: boolean
}
interface FunctionDefinition {
name: string
description: string
parameters: JSONSchema
}
const FunctionCalling: React.FC<FunctionCallingProps> = ({
functions,
onCall,
isCalling
}) => {
const [selectedFunction, setSelectedFunction] = useState<string | null>(null)
const [args, setArgs] = useState<Record<string, any>>({})
const handleCall = async () => {
if (!selectedFunction) return
const result = await onCall(selectedFunction, args)
// 处理结果
}
return (
<div className="function-calling">
<select
value={selectedFunction || ''}
onChange={e => setSelectedFunction(e.target.value)}
>
<option value="">选择函数</option>
{functions.map(fn => (
<option key={fn.name} value={fn.name}>
{fn.name} - {fn.description}
</option>
))}
</select>
{selectedFunction && (
<FunctionParameters
definition={functions.find(f => f.name === selectedFunction)!}
value={args}
onChange={setArgs}
/>
)}
<button onClick={handleCall} disabled={isCalling}>
{isCalling ? '调用中...' : '调用函数'}
</button>
</div>
)
}
// 3. 组件库主题系统
interface AIUIKitTheme {
colors: {
primary: string
secondary: string
userMessage: string
assistantMessage: string
thinking: string
error: string
}
typography: {
fontFamily: string
fontSize: {
small: string
medium: string
large: string
}
}
spacing: {
messageGap: string
padding: string
}
animations: {
typing: string
streaming: string
}
}
// 4. 组件库使用示例
const App = () => {
return (
<AIUIKitProvider theme={defaultTheme}>
<ChatContainer>
<MessageList>
{messages.map(msg => (
<MessageItem key={msg.id} message={msg}>
{msg.type === 'assistant' && (
<>
<ThinkingProcess steps={msg.thinking} />
<CitationPanel citations={msg.citations} />
</>
)}
</MessageItem>
))}
</MessageList>
<InputArea>
<RichTextEditor />
<FileUpload onUpload={handleUpload} />
<SendButton onClick={handleSend} />
</InputArea>
</ChatContainer>
</AIUIKitProvider>
)
}
五、AI应用首屏加载优化(含WASM)
问题:在AI应用中,如何优化首屏加载速度,特别是涉及大型WebAssembly模块(如本地向量化模型)时?
AI应用经常需要加载大型WASM模块(如ONNX Runtime、TensorFlow.js),这对首屏性能是巨大挑战。
javascript
// 1. WASM模块加载策略
// 1.1 按需加载 + 预加载提示
class WASMModuleLoader {
constructor() {
this.module = null
this.loadingPromise = null
}
// 预加载(在空闲时)
async preload() {
if (this.loadingPromise) return this.loadingPromise
// 使用requestIdleCallback在空闲时加载
return new Promise((resolve) => {
requestIdleCallback(async () => {
this.loadingPromise = this.load()
await this.loadingPromise
resolve()
})
})
}
// 实际加载
async load() {
// 显示加载进度
this.showProgressBar()
const startTime = performance.now()
try {
// 动态导入WASM模块
const module = await import('@tensorflow/tfjs-core')
// 配置WASM后端
await module.setWasmPath('/wasm/tfjs-backend-wasm.wasm')
await module.ready()
const loadTime = performance.now() - startTime
this.reportMetrics('wasm-load', loadTime)
this.module = module
return module
} catch (error) {
this.handleError(error)
// 降级到CPU版本
return this.loadCPUVersion()
} finally {
this.hideProgressBar()
}
}
}
// 1.2 分片加载
class ChunkedWASMLoader {
async loadChunked() {
// 加载核心模块(最小集)
const core = await this.loadCore()
// 根据功能按需加载
const features = {
embedding: () => this.loadEmbedding(),
classification: () => this.loadClassification(),
generation: () => this.loadGeneration()
}
// 只加载当前需要的功能
const neededFeatures = this.detectNeededFeatures()
for (const feature of neededFeatures) {
await features[feature]()
}
return core
}
}
// 2. 加载UI优化
// 2.1 骨架屏 + 进度指示
const WASMLoadingScreen = () => {
const [progress, setProgress] = useState(0)
const [stage, setStage] = useState('downloading')
useEffect(() => {
const loadWASM = async () => {
// 模拟下载进度
for (let i = 0; i <= 100; i += 10) {
setProgress(i)
await new Promise(r => setTimeout(r, 100))
}
setStage('compiling')
// 实际加载WASM
await loadWASMModule()
setStage('ready')
}
loadWASM()
}, [])
return (
<div className="wasm-loading">
<div className="spinner" />
<div className="progress-bar">
<div className="progress" style={{ width: `${progress}%` }} />
</div>
<div className="stage">
{stage === 'downloading' && '下载AI模型中...'}
{stage === 'compiling' && '编译模型中...'}
{stage === 'ready' && '准备就绪'}
</div>
</div>
)
}
// 2.2 占位交互
const AIChatPlaceholder = () => {
const [isWASMReady, setIsWASMReady] = useState(false)
useEffect(() => {
// 预加载WASM
WASMLoader.preload().then(() => {
setIsWASMReady(true)
})
}, [])
if (!isWASMReady) {
// 占位模式:展示界面但禁用AI功能
return (
<div className="placeholder-mode">
<MessageList messages={demoMessages} />
<InputArea disabled placeholder="AI模型加载中,请稍候..." />
<div className="loading-badge">
正在加载AI能力...
</div>
</div>
)
}
return <FullAIChat />
}
// 3. 资源优化
// 3.1 使用CDN + 压缩
// 配置示例
const wasmConfig = {
url: 'https://cdn.example.com/wasm/model.wasm',
// 使用br/gzip压缩
headers: {
'Accept-Encoding': 'br, gzip'
},
// 预连接
preconnect: 'https://cdn.example.com'
}
// 3.2 缓存策略
// Service Worker缓存WASM
self.addEventListener('fetch', (event) => {
if (event.request.url.includes('.wasm')) {
event.respondWith(
caches.open('wasm-cache').then(cache => {
return cache.match(event.request).then(response => {
return response || fetch(event.request).then(response => {
cache.put(event.request, response.clone())
return response
})
})
})
)
}
})
// 3.3 增量更新
class IncrementalWASMLoader {
async loadWithDiff(baseVersion: string, targetVersion: string) {
// 计算差异
const diff = await this.computeDiff(baseVersion, targetVersion)
// 只下载差异部分
const patch = await fetch(`/wasm/diff/${diff.id}`)
// 应用补丁
return this.applyPatch(patch)
}
}
// 4. 降级策略
// 4.1 设备检测与分级加载
class DeviceCapability {
static detect() {
// 检测WebAssembly支持
const hasWASM = typeof WebAssembly === 'object'
// 检测内存大小
const memory = navigator.deviceMemory || 4
// 检测CPU核心数
const cores = navigator.hardwareConcurrency || 2
return {
hasWASM,
memory,
cores,
tier: this.getTier(hasWASM, memory, cores)
}
}
static getTier(hasWASM: boolean, memory: number, cores: number): 'low' | 'medium' | 'high' {
if (!hasWASM || memory < 2 || cores < 2) return 'low'
if (memory < 4 || cores < 4) return 'medium'
return 'high'
}
}
// 根据设备能力选择加载策略
const loadAIModel = async () => {
const capability = DeviceCapability.detect()
switch (capability.tier) {
case 'low':
// 使用云端API,不加载本地模型
return new CloudAPIAdapter()
case 'medium':
// 加载轻量级模型
return loadLightweightModel()
case 'high':
// 加载完整WASM模型
return loadFullWASMModel()
}
}
// 5. 性能监控
const monitorWASMLoad = () => {
// 使用Performance API监控
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.name.includes('.wasm')) {
console.log('WASM加载耗时:', entry.duration)
// 上报到监控平台
reportMetrics('wasm-load-time', entry.duration)
}
}
})
observer.observe({ entryTypes: ['resource'] })
}
六、Function Calling原理与实现
问题:解释一下Function Calling(函数调用)的原理,前端如何配合模型完成一次完整的工具调用?
Function Calling是大模型与外部世界交互的关键能力,前端需要理解完整的数据流。
typescript
// 1. Function Calling完整流程
// 用户输入 → 模型决策 → 前端执行 → 结果返回 → 模型生成最终回答
// 2. 函数定义(发送给模型)
interface FunctionDefinition {
name: string
description: string
parameters: {
type: 'object'
properties: Record<string, {
type: string
description: string
enum?: string[]
}>
required: string[]
}
}
// 示例:天气查询函数定义
const weatherFunction: FunctionDefinition = {
name: 'get_current_weather',
description: '获取指定城市的当前天气',
parameters: {
type: 'object',
properties: {
city: {
type: 'string',
description: '城市名称,如:北京、上海'
},
unit: {
type: 'string',
enum: ['celsius', 'fahrenheit'],
description: '温度单位'
}
},
required: ['city']
}
}
// 3. 前端Function Calling管理器
class FunctionCallingManager {
private functions: Map<string, FunctionImplementation> = new Map()
// 注册前端可执行的函数
registerFunction(name: string, implementation: FunctionImplementation) {
this.functions.set(name, implementation)
}
// 获取所有函数定义(用于API请求)
getFunctionDefinitions(): FunctionDefinition[] {
return Array.from(this.functions.values()).map(fn => fn.definition)
}
// 执行函数调用
async executeCall(call: FunctionCall): Promise<FunctionCallResult> {
const fn = this.functions.get(call.name)
if (!fn) {
throw new Error(`未找到函数: ${call.name}`)
}
try {
// 参数验证
this.validateArguments(call.arguments, fn.definition)
// 执行函数
const result = await fn.implementation(call.arguments)
return {
callId: call.id,
name: call.name,
result,
success: true
}
} catch (error) {
return {
callId: call.id,
name: call.name,
error: error.message,
success: false
}
}
}
private validateArguments(args: any, definition: FunctionDefinition) {
// 验证必填参数
for (const required of definition.parameters.required) {
if (args[required] === undefined) {
throw new Error(`缺少必填参数: ${required}`)
}
}
}
}
// 4. 完整的对话流程实现
class AIChatWithFunctions {
private functionManager: FunctionCallingManager
private messages: Message[] = []
constructor() {
this.functionManager = new FunctionCallingManager()
this.registerFunctions()
}
private registerFunctions() {
// 注册天气函数
this.functionManager.registerFunction('get_current_weather', {
definition: weatherFunction,
implementation: async (args) => {
// 调用实际天气API
const response = await fetch(`/api/weather?city=${args.city}`)
const data = await response.json()
return {
city: args.city,
temperature: data.temp,
unit: args.unit || 'celsius',
condition: data.condition
}
}
})
// 注册计算器函数
this.functionManager.registerFunction('calculate', {
definition: {
name: 'calculate',
description: '执行数学计算',
parameters: {
type: 'object',
properties: {
expression: {
type: 'string',
description: '数学表达式,如:"2 + 3 * 4"'
}
},
required: ['expression']
}
},
implementation: async (args) => {
// 安全计算(使用eval需谨慎)
const result = this.safeEvaluate(args.expression)
return { expression: args.expression, result }
}
})
}
async sendMessage(userInput: string) {
// 1. 添加用户消息
this.messages.push({ role: 'user', content: userInput })
// 2. 请求模型
let response = await this.callLLM({
messages: this.messages,
functions: this.functionManager.getFunctionDefinitions(),
function_call: 'auto' // 让模型自动决定是否调用
})
// 3. 处理函数调用循环
while (response.function_call) {
// 3.1 执行函数
const result = await this.functionManager.executeCall(response.function_call)
// 3.2 将函数调用和结果添加到消息历史
this.messages.push({
role: 'assistant',
content: null,
function_call: response.function_call
})
this.messages.push({
role: 'function',
name: result.name,
content: JSON.stringify(result.result)
})
// 3.3 再次调用模型,传入函数结果
response = await this.callLLM({
messages: this.messages,
functions: this.functionManager.getFunctionDefinitions()
})
}
// 4. 最终回答
this.messages.push({
role: 'assistant',
content: response.content
})
return response.content
}
private async callLLM(params: any) {
// 调用模型API
const res = await fetch('/api/chat', {
method: 'POST',
body: JSON.stringify(params)
})
return res.json()
}
private safeEvaluate(expression: string): number {
// 使用安全的表达式计算库,如 math.js
// 这里简单实现
return Function('"use strict";return (' + expression + ')')()
}
}
// 5. 前端UI组件集成
const FunctionCallingDemo = () => {
const [chat, setChat] = useState(() => new AIChatWithFunctions())
const [messages, setMessages] = useState<Message[]>([])
const [isCalling, setIsCalling] = useState(false)
const handleSend = async (input: string) => {
setIsCalling(true)
try {
const response = await chat.sendMessage(input)
setMessages(chat.getMessages())
} finally {
setIsCalling(false)
}
}
return (
<div>
<MessageList messages={messages} />
{isCalling && (
<FunctionCallingIndicator
functions={chat.getActiveFunctions()}
/>
)}
<InputArea onSend={handleSend} />
</div>
)
}
// 6. 函数调用安全考虑
class SecureFunctionManager {
// 权限控制
private permissions: Map<string, string[]> = new Map()
// 速率限制
private rateLimits: Map<string, number> = new Map()
async executeWithPermission(call: FunctionCall, userId: string) {
// 检查权限
const allowed = this.checkPermission(call.name, userId)
if (!allowed) {
return { error: '无权限调用此函数' }
}
// 检查速率限制
const rateLimit = this.rateLimits.get(call.name)
if (rateLimit && this.exceedsLimit(call.name, userId, rateLimit)) {
return { error: '调用频率过高,请稍后再试' }
}
// 执行函数
return this.execute(call)
}
// 敏感操作确认
async requireConfirmation(call: FunctionCall): Promise<boolean> {
if (this.isSensitiveOperation(call.name)) {
return await this.showConfirmationDialog({
title: '确认操作',
message: `是否允许执行 ${call.name}?`,
details: call.arguments
})
}
return true
}
}
七、AI生成内容的持久化与多端同步
问题:你们项目中是如何处理AI生成内容的持久化和多端同步的?
AI生成内容(对话记录、生成的文档等)需要可靠的持久化和多端同步能力。
typescript
// 1. 数据结构设计
interface Conversation {
id: string
title: string
createdAt: Date
updatedAt: Date
messages: Message[]
metadata: {
model: string
totalTokens: number
summary?: string
}
syncStatus: 'synced' | 'pending' | 'conflict'
version: number // 用于冲突检测
}
interface Message {
id: string
role: 'user' | 'assistant' | 'system' | 'function'
content: string
timestamp: Date
citations?: Citation[]
thinking?: ThinkingStep[]
function_call?: FunctionCall
syncStatus: 'synced' | 'pending'
}
// 2. 持久化层实现
class AIContentStorage {
private db: IDBDatabase // IndexedDB
private syncQueue: SyncQueue
constructor() {
this.initDB()
this.syncQueue = new SyncQueue()
}
// 初始化IndexedDB
private async initDB() {
return new Promise((resolve, reject) => {
const request = indexedDB.open('AIContentDB', 1)
request.onupgradeneeded = (event) => {
const db = event.target.result
// 对话存储
if (!db.objectStoreNames.contains('conversations')) {
const store = db.createObjectStore('conversations', { keyPath: 'id' })
store.createIndex('updatedAt', 'updatedAt', { unique: false })
store.createIndex('syncStatus', 'syncStatus', { unique: false })
}
// 消息存储
if (!db.objectStoreNames.contains('messages')) {
const store = db.createObjectStore('messages', { keyPath: 'id' })
store.createIndex('conversationId', 'conversationId', { unique: false })
store.createIndex('timestamp', 'timestamp', { unique: false })
}
}
request.onsuccess = () => {
this.db = request.result
resolve()
}
request.onerror = reject
})
}
// 保存对话
async saveConversation(conversation: Conversation): Promise<void> {
const tx = this.db.transaction(['conversations', 'messages'], 'readwrite')
// 保存对话元数据
const convStore = tx.objectStore('conversations')
await convStore.put({
...conversation,
syncStatus: 'pending',
version: (conversation.version || 0) + 1
})
// 保存消息
const msgStore = tx.objectStore('messages')
for (const message of conversation.messages) {
await msgStore.put({
...message,
conversationId: conversation.id,
syncStatus: 'pending'
})
}
await tx.done
// 加入同步队列
this.syncQueue.add(conversation.id)
}
// 加载对话
async loadConversation(id: string): Promise<Conversation | null> {
const tx = this.db.transaction(['conversations', 'messages'], 'readonly')
const convStore = tx.objectStore('conversations')
const conversation = await convStore.get(id)
if (!conversation) return null
const msgStore = tx.objectStore('messages')
const index = msgStore.index('conversationId')
const messages = await index.getAll(id)
return {
...conversation,
messages: messages.sort((a, b) => a.timestamp - b.timestamp)
}
}
}
// 3. 同步队列实现
class SyncQueue {
private queue: string[] = []
private isSyncing = false
add(conversationId: string) {
if (!this.queue.includes(conversationId)) {
this.queue.push(conversationId)
this.process()
}
}
private async process() {
if (this.isSyncing) return
if (this.queue.length === 0) return
this.isSyncing = true
while (this.queue.length > 0) {
const id = this.queue.shift()!
await this.syncConversation(id)
}
this.isSyncing = false
}
private async syncConversation(id: string) {
try {
const conversation = await storage.loadConversation(id)
if (!conversation) return
// 发送到服务器
const response = await fetch(`/api/conversations/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(conversation)
})
if (response.status === 409) {
// 冲突,需要合并
await this.handleConflict(id, await response.json())
} else if (response.ok) {
// 更新本地同步状态
await this.markSynced(id)
}
} catch (error) {
console.error('Sync failed:', error)
// 重新加入队列
this.queue.unshift(id)
}
}
private async handleConflict(id: string, serverVersion: Conversation) {
// 显示冲突解决UI
const resolved = await showConflictResolver(serverVersion, localVersion)
// 使用合并后的版本
await storage.saveConversation(resolved)
// 重新同步
this.add(id)
}
}
// 4. 多端同步的实时性
class RealTimeSync {
private ws: WebSocket
private listeners: Map<string, Function> = new Map()
constructor() {
this.connect()
}
private connect() {
this.ws = new WebSocket('wss://api.example.com/sync')
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data)
this.handleRemoteUpdate(data)
}
this.ws.onclose = () => {
// 断线重连
setTimeout(() => this.connect(), 3000)
}
}
private handleRemoteUpdate(data: any) {
switch (data.type) {
case 'conversation.update':
// 更新本地数据
this.updateLocalConversation(data.conversation)
// 通知UI
this.notifyListeners('conversation.update', data.conversation)
break
case 'message.new':
this.addNewMessage(data.message)
break
}
}
// 广播本地变更
broadcastUpdate(conversationId: string, update: any) {
this.ws.send(JSON.stringify({
type: 'update',
conversationId,
update,
deviceId: this.getDeviceId(),
timestamp: Date.now()
}))
}
}
// 5. 离线支持
class OfflineSupport {
private isOnline = navigator.onLine
constructor() {
window.addEventListener('online', () => this.handleOnline())
window.addEventListener('offline', () => this.handleOffline())
}
async handleMessage(message: Message) {
if (this.isOnline) {
// 在线:直接发送
return await this.sendToServer(message)
} else {
// 离线:存储到本地队列
await this.queueOfflineMessage(message)
return { status: 'queued', message: '已保存,网络恢复后自动发送' }
}
}
private async queueOfflineMessage(message: Message) {
const queue = await this.getOfflineQueue()
queue.push({
message,
timestamp: Date.now(),
retryCount: 0
})
await this.saveOfflineQueue(queue)
}
private async handleOnline() {
this.isOnline = true
// 发送所有离线队列中的消息
const queue = await this.getOfflineQueue()
for (const item of queue) {
try {
await this.sendToServer(item.message)
} catch (error) {
// 重试逻辑
if (item.retryCount < 3) {
item.retryCount++
await this.saveOfflineQueue(queue)
}
}
}
// 清空已发送的队列
await this.clearOfflineQueue()
}
}
八、Web Worker在AI前端中的应用
问题:谈谈Web Worker在AI前端应用中的实际应用场景。
Web Worker是AI前端应用中性能优化的关键工具,可以将计算密集型任务从主线程移出。
typescript
// 1. Worker类型与场景
// 1.1 专用Worker - 处理特定AI任务
// workers/embedding.worker.ts
self.addEventListener('message', async (e) => {
const { texts, model } = e.data
// 加载模型(如果未加载)
if (!self.model) {
self.model = await loadModel(model)
}
// 批量计算向量
const embeddings = []
for (const text of texts) {
const embedding = await self.model.embed(text)
embeddings.push(embedding)
// 报告进度
self.postMessage({
type: 'progress',
current: embeddings.length,
total: texts.length
})
}
// 返回结果
self.postMessage({
type: 'complete',
embeddings
})
})
// 主线程使用
class EmbeddingService {
private worker: Worker
constructor() {
this.worker = new Worker('/workers/embedding.worker.ts')
}
async embed(texts: string[]): Promise<number[][]> {
return new Promise((resolve) => {
this.worker.onmessage = (e) => {
if (e.data.type === 'complete') {
resolve(e.data.embeddings)
}
}
this.worker.postMessage({ texts, model: 'bge-small' })
})
}
}
// 2. 流式处理Worker - 处理流式响应
// workers/streaming.worker.ts
class StreamingProcessor {
private buffer: string = ''
processChunk(chunk: string) {
this.buffer += chunk
// 按句子分割
const sentences = this.buffer.split(/(?<=[。!?.!?])/)
if (sentences.length > 1) {
// 发送完整句子
const complete = sentences.slice(0, -1)
this.buffer = sentences[sentences.length - 1]
return complete
}
return []
}
}
// 3. 文档解析Worker - 处理PDF/Word解析
// workers/document-parser.worker.ts
import * as pdfjs from 'pdfjs-dist'
self.addEventListener('message', async (e) => {
const { file, type } = e.data
try {
switch (type) {
case 'pdf':
const text = await parsePDF(file)
self.postMessage({ type: 'success', text })
break
case 'markdown':
const parsed = await parseMarkdown(file)
self.postMessage({ type: 'success', text: parsed })
break
}
} catch (error) {
self.postMessage({ type: 'error', error: error.message })
}
})
async function parsePDF(file: ArrayBuffer): Promise<string> {
const pdf = await pdfjs.getDocument({ data: file }).promise
let fullText = ''
for (let i = 1; i <= pdf.numPages; i++) {
const page = await pdf.getPage(i)
const textContent = await page.getTextContent()
const pageText = textContent.items.map(item => item.str).join(' ')
fullText += pageText + '\n\n'
// 报告进度
self.postMessage({
type: 'progress',
current: i,
total: pdf.numPages
})
}
return fullText
}
// 4. 向量检索Worker - 本地相似度计算
// workers/vector-search.worker.ts
class VectorSearchEngine {
private vectors: Float32Array[]
private metadata: any[]
constructor(vectors: Float32Array[], metadata: any[]) {
this.vectors = vectors
this.metadata = metadata
}
// 余弦相似度计算
search(queryVector: Float32Array, topK: number = 10): SearchResult[] {
const scores = this.vectors.map((vec, idx) => ({
index: idx,
score: this.cosineSimilarity(queryVector, vec),
metadata: this.metadata[idx]
}))
return scores
.sort((a, b) => b.score - a.score)
.slice(0, topK)
}
private cosineSimilarity(a: Float32Array, b: Float32Array): number {
let dot = 0, normA = 0, normB = 0
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i]
normA += a[i] * a[i]
normB += b[i] * b[i]
}
return dot / (Math.sqrt(normA) * Math.sqrt(normB))
}
}
// 5. 批量处理Worker - 并行处理多个任务
// workers/batch-processor.worker.ts
class BatchProcessor {
private queue: Task[] = []
private processing = false
addTask(task: Task) {
this.queue.push(task)
this.process()
}
private async process() {
if (this.processing || this.queue.length === 0) return
this.processing = true
while (this.queue.length > 0) {
const batch = this.queue.splice(0, 5) // 批量处理
const results = await Promise.all(
batch.map(task => this.executeTask(task))
)
// 返回批量结果
self.postMessage({
type: 'batch',
results
})
}
this.processing = false
}
private async executeTask(task: Task): Promise<any> {
// 执行具体任务
return task.execute()
}
}
// 6. 主线程使用示例
class AIApplication {
private embeddingWorker: Worker
private parserWorker: Worker
private searchWorker: Worker
constructor() {
this.initWorkers()
}
private initWorkers() {
// 向量化Worker
this.embeddingWorker = new Worker('/workers/embedding.worker.js')
this.embeddingWorker.onmessage = (e) => {
if (e.data.type === 'complete') {
console.log('向量化完成:', e.data.embeddings)
}
}
// 文档解析Worker
this.parserWorker = new Worker('/workers/document-parser.worker.js')
this.parserWorker.onmessage = (e) => {
if (e.data.type === 'progress') {
console.log(`解析进度: ${e.data.current}/${e.data.total}`)
} else if (e.data.type === 'success') {
console.log('文档解析完成:', e.data.text)
}
}
// 向量检索Worker
this.searchWorker = new Worker('/workers/vector-search.worker.js')
}
async processDocument(file: File) {
// 在Worker中解析文档
this.parserWorker.postMessage({
file: await file.arrayBuffer(),
type: file.type.includes('pdf') ? 'pdf' : 'markdown'
})
}
async search(query: string) {
// 先在主线程做轻量处理
const queryEmbedding = await this.getEmbeddingLight(query)
// 在Worker中做重计算
this.searchWorker.postMessage({
type: 'search',
queryVector: queryEmbedding,
topK: 10
})
}
}
// 7. Worker生命周期管理
class WorkerPool {
private workers: Worker[] = []
private availableWorkers: number[] = []
private taskQueue: Task[] = []
constructor(poolSize: number = navigator.hardwareConcurrency || 4) {
for (let i = 0; i < poolSize; i++) {
const worker = new Worker('/workers/ai-worker.js')
this.workers.push(worker)
this.availableWorkers.push(i)
worker.onmessage = (e) => {
// 处理结果
this.handleResult(e.data)
// 回收Worker
this.availableWorkers.push(i)
this.processQueue()
}
}
}
private processQueue() {
if (this.taskQueue.length === 0) return
if (this.availableWorkers.length === 0) return
const task = this.taskQueue.shift()!
const workerId = this.availableWorkers.shift()!
const worker = this.workers[workerId]
worker.postMessage(task.data)
}
submit(task: Task) {
this.taskQueue.push(task)
this.processQueue()
}
}
// 8. 性能监控
const monitorWorkerPerformance = () => {
// 使用Performance API监控Worker
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.entryType === 'worker') {
console.log('Worker执行时间:', entry.duration)
// 上报到监控平台
reportMetrics('worker-execution-time', entry.duration)
}
}
})
observer.observe({ entryTypes: ['worker'] })
}
📚 知识点速查表
| 知识点 | 核心要点 |
|---|---|
| 长列表优化 | 虚拟滚动、消息缓存、滚动节流、内存限制 |
| RAG前端链路 | 文档上传、智能分块、批量向量化、进度反馈、中断控制 |
| Prompt工程化 | 模板管理、版本控制、注入防护、A/B测试、监控日志 |
| AI组件库 | 流式文本、思考过程、引用面板、函数调用、主题系统 |
| WASM加载优化 | 预加载、分片加载、骨架屏、设备降级、缓存策略 |
| Function Calling | 函数定义、调用循环、权限控制、速率限制、安全确认 |
| 持久化同步 | IndexedDB、同步队列、冲突解决、离线支持、实时广播 |
| Web Worker | 向量计算、文档解析、流式处理、Worker池、性能监控 |
📌 最后一句:
阿里云这场AI应用开发二面,从工程化架构到性能优化,从组件设计到底层原理,每个问题都在考察你是否具备构建生产级AI应用 的能力。候选人感觉"不错但没后续",可能的原因是在某个环节的深度或系统性上还有欠缺。AI前端开发,不只是调用API,更是对工程化、性能、安全、体验的综合考量。技术深度决定你能走多快,工程化思维决定你能走多远。