搭建服务器
刀刀
0字
0分钟
2026/8/17
前言
前端虽然可以直接请求大模型接口,但存在以下问题:
- API Key 写在前端容易暴露
- 无法鉴权和拦截攻击
- 后续操作如定义工具、MCP 等无法进行
OpenAI 库
主流编程语言都有专门调用 AI 接口的库,且基本遵循同一套标准。如 Node.js 的 OpenAI 库。
js
const express = require('express')
const cors = require('cors')
const OpenAI = require('openai') // 专门用来按标准请求大模型接口的一个sdk库
const app = express()
app.use(cors())
const openai = new OpenAI({
apiKey: 'sk-xxxxxx',
baseURL: 'xxx',
})
app.get('/llm', async (req, res) => {
const keyword = req.query.keyword
const aiRes = await openai.chat.completions.create({
model: '',
messages: [{ role: 'user', content: keyword }],
})
res.json(aiRes.choices[0].message.content)
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})详解 OpenAI
- OpenAI 库使用的地址通常与直接 HTTP 请求不同
- OpenAI 库相对于 HTTP 请求,提供了规范,更便于使用 Function Call 及 MCP 接入,代码更简洁,优先选用。此外还提供其他方法用于其他场景,等同于一个专门用来请求大模型接口的 SDK
- OpenAI 库请求接口本质上仍用
fetch发送 HTTP 请求,可拦截其发出的 HTTP 请求和响应
重写 fetch 查看请求和响应
js
const express = require('express')
const cors = require('cors')
const OpenAI = require('openai') // 专门用来按标准请求大模型接口的一个sdk库
const app = express()
app.use(cors())
// 重写 fetch,让整个项目通过 fetch 发请求时会打印一些东西
const originalFetch = global.fetch
global.fecth = async function (...args) {
const [url, options = {}] = args
console.log('fetching', url, options)
try {
const response = await originalFetch.apply(this, args) // 调用原始 fetch
const clonedResponse = response.clone() // 克隆响应以便读取body而不影响原始响应
for (const [key, value] of Object.entries(options.headers)) {
console.log(`${key}: ${value}`)
}
const result = await clonedResponse.json() // 尝试读取响应体
return response
} catch (error) {
console.error(`Error: ${error}`)
}
}
const openai = new OpenAI({
apiKey: 'sk-xxxxxx',
baseURL: 'xxx',
})
app.get('/llm', async (req, res) => {
const keyword = req.query.keyword
const aiRes = await openai.chat.completions.create({
model: '',
messages: [{ role: 'user', content: keyword }],
})
res.json(aiRes.choices[0].message.content)
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})携带历史
接口是无状态的,每次请求携带上下文有助于模型理解用户意图。实现一个简单的携带历史功能。
js
const express = require('express')
const cors = require('cors')
const OpenAI = require('openai') // 专门用来按标准请求大模型接口的一个sdk库
const app = express()
app.use(cors())
// 重写 fetch,让整个项目通过 fetch 发请求时会打印一些东西
const originalFetch = global.fetch
global.fecth = async function (...args) {
const [url, options = {}] = args
console.log('fetching', url, options)
try {
const response = await originalFetch.apply(this, args) // 调用原始 fetch
const clonedResponse = response.clone() // 克隆响应以便读取body而不影响原始响应
for (const [key, value] of Object.entries(options.headers)) {
console.log(`${key}: ${value}`)
}
const result = await clonedResponse.json() // 尝试读取响应体
return response
} catch (error) {
console.error(`Error: ${error}`)
}
}
const messageList = [] // 存储历史消息
const openai = new OpenAI({
apiKey: 'sk-xxxxxx',
baseURL: 'xxx',
})
app.get('/llm', async (req, res) => {
const keyword = req.query.keyword
const queryObj = {
role: 'user',
content: keyword,
}
messageList.push(queryObj) // 每次提问保存上下文
const aiRes = await openai.chat.completions.create({
model: '',
messages: messageList,
})
messageList.push(aiRes.choices[0].message) // 每次回答保存上下文
res.json(aiRes.choices[0].message.content)
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})总结
