- 作者:老汪软件技巧
- 发表时间:2024-11-12 21:03
- 浏览量:
大家好,我是双越老师,也是 wangEditor 作者。
今年我致力于开发一个 Node 全栈 AIGC 知识库项目划水AI,包括 AI 写作、多人协同编辑。复杂业务,真实上线,大家可以去注册试用。
今天和大家分享一下 划水AI 是如何开发 AI 编辑器,其中遇到了哪些问题,做了哪些优化。
没那么简单
谈论到 AIGC、 AI 应用场景的话题,很多人都会抬高鼻子说话:不就调调接口吗,有什么技术含量吗?
研发发动机的有技术含量,把发动机装配到汽车上并调教好的,也同样有很高的技术含量。只是不同的领域而已。
借助 AI 服务开发一个 AI 编辑器,这并不简单。首先富文本编辑器就挺麻烦,再集成 AI 功能就更麻烦,例如
具体的可以去 划水AI 注册试用一下,如遇到问题可提交 issue ,我们也在不断的优化改进中。
看完这几个问题,也许你能体会到:这个工作说不上多难,但它的使用场景足够复杂 —— 这其实很像我们日常工作中的项目,并不是多难多深,但业务场景很麻烦。
而我们在公司中的价值就是:使用技术手段解决复杂的业务场景和功能,而不是深挖内部和原理。
你就是熟读 V8 引擎源码,只要你去找工作,你每天也就是增删改查,并拿着相应的工资。除非你有能力自己创业。
设计了哪些功能?AI 生成文本
如文章一开始的 gif 动图,输入指令(或点击一个菜单)根据当前文章的标题和内容,让 AI 帮你写一段文字。
你可以写大纲、头脑风暴。或针对一篇已有的文章,续写、写总结。
AI 处理文本
如下图,选中一段文字,让 AI 帮你处理、优化并生成新的版本。例如让 AI 扩展、简化、翻译、切换语气等。
前几天我和一个同学评审简历,他对于工作职责不会写,我就随便写了一句话,然后选中,让 AI 帮我扩展。这样他就可以根据扩展出来的内容来写、甚至面试的时候可以根据这些来表达。
未来扩展
AI 是一个可想象空间非常大的方向。现在 划水AI 处理文本,未来可以借助 AI 的能力来处理图片、视频、文档等。
可用的 AI 接口服务
几个月前我刚开始调研时写过一篇文章 用 Node.js 调用 ChatGPT API 实现 Stream 流式聊天效果
聊天,相比于编辑器,实现起来是比较简单的,所以这里更多的是调研如何使用 AI 接口,当时 ChatGPT 还没有对国内禁用服务。
但后来 OpenAI 禁止国内访问他们的 API 服务,但我们可以借助中转服务,例如 Deepbricks ,使用方法和 ChatGPT 是一样的,价格也足够便宜。
import OpenAI from 'openai'
const openai = new OpenAI({ apiKey: 'xxxxxxxxxxxx' })
async function main() {
const completion = await openai.chat.completions.create({
messages: [{ role: 'user', content: 'How are you today?' }], // 消息内容
model: 'gpt-3.5-turbo',
max_tokens: 20, // 限制返回字符,帮你节省额度
})
const result = completion.choices[0]
console.log('result: ', result)
}
main()
鉴权和计算 token
如下图,请求 AI 接口时需要携带 token ,但如果你的 token 被泄漏了或者被调用了怎么办?虽然 token 可以设置 timeout 但如果多次泄漏呢?
我当时被这个问题困扰很久,后来考虑到一个非常简单的方法:token 中加密 userId ,然后用 userId 对应 token 使用量,再配合 timeout 就不会有这个问题了。
所以,在发送请求时需要加密 token ,包含 time 和 userId
// join token
const dt = Date.now()
const content = { dt, userId: user.id }
const token = CryptoJS.AES.encrypt(JSON.stringify(content), AUTH_KEY).toString()
url.searchParams.set('x-auth-token', token) // Add auth token
在 AI 服务中使用同样的 secret 解密 token ,解密失败就返回 error
// decrypt token
const authTokenRaw = query['x-auth-token'] || ''
const tokenInfo = decryptToken(authTokenRaw)
if (tokenInfo == null || !tokenInfo.userId) {
const errMsg = 'invalid token'
console.log('error: ', errMsg)
ctx.res.write(`data: [ERROR]${errMsg}\n\n`) // 格式必须是 `data: xxx\n\n` !!!
return
}
// console.log('tokenInfo.... ', tokenInfo)
然后拿 userId 去查询是否还有使用量,如何达到 limit 就要报错提示。
// check token usage
const { userId } = tokenInfo
const usage = await getTokenUsage(userId)
// console.log('usage: ', usage)
if (usage == null) {
const errMsg = 'token usage not found'
console.log('error: ', errMsg)
ctx.res.write(`data: [ERROR]${errMsg}\n\n`)
return
}
const { tokensLimit, totalTokens } = usage
if (tokensLimit <= 0) {
const errMsg = 'token usage limit exceeded'
console.log('error: ', errMsg)
ctx.res.write(`data: [ERROR]${errMsg}\n\n`)
return
}
所以,虽然是调用第三方的 AI 服务,但在实际使用的时候会有很多情况,需要设计和实现。
最后
我在开发 划水AI 时候记录了详细的研发过程,包括调研、设计、代码修改记录、测试用例等,还有遇到的各种问题 bug 、调研、思考、修改过程。有兴趣的同学可私聊我。