import { Z as ElRadioButton, P as ElRadioGroup, ao as vLoading, x as ElFormItem, aq as ElSelect, ar as ElOption, y as ElInput, as as ElSlider, h as ElButton, at as aim_default, aa as delete_default, ad as chat_dot_round_default, i as ElIcon, ae as user_default, ai as promotion_default, au as video_pause_default, w as ElForm, v as ElDialog, E as ElMessage, D as ElMessageBox } from "./element-plus.CkEW9frc.js"; import { J as defineComponent, ej as MarkdownIt, t as onMounted, S as openBlock, _ as createElementBlock, a1 as createBaseVNode, $ as createVNode, a0 as withCtx, H as Fragment, ay as renderList, o as unref, T as createBlock, a9 as createTextVNode, aa as toDisplayString, a6 as withDirectives, a8 as createCommentVNode, a3 as normalizeClass, a_ as withKeys, aw as withModifiers, r as ref, j as computed, ak as reactive, n as nextTick, el as HighlightJS } from "./.pnpm.BW3P1y8f.js"; import { l as httpRequest, A as Auth } from "./index.CMd5bD1r.js"; import { A as AIProviderAPI } from "./ai_config.BnEV7HHL.js"; import { K as KnowledgeBaseAPI } from "./knowledge_base.CHSLq1jf.js"; import { _ as _export_sfc } from "./_plugin-vue_export-helper.1tPrXgE0.js"; import "./codemirror.CvJAcn2d.js"; const API_PATH = "/application/ai/model"; const AI_MODEL_TYPES = { enterprise_naming: "企业起名", enterprise_renaming: "企业改名", enterprise_scoring: "企业测名", enterprise_scoring_trial: "企业测名试用", personal_naming: "个人起名", personal_renaming: "个人改名", personal_scoring: "个人测名", personal_scoring_trial: "个人测名试用" }; const AI_MODEL_TYPE_GROUPS = { enterprise: { label: "企业服务", types: ["enterprise_naming", "enterprise_renaming", "enterprise_scoring", "enterprise_scoring_trial"] }, personal: { label: "个人服务", types: ["personal_naming", "personal_renaming", "personal_scoring", "personal_scoring_trial"] } }; const AIModelConfigAPI = { // 获取模型配置详情(如果不存在会自动创建默认配置) detail(modelType) { return httpRequest({ url: `${API_PATH}/detail/${modelType}`, method: "get" }); }, // 列表查询 list(query) { return httpRequest({ url: `${API_PATH}/list`, method: "get", params: query }); }, // 更新配置 update(modelType, body) { return httpRequest({ url: `${API_PATH}/update/${modelType}`, method: "put", data: body }); }, // 获取可用模型列表 getAvailableModels(providerId) { return httpRequest({ url: `${API_PATH}/available-models/${providerId}`, method: "get" }); }, // 获取训练对话记录 getMessages(modelType) { return httpRequest({ url: `${API_PATH}/messages/${modelType}`, method: "get" }); }, // 删除单条训练对话记录 deleteMessage(messageId) { return httpRequest({ url: `${API_PATH}/message/${messageId}`, method: "delete" }); }, // 清空训练对话记录 clearMessages(modelType) { return httpRequest({ url: `${API_PATH}/messages/${modelType}`, method: "delete" }); }, // 训练对话(流式输出) async chat(data, signal) { const baseURL = void 0; const token = Auth.getAccessToken(); return fetch(`${baseURL}${API_PATH}/chat`, { method: "POST", headers: { "Content-Type": "application/json", "Authorization": token ? `Bearer ${token}` : "" }, body: JSON.stringify(data), signal }); }, // 起名测试(非流式,一次性返回) test(data) { return httpRequest({ url: `${API_PATH}/test`, method: "post", data }); } }; const _hoisted_1 = { class: "ai-model-container" }; const _hoisted_2 = { class: "config-panel" }; const _hoisted_3 = { class: "model-type-selector" }; const _hoisted_4 = { class: "category-tabs" }; const _hoisted_5 = { class: "type-tabs" }; const _hoisted_6 = { class: "chat-panel" }; const _hoisted_7 = { class: "panel-header" }; const _hoisted_8 = { class: "header-actions" }; const _hoisted_9 = { key: 0, class: "welcome-screen" }; const _hoisted_10 = { class: "welcome-content" }; const _hoisted_11 = { key: 1, class: "messages-list" }; const _hoisted_12 = { class: "message-content" }; const _hoisted_13 = { class: "message-header" }; const _hoisted_14 = ["innerHTML"]; const _hoisted_15 = { class: "message-avatar" }; const _hoisted_16 = { class: "message-avatar" }; const _hoisted_17 = { class: "message-content" }; const _hoisted_18 = { class: "message-header" }; const _hoisted_19 = ["innerHTML"]; const _hoisted_20 = { key: 0, class: "message-item assistant" }; const _hoisted_21 = { class: "message-avatar" }; const _hoisted_22 = { class: "message-content" }; const _hoisted_23 = { class: "message-body" }; const _hoisted_24 = ["innerHTML"]; const _hoisted_25 = { key: 1, class: "typing-indicator" }; const _hoisted_26 = { class: "chat-input" }; const _hoisted_27 = { class: "input-wrapper" }; const _hoisted_28 = { class: "test-dialog-content" }; const _hoisted_29 = { key: 0, class: "test-result" }; const _hoisted_30 = ["innerHTML"]; const _sfc_main = /* @__PURE__ */ defineComponent({ ...{ name: "AIModel", inheritAttrs: false }, __name: "index", setup(__props) { const md = new MarkdownIt({ html: true, linkify: true, typographer: true, breaks: true, highlight(str, lang) { if (lang && HighlightJS.getLanguage(lang)) { try { return `
${HighlightJS.highlight(str, { language: lang, ignoreIllegals: true }).value}`;
} catch {
}
}
return `${md.utils.escapeHtml(str)}`;
}
});
const currentCategory = ref("enterprise");
const currentModelType = ref("enterprise_naming");
const currentGroupTypes = computed(() => {
return AI_MODEL_TYPE_GROUPS[currentCategory.value].types;
});
function getShortLabel(typeKey) {
const label = AI_MODEL_TYPES[typeKey];
return label.replace(/^企业|个人/, "");
}
function handleCategoryChange() {
const firstType = AI_MODEL_TYPE_GROUPS[currentCategory.value].types[0];
currentModelType.value = firstType;
handleModelTypeChange();
}
const configFormRef = ref();
const configForm = reactive({
provider_id: void 0,
model_name: void 0,
system_prompt: "",
temperature: 1,
knowledge_base_ids: []
});
const originalConfig = ref({});
const configLoading = ref(false);
const saveLoading = ref(false);
const messagesLoading = ref(false);
const providerList = ref([]);
const availableModels = ref([]);
const knowledgeBaseList = ref([]);
const messages = ref([]);
const inputMessage = ref("");
const currentResponse = ref("");
const isGenerating = ref(false);
const messagesContainer = ref();
const abortController = ref(null);
const showTestDialog = ref(false);
const testInput = ref("");
const testResult = ref("");
const testLoading = ref(false);
async function loadProviderList() {
try {
const res = await AIProviderAPI.list({ page_no: 1, page_size: 100 });
providerList.value = res.data.data.items;
} catch (error) {
console.error("加载供应商列表失败", error);
}
}
async function loadKnowledgeBaseList() {
try {
const res = await KnowledgeBaseAPI.list({ page_no: 1, page_size: 100, kb_status: 2 });
knowledgeBaseList.value = res.data.data.items;
} catch (error) {
console.error("加载知识库列表失败", error);
}
}
async function loadModelConfig() {
configLoading.value = true;
try {
const res = await AIModelConfigAPI.detail(currentModelType.value);
const data = res.data.data;
Object.assign(configForm, {
provider_id: data.provider_id,
model_name: data.model_name,
system_prompt: data.system_prompt || "",
temperature: data.temperature ?? 1,
knowledge_base_ids: data.knowledge_base_ids || []
});
originalConfig.value = { ...configForm };
if (data.provider_id) {
await loadAvailableModels(data.provider_id);
}
} catch (error) {
console.error("加载模型配置失败", error);
} finally {
configLoading.value = false;
}
}
async function loadAvailableModels(providerId) {
try {
console.log("[DEBUG] 加载模型列表,供应商ID:", providerId);
const res = await AIModelConfigAPI.getAvailableModels(providerId);
console.log("[DEBUG] API 响应:", res.data);
availableModels.value = res.data.data || [];
console.log("[DEBUG] 更新后的模型列表:", availableModels.value);
} catch (error) {
console.error("加载可用模型列表失败", error);
availableModels.value = [];
}
}
async function loadMessages() {
messagesLoading.value = true;
try {
const res = await AIModelConfigAPI.getMessages(currentModelType.value);
messages.value = res.data.data;
scrollToBottom();
} catch (error) {
console.error("加载训练对话记录失败", error);
} finally {
messagesLoading.value = false;
}
}
async function handleProviderChange(providerId) {
console.log("[DEBUG] 供应商变化,新ID:", providerId);
configForm.model_name = void 0;
availableModels.value = [];
if (providerId) {
await loadAvailableModels(providerId);
}
}
async function handleModelTypeChange() {
await Promise.all([loadModelConfig(), loadMessages()]);
}
async function handleSaveConfig() {
saveLoading.value = true;
try {
await AIModelConfigAPI.update(currentModelType.value, configForm);
originalConfig.value = { ...configForm };
ElMessage.success("配置保存成功");
} catch (error) {
console.error("保存配置失败", error);
ElMessage.error("保存配置失败");
} finally {
saveLoading.value = false;
}
}
function isConfigChanged() {
return JSON.stringify(configForm) !== JSON.stringify(originalConfig.value);
}
async function handleSendMessage() {
var _a;
const message = inputMessage.value.trim();
if (!message || isGenerating.value) return;
const configChanged = isConfigChanged();
inputMessage.value = "";
isGenerating.value = true;
currentResponse.value = "";
const tempUserMessageId = -Date.now();
const userMessage = {
id: tempUserMessageId,
model_config_id: 0,
role: "user",
content: message,
created_time: (/* @__PURE__ */ new Date()).toISOString(),
updated_time: (/* @__PURE__ */ new Date()).toISOString()
};
messages.value.push(userMessage);
scrollToBottom();
try {
const chatData = {
model_type: currentModelType.value,
message,
config_changed: configChanged,
config_data: configChanged ? configForm : void 0
};
abortController.value = new AbortController();
const response = await AIModelConfigAPI.chat(chatData, abortController.value.signal);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const reader = (_a = response.body) == null ? void 0 : _a.getReader();
if (!reader) {
throw new Error("无法获取响应流");
}
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value, { stream: true });
currentResponse.value += chunk;
scrollToBottom();
}
if (configChanged) {
originalConfig.value = { ...configForm };
}
if (currentResponse.value) {
const assistantMessage = {
id: -Date.now() - 1,
model_config_id: 0,
role: "assistant",
content: currentResponse.value,
created_time: (/* @__PURE__ */ new Date()).toISOString(),
updated_time: (/* @__PURE__ */ new Date()).toISOString()
};
messages.value.push(assistantMessage);
}
} catch (error) {
if (error.name === "AbortError") {
console.log("用户中断了生成");
if (currentResponse.value) {
const assistantMessage = {
id: -Date.now() - 1,
model_config_id: 0,
role: "assistant",
content: currentResponse.value + "\n\n*[已停止生成]*",
created_time: (/* @__PURE__ */ new Date()).toISOString(),
updated_time: (/* @__PURE__ */ new Date()).toISOString()
};
messages.value.push(assistantMessage);
}
} else {
console.error("发送消息失败", error);
const errorMessage = {
id: -Date.now() - 1,
model_config_id: 0,
role: "assistant",
content: "发送消息失败,请检查配置和网络连接",
created_time: (/* @__PURE__ */ new Date()).toISOString(),
updated_time: (/* @__PURE__ */ new Date()).toISOString()
};
messages.value.push(errorMessage);
}
} finally {
currentResponse.value = "";
isGenerating.value = false;
abortController.value = null;
scrollToBottom();
}
}
function handleStopGenerate() {
if (abortController.value) {
abortController.value.abort();
}
}
async function handleTest() {
const text = testInput.value.trim();
if (!text || testLoading.value) return;
testLoading.value = true;
testResult.value = "";
try {
const res = await AIModelConfigAPI.test({
model_type: currentModelType.value,
text
});
testResult.value = res.data.data;
} catch (error) {
console.error("起名测试失败", error);
ElMessage.error("测试失败,请检查配置和网络连接");
} finally {
testLoading.value = false;
}
}
function handleTestDialogClosed() {
testInput.value = "";
testResult.value = "";
}
async function handleDeleteMessage(messageId) {
try {
await ElMessageBox.confirm("确定删除这条对话记录吗?", "提示", {
type: "warning"
});
await AIModelConfigAPI.deleteMessage(messageId);
messages.value = messages.value.filter((m) => m.id !== messageId);
ElMessage.success("删除成功");
} catch (error) {
if (error !== "cancel") {
console.error("删除消息失败", error);
}
}
}
async function handleClearMessages() {
try {
await ElMessageBox.confirm("确定清空所有对话记录吗?此操作不可恢复。", "提示", {
type: "warning"
});
await AIModelConfigAPI.clearMessages(currentModelType.value);
messages.value = [];
ElMessage.success("对话已清空");
} catch (error) {
if (error !== "cancel") {
console.error("清空对话失败", error);
}
}
}
function processThinkTags(content) {
if (!content) return "";
const thinkRegex = /