Skip to content

Commit b53b8bd

Browse files
committed
✨ feat: 支持其它 AI 模型
1 parent e119e74 commit b53b8bd

File tree

8 files changed

+105
-84
lines changed

8 files changed

+105
-84
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"displayName": "lowcode",
44
"description": "lowcode tool, support ChatGPT",
55
"author": "wjkang <[email protected]>",
6-
"version": "1.7.7",
6+
"version": "1.7.8",
77
"icon": "asset/icon.png",
88
"publisher": "wjkang",
99
"repository": "https://github.com/lowcoding/lowcode-vscode",
@@ -30,6 +30,9 @@
3030
"ChatGPT",
3131
"openai",
3232
"GPT",
33+
"Gemini",
34+
"LLM",
35+
"AI",
3336
"yapi",
3437
"yapi to ts",
3538
"typescript to json",

src/commands/runSnippetScript.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getSnippets } from '../utils/materials';
55
import { getEnv, rootPath } from '../utils/vscodeEnv';
66
import { getInnerLibs } from '../utils/lib';
77
import { getOutputChannel } from '../utils/outputChannel';
8-
import { createChatCompletionForScript } from '../utils/openai';
8+
import { createChatCompletionForScript } from '../utils/llm';
99
import { getClipboardImage } from '../utils/clipboard';
1010
import { formatPath } from '../utils/platform';
1111

src/utils/generate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { getInnerLibs } from './lib';
1818
import { getOutputChannel } from './outputChannel';
1919
import { getLastActiveTextEditor } from '../context';
2020
import { getSyncFolder } from './config';
21-
import { createChatCompletionForScript } from './openai';
21+
import { createChatCompletionForScript } from './llm';
2222

