feat(admin): 添加模型算力点配置和扣费功能
- 在管理后台设置页面添加模型算力点配置表格 - 实现后端AI接口调用时按模型扣除用户算力点 - 添加算力点余额检查和不足时的错误处理 - 在credit_logs中记录AI调用消费流水 - 更新前端远程调用后刷新用户信息显示 - 文档中补充模型算力点配置说明
This commit is contained in:
@@ -169,6 +169,7 @@ export type AdminModelChannel = {
|
||||
|
||||
export type AdminPublicModelChannelSettings = {
|
||||
availableModels: string[];
|
||||
modelCosts: AdminModelCost[];
|
||||
defaultModel: string;
|
||||
defaultImageModel: string;
|
||||
defaultVideoModel: string;
|
||||
@@ -177,6 +178,11 @@ export type AdminPublicModelChannelSettings = {
|
||||
allowCustomChannel: boolean;
|
||||
};
|
||||
|
||||
export type AdminModelCost = {
|
||||
model: string;
|
||||
credits: number;
|
||||
};
|
||||
|
||||
export type AdminPublicSettings = {
|
||||
modelChannel: AdminPublicModelChannelSettings;
|
||||
auth: {
|
||||
|
||||
@@ -121,6 +121,10 @@ function aiHeaders(config: AiConfig, contentType?: string) {
|
||||
};
|
||||
}
|
||||
|
||||
function refreshRemoteUser(config: AiConfig) {
|
||||
if (config.channelMode === "remote") void useUserStore.getState().hydrateUser();
|
||||
}
|
||||
|
||||
function withSystemMessage(config: AiConfig, messages: ChatCompletionMessage[]) {
|
||||
const systemPrompt = config.systemPrompt.trim();
|
||||
return systemPrompt ? [{ role: "system" as const, content: systemPrompt }, ...messages] : messages;
|
||||
@@ -143,7 +147,9 @@ export async function requestGeneration(config: AiConfig, prompt: string) {
|
||||
headers: aiHeaders(config, "application/json"),
|
||||
},
|
||||
);
|
||||
return parseImagePayload(response.data);
|
||||
const images = parseImagePayload(response.data);
|
||||
refreshRemoteUser(config);
|
||||
return images;
|
||||
} catch (error) {
|
||||
throw new Error(readAxiosError(error, "请求失败"));
|
||||
}
|
||||
@@ -166,7 +172,9 @@ export async function requestEdit(config: AiConfig, prompt: string, references:
|
||||
|
||||
try {
|
||||
const response = await axios.post<ImageApiResponse>(aiApiUrl(config, "/images/edits"), formData, { headers: aiHeaders(config) });
|
||||
return parseImagePayload(response.data);
|
||||
const images = parseImagePayload(response.data);
|
||||
refreshRemoteUser(config);
|
||||
return images;
|
||||
} catch (error) {
|
||||
throw new Error(readAxiosError(error, "请求失败"));
|
||||
}
|
||||
@@ -230,6 +238,7 @@ export async function requestImageQuestion(config: AiConfig, messages: ChatCompl
|
||||
} catch (error) {
|
||||
throw new Error(readAxiosError(error, "请求失败"));
|
||||
}
|
||||
refreshRemoteUser(config);
|
||||
return answer || "没有返回内容";
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@ function aiHeaders(config: AiConfig) {
|
||||
return config.channelMode === "remote" ? (token ? { Authorization: `Bearer ${token}` } : undefined) : { Authorization: `Bearer ${config.apiKey}` };
|
||||
}
|
||||
|
||||
function refreshRemoteUser(config: AiConfig) {
|
||||
if (config.channelMode === "remote") void useUserStore.getState().hydrateUser();
|
||||
}
|
||||
|
||||
export async function requestVideoGeneration(config: AiConfig, prompt: string, references: ReferenceImage[] = []) {
|
||||
const model = config.model || config.videoModel;
|
||||
const body = new FormData();
|
||||
@@ -34,6 +38,7 @@ export async function requestVideoGeneration(config: AiConfig, prompt: string, r
|
||||
await new Promise((resolve) => setTimeout(resolve, 2500));
|
||||
}
|
||||
const content = await axios.get<Blob>(aiApiUrl(config, `/videos/${created.data.id}/content`), { headers: aiHeaders(config), params: config.channelMode === "remote" ? { model } : undefined, responseType: "blob" });
|
||||
refreshRemoteUser(config);
|
||||
return content.data;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user