Spaces:
Sleeping
Sleeping
import { getClientConfig } from "../config/client"; | |
import { | |
ACCESS_CODE_PREFIX, | |
ModelProvider, | |
ServiceProvider, | |
} from "../constant"; | |
import { | |
ChatMessageTool, | |
ChatMessage, | |
ModelType, | |
useAccessStore, | |
useChatStore, | |
} from "../store"; | |
import { ChatGPTApi, DalleRequestPayload } from "./platforms/openai"; | |
import { GeminiProApi } from "./platforms/google"; | |
import { ClaudeApi } from "./platforms/anthropic"; | |
import { ErnieApi } from "./platforms/baidu"; | |
import { DoubaoApi } from "./platforms/bytedance"; | |
import { QwenApi } from "./platforms/alibaba"; | |
import { HunyuanApi } from "./platforms/tencent"; | |
import { MoonshotApi } from "./platforms/moonshot"; | |
import { SparkApi } from "./platforms/iflytek"; | |
import { DeepSeekApi } from "./platforms/deepseek"; | |
import { XAIApi } from "./platforms/xai"; | |
import { ChatGLMApi } from "./platforms/glm"; | |
import { SiliconflowApi } from "./platforms/siliconflow"; | |
export const ROLES = ["system", "user", "assistant"] as const; | |
export type MessageRole = (typeof ROLES)[number]; | |
export const Models = ["gpt-3.5-turbo", "gpt-4"] as const; | |
export const TTSModels = ["tts-1", "tts-1-hd"] as const; | |
export type ChatModel = ModelType; | |
export interface MultimodalContent { | |
type: "text" | "image_url"; | |
text?: string; | |
image_url?: { | |
url: string; | |
}; | |
} | |
export interface RequestMessage { | |
role: MessageRole; | |
content: string | MultimodalContent[]; | |
} | |
export interface LLMConfig { | |
model: string; | |
providerName?: string; | |
temperature?: number; | |
top_p?: number; | |
stream?: boolean; | |
presence_penalty?: number; | |
frequency_penalty?: number; | |
size?: DalleRequestPayload["size"]; | |
quality?: DalleRequestPayload["quality"]; | |
style?: DalleRequestPayload["style"]; | |
} | |
export interface SpeechOptions { | |
model: string; | |
input: string; | |
voice: string; | |
response_format?: string; | |
speed?: number; | |
onController?: (controller: AbortController) => void; | |
} | |
export interface ChatOptions { | |
messages: RequestMessage[]; | |
config: LLMConfig; | |
onUpdate?: (message: string, chunk: string) => void; | |
onFinish: (message: string, responseRes: Response) => void; | |
onError?: (err: Error) => void; | |
onController?: (controller: AbortController) => void; | |
onBeforeTool?: (tool: ChatMessageTool) => void; | |
onAfterTool?: (tool: ChatMessageTool) => void; | |
} | |
export interface LLMUsage { | |
used: number; | |
total: number; | |
} | |
export interface LLMModel { | |
name: string; | |
displayName?: string; | |
available: boolean; | |
provider: LLMModelProvider; | |
sorted: number; | |
} | |
export interface LLMModelProvider { | |
id: string; | |
providerName: string; | |
providerType: string; | |
sorted: number; | |
} | |
export abstract class LLMApi { | |
abstract chat(options: ChatOptions): Promise<void>; | |
abstract speech(options: SpeechOptions): Promise<ArrayBuffer>; | |
abstract usage(): Promise<LLMUsage>; | |
abstract models(): Promise<LLMModel[]>; | |
} | |
type ProviderName = "openai" | "azure" | "claude" | "palm"; | |
interface Model { | |
name: string; | |
provider: ProviderName; | |
ctxlen: number; | |
} | |
interface ChatProvider { | |
name: ProviderName; | |
apiConfig: { | |
baseUrl: string; | |
apiKey: string; | |
summaryModel: Model; | |
}; | |
models: Model[]; | |
chat: () => void; | |
usage: () => void; | |
} | |
export class ClientApi { | |
public llm: LLMApi; | |
constructor(provider: ModelProvider = ModelProvider.GPT) { | |
switch (provider) { | |
case ModelProvider.GeminiPro: | |
this.llm = new GeminiProApi(); | |
break; | |
case ModelProvider.Claude: | |
this.llm = new ClaudeApi(); | |
break; | |
case ModelProvider.Ernie: | |
this.llm = new ErnieApi(); | |
break; | |
case ModelProvider.Doubao: | |
this.llm = new DoubaoApi(); | |
break; | |
case ModelProvider.Qwen: | |
this.llm = new QwenApi(); | |
break; | |
case ModelProvider.Hunyuan: | |
this.llm = new HunyuanApi(); | |
break; | |
case ModelProvider.Moonshot: | |
this.llm = new MoonshotApi(); | |
break; | |
case ModelProvider.Iflytek: | |
this.llm = new SparkApi(); | |
break; | |
case ModelProvider.DeepSeek: | |
this.llm = new DeepSeekApi(); | |
break; | |
case ModelProvider.XAI: | |
this.llm = new XAIApi(); | |
break; | |
case ModelProvider.ChatGLM: | |
this.llm = new ChatGLMApi(); | |
break; | |
case ModelProvider.SiliconFlow: | |
this.llm = new SiliconflowApi(); | |
break; | |
default: | |
this.llm = new ChatGPTApi(); | |
} | |
} | |
config() {} | |
prompts() {} | |
masks() {} | |
async share(messages: ChatMessage[], avatarUrl: string | null = null) { | |
const msgs = messages | |
.map((m) => ({ | |
from: m.role === "user" ? "human" : "gpt", | |
value: m.content, | |
})) | |
.concat([ | |
{ | |
from: "human", | |
value: | |
"Share from [NextChat]: https://github.com/Yidadaa/ChatGPT-Next-Web", | |
}, | |
]); | |
// 敬告二开开发者们,为了开源大模型的发展,请不要修改上述消息,此消息用于后续数据清洗使用 | |
// Please do not modify this message | |
console.log("[Share]", messages, msgs); | |
const clientConfig = getClientConfig(); | |
const proxyUrl = "/sharegpt"; | |
const rawUrl = "https://sharegpt.com/api/conversations"; | |
const shareUrl = clientConfig?.isApp ? rawUrl : proxyUrl; | |
const res = await fetch(shareUrl, { | |
body: JSON.stringify({ | |
avatarUrl, | |
items: msgs, | |
}), | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
method: "POST", | |
}); | |
const resJson = await res.json(); | |
console.log("[Share]", resJson); | |
if (resJson.id) { | |
return `https://shareg.pt/${resJson.id}`; | |
} | |
} | |
} | |
export function getBearerToken( | |
apiKey: string, | |
noBearer: boolean = false, | |
): string { | |
return validString(apiKey) | |
? `${noBearer ? "" : "Bearer "}${apiKey.trim()}` | |
: ""; | |
} | |
export function validString(x: string): boolean { | |
return x?.length > 0; | |
} | |
export function getHeaders(ignoreHeaders: boolean = false) { | |
const accessStore = useAccessStore.getState(); | |
const chatStore = useChatStore.getState(); | |
let headers: Record<string, string> = {}; | |
if (!ignoreHeaders) { | |
headers = { | |
"Content-Type": "application/json", | |
Accept: "application/json", | |
}; | |
} | |
const clientConfig = getClientConfig(); | |
function getConfig() { | |
const modelConfig = chatStore.currentSession().mask.modelConfig; | |
const isGoogle = modelConfig.providerName === ServiceProvider.Google; | |
const isAzure = modelConfig.providerName === ServiceProvider.Azure; | |
const isAnthropic = modelConfig.providerName === ServiceProvider.Anthropic; | |
const isBaidu = modelConfig.providerName == ServiceProvider.Baidu; | |
const isByteDance = modelConfig.providerName === ServiceProvider.ByteDance; | |
const isAlibaba = modelConfig.providerName === ServiceProvider.Alibaba; | |
const isMoonshot = modelConfig.providerName === ServiceProvider.Moonshot; | |
const isIflytek = modelConfig.providerName === ServiceProvider.Iflytek; | |
const isDeepSeek = modelConfig.providerName === ServiceProvider.DeepSeek; | |
const isXAI = modelConfig.providerName === ServiceProvider.XAI; | |
const isChatGLM = modelConfig.providerName === ServiceProvider.ChatGLM; | |
const isSiliconFlow = | |
modelConfig.providerName === ServiceProvider.SiliconFlow; | |
const isEnabledAccessControl = accessStore.enabledAccessControl(); | |
const apiKey = isGoogle | |
? accessStore.googleApiKey | |
: isAzure | |
? accessStore.azureApiKey | |
: isAnthropic | |
? accessStore.anthropicApiKey | |
: isByteDance | |
? accessStore.bytedanceApiKey | |
: isAlibaba | |
? accessStore.alibabaApiKey | |
: isMoonshot | |
? accessStore.moonshotApiKey | |
: isXAI | |
? accessStore.xaiApiKey | |
: isDeepSeek | |
? accessStore.deepseekApiKey | |
: isChatGLM | |
? accessStore.chatglmApiKey | |
: isSiliconFlow | |
? accessStore.siliconflowApiKey | |
: isIflytek | |
? accessStore.iflytekApiKey && accessStore.iflytekApiSecret | |
? accessStore.iflytekApiKey + ":" + accessStore.iflytekApiSecret | |
: "" | |
: accessStore.openaiApiKey; | |
return { | |
isGoogle, | |
isAzure, | |
isAnthropic, | |
isBaidu, | |
isByteDance, | |
isAlibaba, | |
isMoonshot, | |
isIflytek, | |
isDeepSeek, | |
isXAI, | |
isChatGLM, | |
isSiliconFlow, | |
apiKey, | |
isEnabledAccessControl, | |
}; | |
} | |
function getAuthHeader(): string { | |
return isAzure | |
? "api-key" | |
: isAnthropic | |
? "x-api-key" | |
: isGoogle | |
? "x-goog-api-key" | |
: "Authorization"; | |
} | |
const { | |
isGoogle, | |
isAzure, | |
isAnthropic, | |
isBaidu, | |
isByteDance, | |
isAlibaba, | |
isMoonshot, | |
isIflytek, | |
isDeepSeek, | |
isXAI, | |
isChatGLM, | |
isSiliconFlow, | |
apiKey, | |
isEnabledAccessControl, | |
} = getConfig(); | |
// when using baidu api in app, not set auth header | |
if (isBaidu && clientConfig?.isApp) return headers; | |
const authHeader = getAuthHeader(); | |
const bearerToken = getBearerToken( | |
apiKey, | |
isAzure || isAnthropic || isGoogle, | |
); | |
if (bearerToken) { | |
headers[authHeader] = bearerToken; | |
} else if (isEnabledAccessControl && validString(accessStore.accessCode)) { | |
headers["Authorization"] = getBearerToken( | |
ACCESS_CODE_PREFIX + accessStore.accessCode, | |
); | |
} | |
return headers; | |
} | |
export function getClientApi(provider: ServiceProvider): ClientApi { | |
switch (provider) { | |
case ServiceProvider.Google: | |
return new ClientApi(ModelProvider.GeminiPro); | |
case ServiceProvider.Anthropic: | |
return new ClientApi(ModelProvider.Claude); | |
case ServiceProvider.Baidu: | |
return new ClientApi(ModelProvider.Ernie); | |
case ServiceProvider.ByteDance: | |
return new ClientApi(ModelProvider.Doubao); | |
case ServiceProvider.Alibaba: | |
return new ClientApi(ModelProvider.Qwen); | |
case ServiceProvider.Tencent: | |
return new ClientApi(ModelProvider.Hunyuan); | |
case ServiceProvider.Moonshot: | |
return new ClientApi(ModelProvider.Moonshot); | |
case ServiceProvider.Iflytek: | |
return new ClientApi(ModelProvider.Iflytek); | |
case ServiceProvider.DeepSeek: | |
return new ClientApi(ModelProvider.DeepSeek); | |
case ServiceProvider.XAI: | |
return new ClientApi(ModelProvider.XAI); | |
case ServiceProvider.ChatGLM: | |
return new ClientApi(ModelProvider.ChatGLM); | |
case ServiceProvider.SiliconFlow: | |
return new ClientApi(ModelProvider.SiliconFlow); | |
default: | |
return new ClientApi(ModelProvider.GPT); | |
} | |
} | |