第34章 React与AI
Chapter-34 - React 与 AI
34.1 AI API 集成
34.1.1 OpenAI API 的基本调用
React + AI 可以做什么? 这是个开放问题,答案很多:
- AI 聊天机器人:像 ChatGPT 一样的对话界面
- 内容生成:输入标题 AI 生成文章、输入描述生成图片
- 智能客服:理解用户问题,自动回复或转人工
- 代码助手:解释代码、debug、生成代码
- 多模态:输入图片+文字,AI 理解图片内容
本质上,AI API 让 React 应用有了"理解"和"生成"的能力——不只是展示静态内容,而是能对话、能思考、能创造。
下面来看怎么接入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| import OpenAI from 'openai'
const openai = new OpenAI({
apiKey: import.meta.env.VITE_OPENAI_API_KEY
})
async function generateText(prompt) {
const response = await openai.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
max_tokens: 500
})
return response.choices[0].message.content
}
|
34.1.2 Anthropic Claude API 集成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| async function chatWithClaude(messages) {
const response = await fetch('https://api.anthropic.com/v1/messages', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': import.meta.env.VITE_ANTHROPIC_API_KEY,
'anthropic-version': '2023-06-01'
},
body: JSON.stringify({
model: 'claude-3-sonnet',
max_tokens: 1024,
messages
})
})
return response.json()
}
|
34.1.3 流式响应(Streaming):Server-Sent Events
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
| async function* streamChat(prompt) {
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${import.meta.env.VITE_OPENAI_API_KEY}`
},
body: JSON.stringify({
model: 'gpt-4',
messages: [{ role: 'user', content: prompt }],
stream: true
})
})
const reader = response.body.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
const chunk = decoder.decode(value)
const lines = chunk.split('\n')
for (const line of lines) {
if (line.startsWith('data: ')) {
const data = line.slice(6)
if (data !== '[DONE]') {
yield JSON.parse(data).choices[0].delta.content
}
}
}
}
}
|
34.2 React 中的 AI 集成
34.2.1 流式响应的 React 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
| import { useState } from 'react'
// streamChat 是 34.1.3 节定义的生成器函数
// import { streamChat } from './api/chat'
function Chat() {
const [messages, setMessages] = useState([])
const [input, setInput] = useState('')
const [streaming, setStreaming] = useState(false)
async function handleSubmit(e) {
e.preventDefault()
if (!input.trim()) return
setStreaming(true)
setMessages(prev => [...prev, { role: 'user', content: input }])
setInput('')
const response = []
for await (const chunk of streamChat(input)) {
response.push(chunk)
// 每次收到新的 chunk,就更新最后一条消息(打字机效果)
setMessages(prev => {
const last = prev[prev.length - 1]
return [...prev.slice(0, -1), { role: 'assistant', content: response.join('') }]
})
}
setStreaming(false)
}
return (
<form onSubmit={handleSubmit}>
<div className="messages">
{messages.map((m, i) => (
<div key={i} className={m.role}>{m.content}</div>
))}
</div>
<input value={input} onChange={e => setInput(e.target.value)} disabled={streaming} />
<button type="submit" disabled={streaming}>发送</button>
</form>
)
}
|
34.2.2 AI 对话组件的设计
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| function AIChatbot() {
const [messages, setMessages] = useState([])
const [isLoading, setIsLoading] = useState(false)
async function sendMessage(content) {
setIsLoading(true)
setMessages(prev => [...prev, { role: 'user', content }])
try {
const response = await generateText(content)
setMessages(prev => [...prev, { role: 'assistant', content: response }])
} catch (error) {
setMessages(prev => [...prev, { role: 'error', content: '请求失败' }])
}
setIsLoading(false)
}
return <ChatInterface messages={messages} onSend={sendMessage} isLoading={isLoading} />
}
|
34.2.3 多模态输入:图片 + 文本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| async function multimodal(input, imageBase64) {
const response = await openai.chat.completions.create({
model: 'gpt-4-vision-preview',
messages: [{
role: 'user',
content: [
{ type: 'text', text: input },
{ type: 'image_url', image_url: { url: `data:image/jpeg;base64,${imageBase64}` }}
]
}]
})
return response.choices[0].message.content
}
|
34.3 前端 prompt 工程
34.3.1 Prompt 模板设计
Prompt 工程不是 AI 领域独有的概念——在前端场景中,它本质上是你给 AI 设定"行为规则"和"上下文"的方式。常见的做法是设计一个 systemPrompt(系统提示词)作为"首席指挥官",再把用户问题拼在后面发给 AI。
1
2
3
4
5
6
| const systemPrompt = `你是一个专业的React开发助手。
请用简洁的语言回答问题,并在适当时机给出代码示例。`
async function ask(question) {
return generateText(`${systemPrompt}\n\n用户问题:${question}`)
}
|
34.3.2 Few-shot 示例
Few-shot(少样本)是一种让 AI"照着例子学"的技巧——在提示词里给几个输入-输出示例,AI 会模仿这些示例的风格或逻辑来回答。适合任务格式固定但变化多端的场景(如翻译、分类、格式化输出)。
1
2
3
4
5
6
7
8
| const fewShotPrompt = `将以下英语翻译成中文:
示例:
输入:Hello, world!
输出:你好,世界!
输入:The quick brown fox jumps over the lazy dog.
输出:`
|
本章小结
本章我们探索了 React 与 AI 的结合:
- AI API 集成:OpenAI API、Anthropic Claude API 的基本调用
- 流式响应:Server-Sent Events 实现打字机效果
- React 中的 AI 集成:聊天组件设计、流式响应实现
- Prompt 工程:系统提示词、Few-shot 示例
AI 时代,React 与 AI 的结合是大势所趋!下一章我们将学习 跨平台桌面开发!🖥️