最近想实现个人的应用调用gpt,并返回内容

一开始想尝试本地部署大模型,再使用对应API,在查看了各个模型需求的配置后

感觉自己的电脑有些吃力,就选择调用现有大模型的API来使用

因为个人的水平选择了百度千帆大模型平台(该平台提供了Nodejs版本的SDK)

Node.js SDK文档

@baiducloud/qianfan - npm (npmjs.com)

要实现原版gpt的打字机效果等,最好还是使用流式输出以及websocket

chat.gateway.ts

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
import { ChatCompletion, setEnvVariable } from "@baiducloud/qianfan";
import { ConnectedSocket, MessageBody, SubscribeMessage, WebSocketGateway, WebSocketServer } from '@nestjs/websockets';
import * as WebSocket from 'ws';

// 使用安全认证AK/SK鉴权,通过环境变量初始化;
setEnvVariable('QIANFAN_ACCESS_KEY', '自己的AK');
setEnvVariable('QIANFAN_SECRET_KEY', '自己的SK');

// websocket端口
@WebSocketGateway(4000)
export class ChatGateWay {
private client = null

constructor() {
this.client = new ChatCompletion();
}
@SubscribeMessage('chat')
// 订阅消息
async chat(@MessageBody() data, @ConnectedSocket() client: WebSocket) {
// 输入到千帆大模型
const stream = await this.client.chat({
messages: [
{
role: 'user',
content: data,
},
],
stream: true
}, 'ERNIE-3.5-8K');
console.log(data)
client.send(JSON.stringify({ event: 'start', data: 1 }));
for await (const chunk of stream as AsyncIterableIterator<any>) {
// 流式输出并发布消息
client.send(JSON.stringify({ event: 'msg', data: JSON.stringify(chunk) }));
}
client.send(JSON.stringify({ event: 'end', data: 1 }));
}
}

ws.adapter.ts

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import * as WebSocket from 'ws';
import { WebSocketAdapter, INestApplicationContext } from '@nestjs/common';
import { MessageMappingProperties } from '@nestjs/websockets';
import { Observable, fromEvent, EMPTY } from 'rxjs';
import { mergeMap, filter } from 'rxjs/operators';

export class WsAdapter implements WebSocketAdapter {

constructor(private app: INestApplicationContext) { }

create(port: number, options: any = {}): any {
console.log('ws create')
return new WebSocket.Server({ port, ...options });
}

bindClientConnect(server, callback: Function) {
// console.log('ws bindClientConnect, server:\n', server);
server.on('connection', callback);
}

bindMessageHandlers(
client: WebSocket,
handlers: MessageMappingProperties[],
process: (data: any) => Observable<any>,
) {
// console.log('[waAdapter]有新的连接进来')
fromEvent(client, 'message')
.pipe(
mergeMap(data => this.bindMessageHandler(client, data, handlers, process)),
filter(result => result),
)
.subscribe(response => client.send(JSON.stringify(response)));
}

bindMessageHandler(
client: WebSocket,
buffer,
handlers: MessageMappingProperties[],
process: (data: any) => Observable<any>,
): Observable<any> {
let message = null;
console.log(buffer.data)
try {
message = JSON.parse(buffer.data);
} catch (error) {
console.log('ws解析json出错', error);
return EMPTY;
}

const messageHandler = handlers.find(
handler => handler.message === message.event,
);
if (!messageHandler) {
return EMPTY;
}
return process(messageHandler.callback(message.data));
}

close(server) {
console.log('ws server close');
server.close();
}
}

main.ts 使用适配器

1
app.useWebSocketAdapter(new WsAdapter(app));

效果图