Intro
网上到处可见各种引流的应用。
这些应用大部分还是非常不稳定的,界面和交互粗制滥造,可居然有些还要收费体验。毕竟能蹭流量赚点钱,还是很多人愿意的,也不知道有多少人是付费使用API的。
最近连微软也要把ChatGPT加入到搜索引擎中了,New Bing什么的。这样的关注量,利益驱动,或许真的能大大加快人工智能的发展吧!
我也尝试在博客中引入一下,效果如:openai-playground
准备工作
挂到后端服务
以 eggjs 为例。服务部署过程从略。
安装好 eggjs 后,再安装一下 openapi
:
bash
npm install openapi
主要的代码如下:
javascript
// ~/router.js
module.exports = (app) => {
const { router, controller } = app;
router.post('/chat', controller.home.chat);
};
javascript
// ~/controller/home.js
const { Controller } = require('egg');
class HomeController extends Controller {
async chat() {
const { service, request } = this.ctx;
const { words } = request.body;
const res = await service.openai.chat(words);
this.ctx.body = res;
}
}
module.exports = HomeController;
javascript
// ~/service/github.js
const { Service } = require('egg');
const { Configuration, OpenAIApi } = require('openai');
class ChatService extends Service {
async chat(prompt = '') {
// ~/config 配置文件内容从略
const { open_api_key } = this.config;
const configuration = new Configuration({
apiKey: open_api_key,
});
const openai = new OpenAIApi(configuration);
// 以下可参考官方不同的样例代码
// `max_tokens` 越大,答案最大长度最长,免费账户或付费账户的钱花得越快
// 可是太小了,答案往往没有说完就戛然而止
try {
const completion = await openai.createCompletion({
model: 'text-davinci-003',
prompt,
temperature: 0.9,
max_tokens: 500,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0.6,
stop: [' Human:', ' AI:'],
});
return completion.data.choices[0].text;
} catch (error) {
if (error.response) {
return error.response.status;
}
return '';
}
}
}
module.exports = ChatService;
引入到VitePress
服务搭建好后,就着手搞前端的调用。
先写好调用 eggjs 服务的方法:
typescript
//~/openai.ts
import axios from 'axios';
const baseURL = 'xxxxx'; // 这里是 eggjs 所在的地址`
const axiosService = axios.create({ baseURL });
// 默认有一段引入语,要不然空空的也不便开始使用
export const DEFAULT_CHAT = 'Human:你叫什么名字?\nAI:';
// 生成对话
export const generateChat = async (words: string) => {
const url = '/chat';
const res = await axiosService({ method: 'post', url, data: { words } });
if (res && res.data) {
return `${words}${res.data}\n\nHuman:`;
}
return words;
};
将主要的页面放到一个组件中:
vue
<script setup>
import { ref } from 'vue';
import { generateChat, DEFAULT_CHAT } from '../openai.ts';
const chat = ref(DEFAULT_CHAT);
const send = async () => chat.value = await generateChat(chat.value);
const input = ({ target }) => (chat.value = target.value);
const reset = () => (chat.value = DEFAULT_CHAT);
</script>
<template>
<div class="wrapper">
<textarea :value="chat" @input="input" placeholder="基于 ChatGPT API 的聊天程序" />
</div>
<div class="toolbar">
<span class="letters">{{ chat.length || 0 }}</span>
<button @click="send" class="send">Send</button>
<button @click="reset">Reset</button>
</div>
</template>
<style scoped>
/**样式从略 */
</style>
随意新建个md文档,引入前面做好的调用组件:
vue
---
title: ChatGPT Playground
---
<script setup>
import OpenAI from '../.vitepress/components/OpenAI.vue'
</script>
<Suspense>
<OpenAI />
</Suspense>
这里我使用的是默认的 docs
布局,当然你也可以选用没有边框,或者特殊的布局,甚至空页面。由于组件含异步调用,故使用 Suspense
包裹着。
以上。