Merge pull request #3838 from bmen25124/custom_req_proxy Added proxy support to ChatCompletionService

2982d7af526eecbea58eff8ed393efa24b6252ae

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
2 files changed, +20 -7Showing whitespace changes
public/scripts/custom-request.js+11 -5
@@ -43,10 +43,12 @@ import EventSourceStream from './sse-stream.js';
43 * @property {boolean?} [stream=false] - Whether to stream the response43 * @property {boolean?} [stream=false] - Whether to stream the response
44 * @property {ChatCompletionMessage[]} messages - Array of chat messages44 * @property {ChatCompletionMessage[]} messages - Array of chat messages
45 * @property {string} [model] - Optional model name to use for completion45 * @property {string} [model] - Optional model name to use for completion
46 * @property {string} chat_completion_source - Source provider for chat completion46 * @property {string} chat_completion_source - Source provider
47 * @property {number} max_tokens - Maximum number of tokens to generate47 * @property {number} max_tokens - Maximum number of tokens to generate
48 * @property {number} [temperature] - Optional temperature parameter for response randomness48 * @property {number} [temperature] - Optional temperature parameter for response randomness
49 * @property {string} [custom_url] - Optional custom URL for chat completion49 * @property {string} [custom_url] - Optional custom URL
50 * @property {string} [reverse_proxy] - Optional reverse proxy URL
51 * @property {string} [proxy_password] - Optional proxy password
50 */52 */
5153
52/** @typedef {Record<string, any> & ChatCompletionPayloadBase} ChatCompletionPayload */54/** @typedef {Record<string, any> & ChatCompletionPayloadBase} ChatCompletionPayload */
@@ -80,7 +82,6 @@ export class TextCompletionService {
80 */82 */
81 static createRequestData({ stream = false, prompt, max_tokens, model, api_type, api_server, temperature, min_p, ...props }) {83 static createRequestData({ stream = false, prompt, max_tokens, model, api_type, api_server, temperature, min_p, ...props }) {
82 const payload = {84 const payload = {
83 ...props,
84 stream,85 stream,
85 prompt,86 prompt,
86 max_tokens,87 max_tokens,
@@ -90,6 +91,7 @@ export class TextCompletionService {
90 api_server: api_server ?? getTextGenServer(api_type),91 api_server: api_server ?? getTextGenServer(api_type),
91 temperature,92 temperature,
92 min_p,93 min_p,
94 ...props,
93 };95 };
9496
95 // Remove undefined values to avoid API errors97 // Remove undefined values to avoid API errors
@@ -387,9 +389,8 @@ export class ChatCompletionService {
387 * @param {ChatCompletionPayload} custom389 * @param {ChatCompletionPayload} custom
388 * @returns {ChatCompletionPayload}390 * @returns {ChatCompletionPayload}
389 */391 */
390 static createRequestData({ stream = false, messages, model, chat_completion_source, max_tokens, temperature, custom_url, ...props }) {392 static createRequestData({ stream = false, messages, model, chat_completion_source, max_tokens, temperature, custom_url, reverse_proxy, proxy_password, ...props }) {
391 const payload = {393 const payload = {
392 ...props,
393 stream,394 stream,
394 messages,395 messages,
395 model,396 model,
@@ -397,6 +398,11 @@ export class ChatCompletionService {
397 max_tokens,398 max_tokens,
398 temperature,399 temperature,
399 custom_url,400 custom_url,
401 reverse_proxy,
402 proxy_password,
403 use_makersuite_sysprompt: true,
404 claude_use_sysprompt: true,
405 ...props,
400 };406 };
401407
402 // Remove undefined values to avoid API errors408 // Remove undefined values to avoid API errors
public/scripts/extensions/shared.js+9 -2
@@ -1,7 +1,7 @@
1import { CONNECT_API_MAP, getRequestHeaders } from '../../script.js';1import { CONNECT_API_MAP, getRequestHeaders } from '../../script.js';
2import { extension_settings, openThirdPartyExtensionMenu } from '../extensions.js';2import { extension_settings, openThirdPartyExtensionMenu } from '../extensions.js';
3import { t } from '../i18n.js';3import { t } from '../i18n.js';
4import { oai_settings } from '../openai.js';4import { oai_settings, proxies } from '../openai.js';
5import { SECRET_KEYS, secret_state } from '../secrets.js';5import { SECRET_KEYS, secret_state } from '../secrets.js';
6import { textgen_types, textgenerationwebui_settings } from '../textgen-settings.js';6import { textgen_types, textgenerationwebui_settings } from '../textgen-settings.js';
7import { getTokenCountAsync } from '../tokenizers.js';7import { getTokenCountAsync } from '../tokenizers.js';
@@ -306,9 +306,10 @@ export class ConnectionManagerRequestService {
306 * @param {boolean?} [custom.includePreset=true]306 * @param {boolean?} [custom.includePreset=true]
307 * @param {boolean?} [custom.includeInstruct=true]307 * @param {boolean?} [custom.includeInstruct=true]
308 * @param {Partial<InstructSettings>?} [custom.instructSettings] Override instruct settings308 * @param {Partial<InstructSettings>?} [custom.instructSettings] Override instruct settings
309 * @param {Record<string, any>} [overridePayload] - Override payload for the request
309 * @returns {Promise<import('../custom-request.js').ExtractedData | (() => AsyncGenerator<import('../custom-request.js').StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator310 * @returns {Promise<import('../custom-request.js').ExtractedData | (() => AsyncGenerator<import('../custom-request.js').StreamResponse>)>} If not streaming, returns extracted data; if streaming, returns a function that creates an AsyncGenerator
310 */311 */
311 static async sendRequest(profileId, prompt, maxTokens, custom = this.defaultSendRequestParams) {312 static async sendRequest(profileId, prompt, maxTokens, custom = this.defaultSendRequestParams, overridePayload = {}) {
312 const { stream, signal, extractData, includePreset, includeInstruct, instructSettings } = { ...this.defaultSendRequestParams, ...custom };313 const { stream, signal, extractData, includePreset, includeInstruct, instructSettings } = { ...this.defaultSendRequestParams, ...custom };
313314
314 const context = SillyTavern.getContext();315 const context = SillyTavern.getContext();
@@ -326,6 +327,8 @@ export class ConnectionManagerRequestService {
326 throw new Error(`API type ${selectedApiMap.selected} does not support chat completions`);327 throw new Error(`API type ${selectedApiMap.selected} does not support chat completions`);
327 }328 }
328329
330 const proxyPreset = proxies.find((p) => p.name === profile.proxy);
331
329 const messages = Array.isArray(prompt) ? prompt : [{ role: 'user', content: prompt }];332 const messages = Array.isArray(prompt) ? prompt : [{ role: 'user', content: prompt }];
330 return await context.ChatCompletionService.processRequest({333 return await context.ChatCompletionService.processRequest({
331 stream,334 stream,
@@ -334,6 +337,9 @@ export class ConnectionManagerRequestService {
334 model: profile.model,337 model: profile.model,
335 chat_completion_source: selectedApiMap.source,338 chat_completion_source: selectedApiMap.source,
336 custom_url: profile['api-url'],339 custom_url: profile['api-url'],
340 reverse_proxy: proxyPreset?.url,
341 proxy_password: proxyPreset?.password,
342 ...overridePayload,
337 }, {343 }, {
338 presetName: includePreset ? profile.preset : undefined,344 presetName: includePreset ? profile.preset : undefined,
339 }, extractData, signal);345 }, extractData, signal);
@@ -350,6 +356,7 @@ export class ConnectionManagerRequestService {
350 model: profile.model,356 model: profile.model,
351 api_type: selectedApiMap.type,357 api_type: selectedApiMap.type,
352 api_server: profile['api-url'],358 api_server: profile['api-url'],
359 ...overridePayload,
353 }, {360 }, {
354 instructName: includeInstruct ? profile.instruct : undefined,361 instructName: includeInstruct ? profile.instruct : undefined,
355 presetName: includePreset ? profile.preset : undefined,362 presetName: includePreset ? profile.preset : undefined,