2323
export const genCodeByBlock = async (data: {
2424
material: string;

src/utils/llm.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import * as path from 'path';
2+
import * as fs from 'fs-extra';
3+
import { createChatCompletion as openaiCreateChatCompletion } from './openai';
4+
import { emitter } from './emitter';
5+
import { getSyncFolder } from './config';
6+
import { showChatGPTView } from '../webview';
7+
8+
const LLMScript: {
9+
createChatCompletion?: (options: {
10+
messages: { role: 'system' | 'user' | 'assistant'; content: string }[];
11+
handleChunk?: (data: { text?: string; hasMore: boolean }) => void;
12+
}) => Promise<string>;
13+
} = {};
14+
15+
const syncFolder = getSyncFolder();
16+
17+
if (syncFolder) {
18+
const scriptFile = path.join(syncFolder, 'llm/index.js');
19+
if (fs.existsSync(scriptFile)) {
20+
delete eval('require').cache[eval('require').resolve(scriptFile)];
21+
const script = eval('require')(scriptFile);
22+
if (script.createChatCompletion) {
23+
LLMScript.createChatCompletion = script.createChatCompletion;
24+
}
25+
}
26+
}
27+
28+
export const createChatCompletion = async (options: {
29+
messages: { role: 'system' | 'user' | 'assistant'; content: string }[];
30+
handleChunk?: (data: { text?: string; hasMore: boolean }) => void;
31+
}) => {
32+
if (LLMScript.createChatCompletion) {
33+
const res = await LLMScript.createChatCompletion({
34+
messages: options.messages,
35+
handleChunk: (data) => {
36+
if (options.handleChunk) {
37+
options.handleChunk(data);
38+
emitter.emit('chatGPTChunck', data);
39+
}
40+
},
41+
});
42+
emitter.emit('chatGPTComplete', res);
43+
return res;
44+
}
45+
const res = await openaiCreateChatCompletion({
46+
messages: options.messages,
47+
handleChunk: (data) => {
48+
if (options.handleChunk) {
49+
options.handleChunk(data);
50+
emitter.emit('chatGPTChunck', data);
51+
}
52+
},
53+
});
54+
emitter.emit('chatGPTComplete', res);
55+
return res;
56+
};
57+
58+
export const createChatCompletionForScript = (options: {
59+
messages: { role: 'system' | 'user' | 'assistant'; content: string }[];
60+
handleChunk?: (data: { text?: string; hasMore: boolean }) => void;
61+
showWebview?: boolean;
62+
}) => {
63+
if (!options.showWebview) {
64+
return createChatCompletion({
65+
messages: options.messages,
66+
handleChunk: options.handleChunk,
67+
});
68+
}
69+
// 打开 webview,使用 emitter 监听结果,把结果回传给 script
70+
showChatGPTView({
71+
task: {
72+
task: 'askChatGPT',
73+
data: options.messages.map((m) => m.content).join('\n'),
74+
},
75+
});
76+
return new Promise<string>((resolve) => {
77+
emitter.on('chatGPTChunck', (data) => {
78+
if (options.handleChunk) {
79+
options.handleChunk(data);
80+
}
81+
});
82+
emitter.on('chatGPTComplete', (data) => {
83+
resolve(data);
84+
emitter.off('chatGPTChunck');
85+
emitter.off('chatGPTComplete');
86+
});
87+
});
88+
};

src/utils/openai.ts

Lines changed: 9 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,25 @@
11
import * as https from 'https';
22
import { TextDecoder } from 'util';
33
import { getChatGPTConfig } from './config';
4-
import { emitter } from './emitter';
54
import { showChatGPTView } from '../webview';
65

76
export const createChatCompletion = (options: {
8-
apiKey: string;
9-
model: string;
10-
maxTokens: number;
11-
hostname?: string;
12-
apiPath?: string;
137
messages: { role: 'system' | 'user' | 'assistant'; content: string }[];
148
handleChunk?: (data: { text?: string; hasMore: boolean }) => void;
159
}) =>
16-
new Promise<string>((resolve, reject) => {
10+
new Promise<string>((resolve) => {
1711
let combinedResult = '';
1812
let error = '发生错误:';
13+
const config = getChatGPTConfig();
1914
const request = https.request(
2015
{
21-
hostname: options.hostname || 'api.openai.com',
16+
hostname: config.hostname || 'api.openai.com',
2217
port: 443,
23-
path: options.apiPath || '/v1/chat/completions',
18+
path: config.apiPath || '/v1/chat/completions',
2419
method: 'POST',
2520
headers: {
2621
'Content-Type': 'application/json',
27-
Authorization: `Bearer ${options.apiKey}`,
22+
Authorization: `Bearer ${config.apiKey}`,
2823
},
2924
},
3025
(res) => {
@@ -47,7 +42,6 @@ export const createChatCompletion = (options: {
4742
if (element.includes('[DONE]')) {
4843
if (options.handleChunk) {
4944
options.handleChunk({ hasMore: true, text: '' });
50-
emitter.emit('chatGPTChunck', { hasMore: true, text: '' });
5145
}
5246
return;
5347
}
@@ -56,7 +50,6 @@ export const createChatCompletion = (options: {
5650
if (data.finish_reason === 'stop') {
5751
if (options.handleChunk) {
5852
options.handleChunk({ hasMore: true, text: '' });
59-
emitter.emit('chatGPTChunck', { hasMore: true, text: '' });
6053
}
6154
return;
6255
}
@@ -67,10 +60,6 @@ export const createChatCompletion = (options: {
6760
text: openaiRes.replaceAll('\\n', '\n'),
6861
hasMore: true,
6962
});
70-
emitter.emit('chatGPTChunck', {
71-
text: openaiRes.replaceAll('\\n', '\n'),
72-
hasMore: true,
73-
});
7463
}
7564
combinedResult += openaiRes;
7665
}
@@ -80,10 +69,6 @@ export const createChatCompletion = (options: {
8069
hasMore: true,
8170
text: element,
8271
});
83-
emitter.emit('chatGPTChunck', {
84-
hasMore: true,
85-
text: element,
86-
});
8772
}
8873
return;
8974
}
@@ -102,12 +87,9 @@ export const createChatCompletion = (options: {
10287
hasMore: true,
10388
text: e.toString(),
10489
});
105-
emitter.emit('chatGPTChunck', {
106-
hasMore: true,
107-
text: e.toString(),
108-
});
10990
}
110-
reject(e);
91+
// reject(e);
92+
resolve(e.toString());
11193
});
11294
res.on('end', () => {
11395
if (error !== '发生错误:') {
@@ -116,67 +98,23 @@ export const createChatCompletion = (options: {
11698
hasMore: true,
11799
text: error,
118100
});
119-
emitter.emit('chatGPTChunck', {
120-
hasMore: true,
121-
text: error,
122-
});
123101
}
124102
}
125103
resolve(combinedResult || error);
126-
emitter.emit('chatGPTComplete', combinedResult || error);
127104
});
128105
},
129106
);
130107
const body = {
131-
model: options.model,
108+
model: config.model,
132109
messages: options.messages,
133110
stream: true,
134-
max_tokens: options.maxTokens,
111+
max_tokens: config.maxTokens,
135112
};
136113
request.on('error', (error) => {
137114
options.handleChunk &&
138115
options.handleChunk({ hasMore: true, text: error.toString() });
139116
resolve(error.toString());
140-
emitter.emit('chatGPTComplete', error.toString());
141117
});
142118
request.write(JSON.stringify(body));
143119
request.end();
144120
});
145-
146-
export const createChatCompletionForScript = (options: {
147-
messages: { role: 'system' | 'user' | 'assistant'; content: string }[];
148-
handleChunk?: (data: { text?: string; hasMore: boolean }) => void;
149-
showWebview?: boolean;
150-
}) => {
151-
if (!options.showWebview) {
152-
const config = getChatGPTConfig();
153-
return createChatCompletion({
154-
hostname: config.hostname,
155-
apiPath: config.apiPath,
156-
apiKey: config.apiKey,
157-
model: config.model,
158-
messages: options.messages,
159-
maxTokens: config.maxTokens,
160-
handleChunk: options.handleChunk,
161-
});
162-
}
163-
// 打开 webview,使用 emitter 监听结果,把结果回传给 script
164-
showChatGPTView({
165-
task: {
166-
task: 'askChatGPT',
167-
data: options.messages.map((m) => m.content).join('\n'),
168-
},
169-
});
170-
return new Promise<string>((resolve, reject) => {
171-
emitter.on('chatGPTChunck', (data) => {
172-
if (options.handleChunk) {
173-
options.handleChunk(data);
174-
}
175-
});
176-
emitter.on('chatGPTComplete', (data) => {
177-
resolve(data);
178-
emitter.off('chatGPTChunck');
179-
emitter.off('chatGPTComplete');
180-
});
181-
});
182-
};

