Rework custom API
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
import PromptSettings from "./PromptSettings.svelte";
|
import PromptSettings from "./PromptSettings.svelte";
|
||||||
import { openPresetList } from "src/ts/stores.svelte";
|
import { openPresetList } from "src/ts/stores.svelte";
|
||||||
import { selectSingleFile } from "src/ts/util";
|
import { selectSingleFile } from "src/ts/util";
|
||||||
|
import { LLMFormat } from "src/ts/model/modellist";
|
||||||
|
|
||||||
let tokens = $state({
|
let tokens = $state({
|
||||||
mainPrompt: 0,
|
mainPrompt: 0,
|
||||||
@@ -133,39 +134,27 @@
|
|||||||
<span class="text-textcolor mt-4"> {language.proxyAPIKey}</span>
|
<span class="text-textcolor mt-4"> {language.proxyAPIKey}</span>
|
||||||
<TextInput hideText={DBState.db.hideApiKey} marginBottom={false} size={"sm"} placeholder="leave it blank if it hasn't password" bind:value={DBState.db.proxyKey} />
|
<TextInput hideText={DBState.db.hideApiKey} marginBottom={false} size={"sm"} placeholder="leave it blank if it hasn't password" bind:value={DBState.db.proxyKey} />
|
||||||
<span class="text-textcolor mt-4"> {language.proxyRequestModel}</span>
|
<span class="text-textcolor mt-4"> {language.proxyRequestModel}</span>
|
||||||
<SelectInput className="mt-2" bind:value={DBState.db.proxyRequestModel}>
|
<TextInput marginBottom={false} size={"sm"} bind:value={DBState.db.customProxyRequestModel} placeholder="Name" />
|
||||||
<OptionInput value="">None</OptionInput>
|
<span class="text-textcolor mt-4"> {language.format}</span>
|
||||||
<OptionInput value="gpt35">GPT 3.5</OptionInput>
|
<SelectInput value={DBState.db.customAPIFormat.toString()} onchange={(e) => {
|
||||||
<OptionInput value="gpt35_16k">GPT 3.5 16k</OptionInput>
|
DBState.db.customAPIFormat = parseInt(e.currentTarget.value)
|
||||||
<OptionInput value="gpt4">GPT-4</OptionInput>
|
}}>
|
||||||
<OptionInput value="gpt4o">GPT-4o</OptionInput>
|
<OptionInput value={LLMFormat.OpenAICompatible.toString()}>
|
||||||
<OptionInput value="gpt4_32k">GPT-4 32k</OptionInput>
|
OpenAI Compatible
|
||||||
<OptionInput value="gpt4_turbo">GPT-4 Turbo</OptionInput>
|
</OptionInput>
|
||||||
<OptionInput value="gpt4_1106">GPT-4 Turbo 1106</OptionInput>
|
<OptionInput value={LLMFormat.Anthropic.toString()}>
|
||||||
<OptionInput value="gptvi4_1106">GPT-4 Turbo 1106 Vision</OptionInput>
|
Anthropic Claude
|
||||||
<OptionInput value="gpt35_0301">GPT-3.5 0301</OptionInput>
|
</OptionInput>
|
||||||
<OptionInput value="gpt4_0301">GPT-4 0301</OptionInput>
|
<OptionInput value={LLMFormat.Mistral.toString()}>
|
||||||
<OptionInput value="gpt35_0613">GPT-3.5 0613</OptionInput>
|
Mistral
|
||||||
<OptionInput value="gpt4_0613">GPT-4 0613</OptionInput>
|
</OptionInput>
|
||||||
<OptionInput value="claude-2.1">claude-2.1</OptionInput>
|
<OptionInput value={LLMFormat.GoogleCloud.toString()}>
|
||||||
<OptionInput value="claude-2.0">claude-2.0</OptionInput>
|
Google Cloud
|
||||||
<OptionInput value="claude-2">claude-2</OptionInput>
|
</OptionInput>
|
||||||
<OptionInput value="claude-v1.3">claude-v1.3</OptionInput>
|
<OptionInput value={LLMFormat.Cohere.toString()}>
|
||||||
<OptionInput value="claude-v1.3-100k">claude-v1.3-100k</OptionInput>
|
Cohere
|
||||||
<OptionInput value="claude-v1.2">claude-v1.2</OptionInput>
|
</OptionInput>
|
||||||
<OptionInput value="claude-instant-v1.1">claude-instant-v1.1</OptionInput>
|
|
||||||
<OptionInput value="claude-instant-v1.1-100k">claude-instant-v1.1-100k</OptionInput>
|
|
||||||
<OptionInput value="claude-3-opus-20240229">claude-3-opus-20240229</OptionInput>
|
|
||||||
<OptionInput value="claude-3-sonnet-20240229">claude-3-sonnet-20240229</OptionInput>
|
|
||||||
<OptionInput value="claude-3-5-sonnet-20240620">claude-3-5-sonnet-20240620</OptionInput>
|
|
||||||
<OptionInput value="claude-3-5-sonnet-20241022">claude-3-5-sonnet-20241022</OptionInput>
|
|
||||||
<OptionInput value="custom">Custom</OptionInput>
|
|
||||||
</SelectInput>
|
</SelectInput>
|
||||||
{#if DBState.db.proxyRequestModel === 'custom'}
|
|
||||||
<TextInput marginBottom={true} size={"sm"} bind:value={DBState.db.customProxyRequestModel} placeholder="Name" />
|
|
||||||
{:else}
|
|
||||||
<div class="mb-4"></div>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
{/if}
|
||||||
{#if DBState.db.aiModel.startsWith('risullm')}
|
{#if DBState.db.aiModel.startsWith('risullm')}
|
||||||
<span class="text-textcolor mt-4">Risu {language.apiKey}</span>
|
<span class="text-textcolor mt-4">Risu {language.apiKey}</span>
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
import { get } from "svelte/store";
|
|
||||||
import type { MultiModal, OpenAIChat, OpenAIChatFull } from "./index.svelte";
|
import type { MultiModal, OpenAIChat, OpenAIChatFull } from "./index.svelte";
|
||||||
import { getCurrentCharacter, getDatabase, type character } from "../storage/database.svelte";
|
import { getCurrentCharacter, getDatabase, type character } from "../storage/database.svelte";
|
||||||
import { pluginProcess } from "../plugins/plugins";
|
import { pluginProcess } from "../plugins/plugins";
|
||||||
import { language } from "../../lang";
|
import { language } from "../../lang";
|
||||||
import { stringlizeAINChat, stringlizeChat, getStopStrings, unstringlizeAIN, unstringlizeChat } from "./stringlize";
|
import { stringlizeAINChat, getStopStrings, unstringlizeAIN, unstringlizeChat } from "./stringlize";
|
||||||
import { addFetchLog, fetchNative, globalFetch, isNodeServer, isTauri, textifyReadableStream } from "../globalApi.svelte";
|
import { addFetchLog, fetchNative, globalFetch, isNodeServer, isTauri, textifyReadableStream } from "../globalApi.svelte";
|
||||||
import { sleep } from "../util";
|
import { sleep } from "../util";
|
||||||
import { NovelAIBadWordIds, stringlizeNAIChat } from "./models/nai";
|
import { NovelAIBadWordIds, stringlizeNAIChat } from "./models/nai";
|
||||||
import { strongBan, tokenize, tokenizeNum } from "../tokenizer";
|
import { strongBan, tokenize, tokenizeNum } from "../tokenizer";
|
||||||
import { runGGUFModel } from "./models/local";
|
|
||||||
import { risuChatParser } from "../parser.svelte";
|
import { risuChatParser } from "../parser.svelte";
|
||||||
import { SignatureV4 } from "@smithy/signature-v4";
|
import { SignatureV4 } from "@smithy/signature-v4";
|
||||||
import { HttpRequest } from "@smithy/protocol-http";
|
import { HttpRequest } from "@smithy/protocol-http";
|
||||||
import { Sha256 } from "@aws-crypto/sha256-js";
|
import { Sha256 } from "@aws-crypto/sha256-js";
|
||||||
import { v4 } from "uuid";
|
|
||||||
import { supportsInlayImage } from "./files/image";
|
import { supportsInlayImage } from "./files/image";
|
||||||
import { Capacitor } from "@capacitor/core";
|
import { Capacitor } from "@capacitor/core";
|
||||||
import { getFreeOpenRouterModel } from "../model/openrouter";
|
import { getFreeOpenRouterModel } from "../model/openrouter";
|
||||||
@@ -47,9 +44,9 @@ interface requestDataArgument{
|
|||||||
interface RequestDataArgumentExtended extends requestDataArgument{
|
interface RequestDataArgumentExtended extends requestDataArgument{
|
||||||
aiModel?:string
|
aiModel?:string
|
||||||
multiGen?:boolean
|
multiGen?:boolean
|
||||||
realAIModel?:string
|
|
||||||
abortSignal?:AbortSignal
|
abortSignal?:AbortSignal
|
||||||
modelInfo?:LLMModel
|
modelInfo?:LLMModel
|
||||||
|
customURL?:string
|
||||||
}
|
}
|
||||||
|
|
||||||
type requestDataResponse = {
|
type requestDataResponse = {
|
||||||
@@ -199,19 +196,12 @@ export async function requestChatDataMain(arg:requestDataArgument, model:'model'
|
|||||||
targ.biasString = arg.biasString ?? []
|
targ.biasString = arg.biasString ?? []
|
||||||
targ.aiModel = (model === 'model' ? db.aiModel : db.subModel)
|
targ.aiModel = (model === 'model' ? db.aiModel : db.subModel)
|
||||||
targ.multiGen = ((db.genTime > 1 && targ.aiModel.startsWith('gpt') && (!arg.continue)) && (!arg.noMultiGen))
|
targ.multiGen = ((db.genTime > 1 && targ.aiModel.startsWith('gpt') && (!arg.continue)) && (!arg.noMultiGen))
|
||||||
targ.realAIModel = targ.aiModel
|
|
||||||
targ.abortSignal = abortSignal
|
targ.abortSignal = abortSignal
|
||||||
targ.modelInfo = getModelInfo(targ.aiModel)
|
targ.modelInfo = getModelInfo(targ.aiModel)
|
||||||
if(targ.aiModel === 'reverse_proxy'){
|
if(targ.aiModel === 'reverse_proxy'){
|
||||||
if(db.proxyRequestModel === 'custom' && db.customProxyRequestModel.startsWith('claude')){
|
targ.modelInfo.internalID = db.customProxyRequestModel
|
||||||
targ.realAIModel = db.customProxyRequestModel
|
targ.modelInfo.format = db.customAPIFormat
|
||||||
}
|
targ.customURL = db.forceReplaceUrl
|
||||||
if(db.proxyRequestModel.startsWith('claude')){
|
|
||||||
targ.realAIModel = db.proxyRequestModel
|
|
||||||
}
|
|
||||||
if(db.forceProxyAsOpenAI){
|
|
||||||
targ.realAIModel = 'reverse_proxy'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const format = targ.modelInfo.format
|
const format = targ.modelInfo.format
|
||||||
@@ -384,7 +374,7 @@ async function requestOpenAI(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
const oaiFunctionCall = oaiFunctions ? (arg.useEmotion ? {"name": "set_emotion"} : "auto") : undefined
|
const oaiFunctionCall = oaiFunctions ? (arg.useEmotion ? {"name": "set_emotion"} : "auto") : undefined
|
||||||
let requestModel = (aiModel === 'reverse_proxy' || aiModel === 'openrouter') ? db.proxyRequestModel : aiModel
|
let requestModel = (aiModel === 'reverse_proxy' || aiModel === 'openrouter') ? db.proxyRequestModel : aiModel
|
||||||
let openrouterRequestModel = db.openrouterRequestModel
|
let openrouterRequestModel = db.openrouterRequestModel
|
||||||
if(aiModel === 'reverse_proxy' && db.proxyRequestModel === 'custom'){
|
if(aiModel === 'reverse_proxy'){
|
||||||
requestModel = db.customProxyRequestModel
|
requestModel = db.customProxyRequestModel
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,7 +383,7 @@ async function requestOpenAI(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log(formatedChat)
|
console.log(formatedChat)
|
||||||
if(aiModel.startsWith('mistral') || aiModel === 'open-mistral-nemo'){
|
if(arg.modelInfo.format === LLMFormat.Mistral){
|
||||||
requestModel = aiModel
|
requestModel = aiModel
|
||||||
|
|
||||||
let reformatedChat:OpenAIChatExtra[] = []
|
let reformatedChat:OpenAIChatExtra[] = []
|
||||||
@@ -446,7 +436,7 @@ async function requestOpenAI(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await globalFetch("https://api.mistral.ai/v1/chat/completions", {
|
const res = await globalFetch(arg.customURL ?? "https://api.mistral.ai/v1/chat/completions", {
|
||||||
body: {
|
body: {
|
||||||
model: requestModel,
|
model: requestModel,
|
||||||
messages: reformatedChat,
|
messages: reformatedChat,
|
||||||
@@ -525,6 +515,7 @@ async function requestOpenAI(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
: requestModel === 'gpt4o-chatgpt' ? 'chatgpt-4o-latest'
|
: requestModel === 'gpt4o-chatgpt' ? 'chatgpt-4o-latest'
|
||||||
: requestModel === 'gpt4o1-preview' ? 'o1-preview'
|
: requestModel === 'gpt4o1-preview' ? 'o1-preview'
|
||||||
: requestModel === 'gpt4o1-mini' ? 'o1-mini'
|
: requestModel === 'gpt4o1-mini' ? 'o1-mini'
|
||||||
|
: arg.modelInfo.internalID ? arg.modelInfo.internalID
|
||||||
: (!requestModel) ? 'gpt-3.5-turbo'
|
: (!requestModel) ? 'gpt-3.5-turbo'
|
||||||
: requestModel,
|
: requestModel,
|
||||||
messages: formatedChat,
|
messages: formatedChat,
|
||||||
@@ -608,7 +599,7 @@ async function requestOpenAI(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
}
|
}
|
||||||
|
|
||||||
let replacerURL = aiModel === 'openrouter' ? "https://openrouter.ai/api/v1/chat/completions" :
|
let replacerURL = aiModel === 'openrouter' ? "https://openrouter.ai/api/v1/chat/completions" :
|
||||||
(aiModel === 'reverse_proxy') ? (db.forceReplaceUrl) : ('https://api.openai.com/v1/chat/completions')
|
(aiModel === 'reverse_proxy') ? (arg.customURL) : ('https://api.openai.com/v1/chat/completions')
|
||||||
|
|
||||||
let risuIdentify = false
|
let risuIdentify = false
|
||||||
if(replacerURL.startsWith("risu::")){
|
if(replacerURL.startsWith("risu::")){
|
||||||
@@ -768,7 +759,7 @@ async function requestOpenAI(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(arg.realAIModel === 'reverse_proxy'){
|
if(aiModel === 'reverse_proxy'){
|
||||||
const additionalParams = db.additionalParams
|
const additionalParams = db.additionalParams
|
||||||
for(let i=0;i<additionalParams.length;i++){
|
for(let i=0;i<additionalParams.length;i++){
|
||||||
let key = additionalParams[i][0]
|
let key = additionalParams[i][0]
|
||||||
@@ -924,7 +915,7 @@ async function requestOpenAILegacyInstruct(arg:RequestDataArgumentExtended):Prom
|
|||||||
//return `\n\n${author}: ${m.content.trim()}`;
|
//return `\n\n${author}: ${m.content.trim()}`;
|
||||||
}).join("") + `\n## Response\n`;
|
}).join("") + `\n## Response\n`;
|
||||||
|
|
||||||
const response = await globalFetch( "https://api.openai.com/v1/completions", {
|
const response = await globalFetch(arg.customURL ?? "https://api.openai.com/v1/completions", {
|
||||||
body: {
|
body: {
|
||||||
model: "gpt-3.5-turbo-instruct",
|
model: "gpt-3.5-turbo-instruct",
|
||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
@@ -1481,9 +1472,9 @@ async function requestGoogleCloudVertex(arg:RequestDataArgumentExtended):Promise
|
|||||||
headers['Authorization'] = "Bearer " + generateToken(db.google.clientEmail, db.google.privateKey)
|
headers['Authorization'] = "Bearer " + generateToken(db.google.clientEmail, db.google.privateKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = arg.modelInfo.format === LLMFormat.VertexAIGemini ?
|
const url = arg.customURL ?? (arg.modelInfo.format === LLMFormat.VertexAIGemini ?
|
||||||
`https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${arg.modelInfo.internalID}:streamGenerateContent`
|
`https://${REGION}-aiplatform.googleapis.com/v1/projects/${PROJECT_ID}/locations/us-central1/publishers/google/models/${arg.modelInfo.internalID}:streamGenerateContent`
|
||||||
: `https://generativelanguage.googleapis.com/v1beta/models/${arg.modelInfo.internalID}:generateContent?key=${db.google.accessToken}`
|
: `https://generativelanguage.googleapis.com/v1beta/models/${arg.modelInfo.internalID}:generateContent?key=${db.google.accessToken}`)
|
||||||
const res = await globalFetch(url, {
|
const res = await globalFetch(url, {
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: body,
|
body: body,
|
||||||
@@ -1624,7 +1615,7 @@ async function requestNovelList(arg:RequestDataArgumentExtended):Promise<request
|
|||||||
logit_bias: (logit_bias.length > 0) ? logit_bias.join("<<|>>") : undefined,
|
logit_bias: (logit_bias.length > 0) ? logit_bias.join("<<|>>") : undefined,
|
||||||
logit_bias_values: (logit_bias_values.length > 0) ? logit_bias_values.join("|") : undefined,
|
logit_bias_values: (logit_bias_values.length > 0) ? logit_bias_values.join("|") : undefined,
|
||||||
};
|
};
|
||||||
const response = await globalFetch(api_server_url + '/api', {
|
const response = await globalFetch(arg.customURL ?? api_server_url + '/api', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: send_body,
|
body: send_body,
|
||||||
@@ -1771,7 +1762,7 @@ async function requestCohere(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
|
|
||||||
console.log(body)
|
console.log(body)
|
||||||
|
|
||||||
const res = await globalFetch('https://api.cohere.com/v1/chat', {
|
const res = await globalFetch(arg.customURL ?? 'https://api.cohere.com/v1/chat', {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": "Bearer " + db.cohereAPIKey,
|
"Authorization": "Bearer " + db.cohereAPIKey,
|
||||||
@@ -1807,7 +1798,7 @@ async function requestClaude(arg:RequestDataArgumentExtended):Promise<requestDat
|
|||||||
const db = getDatabase()
|
const db = getDatabase()
|
||||||
const aiModel = arg.aiModel
|
const aiModel = arg.aiModel
|
||||||
const useStreaming = arg.useStreaming
|
const useStreaming = arg.useStreaming
|
||||||
let replacerURL = (aiModel === 'reverse_proxy') ? (db.forceReplaceUrl) : ('https://api.anthropic.com/v1/messages')
|
let replacerURL = (aiModel === 'reverse_proxy') ? (arg.customURL) : ('https://api.anthropic.com/v1/messages')
|
||||||
let apiKey = (aiModel === 'reverse_proxy') ? db.proxyKey : db.claudeAPIKey
|
let apiKey = (aiModel === 'reverse_proxy') ? db.proxyKey : db.claudeAPIKey
|
||||||
const maxTokens = arg.maxTokens
|
const maxTokens = arg.maxTokens
|
||||||
if(aiModel === 'reverse_proxy' && db.autofillRequestUrl){
|
if(aiModel === 'reverse_proxy' && db.autofillRequestUrl){
|
||||||
|
|||||||
@@ -445,6 +445,7 @@ export function setDatabase(data:Database){
|
|||||||
data.customQuotesData ??= ['“','”','‘','’']
|
data.customQuotesData ??= ['“','”','‘','’']
|
||||||
data.groupOtherBotRole ??= 'user'
|
data.groupOtherBotRole ??= 'user'
|
||||||
data.customGUI ??= ''
|
data.customGUI ??= ''
|
||||||
|
data.customAPIFormat ??= LLMFormat.OpenAICompatible
|
||||||
changeLanguage(data.language)
|
changeLanguage(data.language)
|
||||||
setDatabaseLite(data)
|
setDatabaseLite(data)
|
||||||
}
|
}
|
||||||
@@ -819,6 +820,7 @@ export interface Database{
|
|||||||
guiHTML:string
|
guiHTML:string
|
||||||
logShare:boolean
|
logShare:boolean
|
||||||
OAIPrediction:string
|
OAIPrediction:string
|
||||||
|
customAPIFormat:LLMFormat
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface customscript{
|
export interface customscript{
|
||||||
@@ -1512,6 +1514,7 @@ import type { RisuModule } from '../process/modules';
|
|||||||
import type { HypaV2Data } from '../process/memory/hypav2';
|
import type { HypaV2Data } from '../process/memory/hypav2';
|
||||||
import { decodeRPack, encodeRPack } from '../rpack/rpack_bg';
|
import { decodeRPack, encodeRPack } from '../rpack/rpack_bg';
|
||||||
import { DBState, selectedCharID } from '../stores.svelte';
|
import { DBState, selectedCharID } from '../stores.svelte';
|
||||||
|
import { LLMFormat } from '../model/modellist';
|
||||||
|
|
||||||
export async function downloadPreset(id:number, type:'json'|'risupreset'|'return' = 'json'){
|
export async function downloadPreset(id:number, type:'json'|'risupreset'|'return' = 'json'){
|
||||||
saveCurrentPreset()
|
saveCurrentPreset()
|
||||||
|
|||||||
@@ -41,12 +41,7 @@ export async function encode(data:string):Promise<(number[]|Uint32Array|Int32Arr
|
|||||||
case 'cohere':
|
case 'cohere':
|
||||||
return await tokenizeWebTokenizers(data, 'cohere')
|
return await tokenizeWebTokenizers(data, 'cohere')
|
||||||
default:
|
default:
|
||||||
// Add exception for gpt-4o tokenizers on reverse_proxy
|
return await tikJS(data, 'o200k_base')
|
||||||
if(db.proxyRequestModel?.startsWith('gpt4o') ||
|
|
||||||
(db.proxyRequestModel === 'custom' && db.customProxyRequestModel.startsWith('gpt-4o'))) {
|
|
||||||
return await tikJS(data, 'o200k_base')
|
|
||||||
}
|
|
||||||
return await tikJS(data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(db.aiModel.startsWith('novellist')){
|
if(db.aiModel.startsWith('novellist')){
|
||||||
|
|||||||
Reference in New Issue
Block a user