Skip to content

Commit

Permalink
feat: enable support for add http proxy for openai #52 (#53)
Browse files Browse the repository at this point in the history
feat: enable support for adding http proxy for openai 

able to add config for Openai to send requests through the proxy

Refs: #52
Signed-off-by: seven <[email protected]>
  • Loading branch information
Blankll authored Apr 29, 2024
1 parent d792022 commit 5a5f44d
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 38 deletions.
1 change: 1 addition & 0 deletions components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ declare module 'vue' {
NCardHeader: typeof import('naive-ui')['NCardHeader']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDialogProvider: typeof import('naive-ui')['NDialogProvider']
NDivider: typeof import('naive-ui')['NDivider']
NDropdown: typeof import('naive-ui')['NDropdown']
NForm: typeof import('naive-ui')['NForm']
NFormItem: typeof import('naive-ui')['NFormItem']
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"electron-store": "^8.1.0",
"highlight.js": "^11.9.0",
"https-proxy-agent": "^7.0.4",
"lodash": "^4.17.21",
"markdown-it": "^14.1.0",
"monaco-editor": "^0.46.0",
"node-fetch": "^2.7.0",
Expand Down
44 changes: 32 additions & 12 deletions src/electron/chatBotApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import OpenAI from 'openai';
import { HttpsProxyAgent } from 'https-proxy-agent';
import fetch from 'node-fetch';
import { isEmpty } from 'lodash';

export enum ChatBotApiMethods {
ASK = 'ASK',
Expand All @@ -17,14 +18,14 @@ export type ChatBotApiInput = {
model?: string;
assistantId?: string;
threadId?: string;
httpProxy?: string;
};

const ASSISTANT_NAME = 'dockit-assistant';

const createOpenaiClient = ({ apiKey }: { apiKey: string }) => {
const httpAgent = process.env.https_proxy
? new HttpsProxyAgent(process.env.https_proxy)
: undefined;
const createOpenaiClient = ({ apiKey, httpProxy }: { apiKey: string; httpProxy?: string }) => {
const proxy = !isEmpty(httpProxy) ? httpProxy : process.env.https_proxy;
const httpAgent = !isEmpty(proxy) ? new HttpsProxyAgent(proxy) : undefined;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return new OpenAI({ httpAgent, apiKey, fetch });
Expand Down Expand Up @@ -90,14 +91,16 @@ const chatBotApi = {
prompt,
model,
assistantId,
httpProxy,
}: {
apiKey: string;
prompt: string;
model: string;
httpProxy?: string;
assistantId: string;
}) => {
// get the assistant by assistantId
const openai = createOpenaiClient({ apiKey });
const openai = createOpenaiClient({ apiKey, httpProxy });
const assistant = await openai.beta.assistants.retrieve(assistantId);
if (!assistant) {
throw new Error('Assistant not found');
Expand All @@ -108,9 +111,17 @@ const chatBotApi = {
instructions: prompt,
});
},
findAssistant: async ({ apiKey, assistantId }: { apiKey: string; assistantId: string }) => {
findAssistant: async ({
apiKey,
assistantId,
httpProxy,
}: {
apiKey: string;
assistantId: string;
httpProxy?: string;
}) => {
try {
const openai = createOpenaiClient({ apiKey });
const openai = createOpenaiClient({ apiKey, httpProxy });
return await openai.beta.assistants.retrieve(assistantId);
} catch ({ status, details }) {
if (status === 404) {
Expand All @@ -132,10 +143,19 @@ const registerChatBotApiListener = (
'chatBotApi',
async (
_,
{ method, question, apiKey, prompt, model, assistantId, threadId }: ChatBotApiInput,
{
method,
question,
apiKey,
prompt,
model,
assistantId,
threadId,
httpProxy,
}: ChatBotApiInput,
) => {
if (method === ChatBotApiMethods.INITIALIZE) {
openai = createOpenaiClient({ apiKey });
openai = createOpenaiClient({ apiKey, httpProxy });

const { assistantId, threadId } = await chatBotApi.initialize({
openai,
Expand All @@ -147,17 +167,17 @@ const registerChatBotApiListener = (

if (method === ChatBotApiMethods.ASK) {
if (!openai) {
openai = createOpenaiClient({ apiKey });
openai = createOpenaiClient({ apiKey, httpProxy });
}
await chatBotApi.ask({ openai, assistantId, threadId, question: question, mainWindow });
}

if (method === ChatBotApiMethods.MODIFY_ASSISTANT) {
await chatBotApi.modifyAssistant({ apiKey, prompt, model, assistantId });
await chatBotApi.modifyAssistant({ apiKey, prompt, model, assistantId, httpProxy });
}

if (method === ChatBotApiMethods.FIND_ASSISTANT) {
return await chatBotApi.findAssistant({ apiKey, assistantId });
return await chatBotApi.findAssistant({ apiKey, assistantId, httpProxy });
}
},
);
Expand Down
16 changes: 6 additions & 10 deletions src/electron/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,16 @@ contextBridge.exposeInMainWorld('fetchApi', {
});

contextBridge.exposeInMainWorld('chatBotApi', {
initialize: async (args: { apiKey: string; prompt: string; model: string }) =>
initialize: async (args: { apiKey: string; prompt: string; model: string; httpProxy?: string }) =>
ipcRenderer.invoke('chatBotApi', { method: 'INITIALIZE', ...args }),

ask: async ({
question,
apiKey,
assistantId,
threadId,
}: {
ask: async (args: {
apiKey: string;
question: string;
assistantId: string;
threadId: string;
}) =>
ipcRenderer.invoke('chatBotApi', { method: 'ASK', question, apiKey, assistantId, threadId }),
httpProxy?: string;
}) => ipcRenderer.invoke('chatBotApi', { ...args, method: 'ASK' }),

onMessageReceived: (callback: (value: unknown) => void) =>
ipcRenderer.on('chat-bot-api-message-delta', (_event, value) => callback(value)),
Expand All @@ -56,8 +51,9 @@ contextBridge.exposeInMainWorld('chatBotApi', {
prompt: string;
model: string;
assistantId: string;
httpProxy?: string;
}) => ipcRenderer.invoke('chatBotApi', { method: 'MODIFY_ASSISTANT', ...args }),

findAssistant: async (args: { apiKey: string; assistantId: string }) =>
findAssistant: async (args: { apiKey: string; assistantId: string; httpProxy?: string }) =>
ipcRenderer.invoke('chatBotApi', { method: 'FIND_ASSISTANT', ...args }),
});
1 change: 1 addition & 0 deletions src/lang/enUS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const enUS = {
model: 'Model',
apiKey: 'API Key',
prompt: 'Prompt',
proxy: 'Network Proxy',
form: {
reset: 'Reset',
save: 'Save & Enable',
Expand Down
1 change: 1 addition & 0 deletions src/lang/zhCN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const zhCN = {
model: '模型',
apiKey: 'API密钥',
prompt: '提示词',
proxy: '网络代理',
form: {
reset: '重置',
save: '保存并启用',
Expand Down
2 changes: 1 addition & 1 deletion src/store/appStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const useAppStore = defineStore('app', {
uiThemeType: Exclude<ThemeType, ThemeType.AUTO>;
skipVersion: string;
aigcConfig: {
openAi: { apiKey?: string; model?: string; prompt?: string };
openAi: { apiKey?: string; model?: string; prompt?: string; httpProxy?: string };
};
} => {
return {
Expand Down
18 changes: 8 additions & 10 deletions src/store/chatStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,12 @@ export const useChatStore = defineStore('chat', {
actions: {
async fetchChats() {
const chats = await storeAPI.get('chats', undefined);
console.log('chats', JSON.stringify({ chats }));
if (!chats || !chats.length) {
return;
}
const { assistantId } = chats[0];
const { apiKey } = await getOpenAiConfig();
const assistant = await chatBotApi.findAssistant({ apiKey, assistantId });
console.log('assistant', JSON.stringify({ assistant }));
const { apiKey, httpProxy } = await getOpenAiConfig();
const assistant = await chatBotApi.findAssistant({ apiKey, assistantId, httpProxy });
if (!assistant) {
this.chats = [];
await storeAPI.set('chats', []);
Expand All @@ -70,12 +68,13 @@ export const useChatStore = defineStore('chat', {
if (!assistantId) {
return;
}
const { apiKey, prompt, model } = await getOpenAiConfig();
const { apiKey, prompt, model, httpProxy } = await getOpenAiConfig();
await chatBotApi.modifyAssistant({
apiKey,
prompt: prompt ?? lang.global.t('setting.ai.defaultPrompt'),
model,
assistantId,
httpProxy,
});
},
async sendMessage(content: string) {
Expand All @@ -97,18 +96,18 @@ export const useChatStore = defineStore('chat', {
});
receiveRegistration = true;
}

const { apiKey, prompt, model, httpProxy } = await getOpenAiConfig();
if (!this.chats[0]) {
const chats = await storeAPI.get('chats', undefined);
if (chats && chats.length) {
this.chats = chats;
} else {
try {
const { apiKey, prompt, model } = await getOpenAiConfig();
const { assistantId, threadId } = await chatBotApi.initialize({
apiKey,
model,
prompt: prompt ?? lang.global.t('setting.ai.defaultPrompt'),
httpProxy,
});
this.chats.push({ id: ulid(), type: 'openai', messages: [], assistantId, threadId });
await storeAPI.set('chats', pureObject(this.chats));
Expand All @@ -131,13 +130,12 @@ export const useChatStore = defineStore('chat', {
? `user's question: ${content} context: indexName - ${index.index}, indexMapping - ${index.mapping}`
: `user's question: ${content}`;
try {
const openaiConfig = await getOpenAiConfig();

await chatBotApi.ask({
question,
assistantId,
threadId,
apiKey: openaiConfig.apiKey,
apiKey,
httpProxy,
});
} catch (err) {
messages[messages.length - 1].status = MessageStatus.FAILED;
Expand Down
2 changes: 1 addition & 1 deletion src/views/editor/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ const executeQueryAction = async (
...action,
index: action.index || established.value?.activeIndex?.index,
});
console.log('get response data: ', data);
displayJsonEditor(JSON.stringify(data, null, ' '));
} catch (err) {
const { status, details } = err as CustomError;
Expand Down
6 changes: 5 additions & 1 deletion src/views/setting/components/aigc.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
:placeholder="$t('setting.ai.defaultPrompt')"
/>
</n-form-item-row>
<n-divider />
<n-form-item-row :label="$t('setting.ai.proxy')">
<n-input v-model:value="openAi.httpProxy" placeholder="http://127.0.0.1:7890" />
</n-form-item-row>
<n-button type="error" @click="reset" class="action-button">
{{ $t('setting.ai.form.reset') }}
</n-button>
Expand Down Expand Up @@ -44,7 +48,7 @@ const { fetchChats, modifyAssistant } = chatStore;
const openAi = ref({ ...aigcConfig.value.openAi });
const reset = async () => {
openAi.value = { apiKey: '', model: '', prompt: '' };
openAi.value = { apiKey: '', model: '', prompt: '', httpProxy: '' };
await saveAigcConfig({ ...aigcConfig.value, openAi: openAi.value, enabled: false });
};
Expand Down
11 changes: 10 additions & 1 deletion src/vite-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,19 @@ export interface IChatBotAPI {
apiKey,
prompt,
model,
httpProxy,
}: {
apiKey: string;
prompt: string;
model: string;
httpProxy?: string;
}) => Promise<{ assistantId: string; threadId: string }>;
ask: (args: {
question: string;
assistantId: string;
threadId: string;
apiKey: string;
httpProxy?: string;
}) => Promise<void>;
onMessageReceived: (
fn: (value: {
Expand All @@ -66,14 +69,20 @@ export interface IChatBotAPI {
apiKey,
prompt,
model,
httpProxy,
assistantId,
}: {
apiKey: string;
prompt: string;
model: string;
httpProxy?: string;
assistantId: string;
}) => Promise<void>;
findAssistant: (args: { apiKey: string; assistantId: string }) => Promise<unknown>;
findAssistant: (args: {
apiKey: string;
assistantId: string;
httpProxy?: string;
}) => Promise<unknown>;
}

export interface ISourceFileAPI {
Expand Down

0 comments on commit 5a5f44d

Please sign in to comment.