src/webview/controllers/openai.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import * as vscode from 'vscode';
22
import { IMessage } from '../type';
3-
import { createChatCompletion } from '../../utils/openai';
3+
import { createChatCompletion } from '../../utils/llm';
44
import { invokeChatGPTChunkCallback } from '../callback';
55
import { pasteToEditor } from '../../utils/editor';
6-
import { getChatGPTConfig } from '../../utils/config';
76
import { compile as compileEjs, Model } from '../../utils/ejs';
87
import { showChatGPTView } from '..';
98

@@ -17,14 +16,8 @@ export const askChatGPT = async (
1716
webview: vscode.Webview;
1817
},
1918
) => {
20-
const config = getChatGPTConfig();
2119
const res = await createChatCompletion({
22-
hostname: config.hostname,
23-
apiPath: config.apiPath,
24-
apiKey: config.apiKey,
25-
model: config.model,
2620
messages: message.data.messages,
27-
maxTokens: config.maxTokens,
2821
handleChunk: (data) => {
2922
invokeChatGPTChunkCallback(context.webview, message.cbid, {
3023
sessionId: message.data.sessionId,

src/webview/controllers/script.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { IMessage } from '../type';
66
import { getEnv, rootPath } from '../../utils/vscodeEnv';
77
import { getInnerLibs } from '../../utils/lib';
88
import { getOutputChannel } from '../../utils/outputChannel';
9-
import { createChatCompletionForScript } from '../../utils/openai';
9+
import { createChatCompletionForScript } from '../../utils/llm';
1010
import { getLastActiveTextEditor } from '../../context';
1111

1212
export const runScript = async (

tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
],
1212
"sourceMap": true,
1313
"rootDir": "src",
14-
"ignoreDeprecations": "5.0",
1514
"strict": true /* enable all strict type-checking options */
1615
/* Additional Checks */
1716
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */

0 commit comments

Comments
 (0)