| @@ -191,7 +191,6 @@ import { | |||||
| ElFormItem, | ElFormItem, | ||||
| ElInput, | ElInput, | ||||
| ElButton, | ElButton, | ||||
| ElUpload, | |||||
| ElContainer, | ElContainer, | ||||
| ElHeader, | ElHeader, | ||||
| ElSlider, | ElSlider, | ||||
| @@ -199,7 +198,7 @@ import { | |||||
| ElOption, | ElOption, | ||||
| ElMessage | ElMessage | ||||
| } from 'element-plus' | } from 'element-plus' | ||||
| import { ArrowDown, UploadFilled } from '@element-plus/icons-vue' | |||||
| import { ArrowDown } from '@element-plus/icons-vue' | |||||
| import uploadIcon from '../assets/material-symbols--upload-sharp.png' | import uploadIcon from '../assets/material-symbols--upload-sharp.png' | ||||
| import { Icon } from '@iconify/vue' | import { Icon } from '@iconify/vue' | ||||
| import { useRoute, useRouter } from 'vue-router' | import { useRoute, useRouter } from 'vue-router' | ||||
| @@ -221,17 +220,6 @@ const agentForm = reactive({ | |||||
| max_tokens: 4096 | max_tokens: 4096 | ||||
| }) | }) | ||||
| const fakeRAGOptions = ref([ | |||||
| { | |||||
| value: 'knowledge_base', | |||||
| label: '知识库1' | |||||
| }, | |||||
| { | |||||
| value: 'knowledge_base1', | |||||
| label: '知识库2' | |||||
| } | |||||
| ]) | |||||
| const selectedRAGOption = ref('') | |||||
| const onUploadIcon = () => { | const onUploadIcon = () => { | ||||
| const input = document.createElement('input') | const input = document.createElement('input') | ||||
| @@ -383,7 +371,6 @@ onMounted(() => { | |||||
| import { useConversation } from './conversationApi' | import { useConversation } from './conversationApi' | ||||
| import { Tool } from './toolConfig' | import { Tool } from './toolConfig' | ||||
| import IconifyIconOffline from '../components/ReIcon/src/iconifyIconOffline' | |||||
| const { handleDebugConversation, debugConversationConfig } = useConversation() | const { handleDebugConversation, debugConversationConfig } = useConversation() | ||||
| @@ -21,8 +21,8 @@ export const conversationSummary = async (chatConversation: string) => { | |||||
| agent_enable: false, | agent_enable: false, | ||||
| tool_config: [], | tool_config: [], | ||||
| chat_model_config: { | chat_model_config: { | ||||
| api_key: "", | |||||
| base_url: "", | |||||
| api_key: "sk-cERDW9Fr2ujq8D2qYck9cpc9MtPytN26466bunfYXZVZWV7Y", | |||||
| base_url: "https://api.chatanywhere.tech/v1/", | |||||
| is_openai: true, | is_openai: true, | ||||
| llm_model: { | llm_model: { | ||||
| "gpt-4o": { | "gpt-4o": { | ||||
| @@ -1,10 +1,10 @@ | |||||
| export class JsonCollapse extends HTMLElement { | export class JsonCollapse extends HTMLElement { | ||||
| private header: HTMLDivElement | null = null; | |||||
| private content: HTMLDivElement | null = null; | |||||
| private header: HTMLDivElement | null = null | |||||
| private content: HTMLDivElement | null = null | |||||
| constructor() { | constructor() { | ||||
| super(); | |||||
| this.attachShadow({ mode: "open" }); | |||||
| super() | |||||
| this.attachShadow({ mode: 'open' }) | |||||
| this.shadowRoot!.innerHTML = ` | this.shadowRoot!.innerHTML = ` | ||||
| <style> | <style> | ||||
| :host { | :host { | ||||
| @@ -26,60 +26,59 @@ export class JsonCollapse extends HTMLElement { | |||||
| background-color: #f9f9f9; | background-color: #f9f9f9; | ||||
| } | } | ||||
| </style> | </style> | ||||
| <div id="header">${this.getAttribute("label") || "JSON"}</div> | |||||
| <div id="header">${this.getAttribute('label') || 'JSON'}</div> | |||||
| <div id="content"></div> | <div id="content"></div> | ||||
| `; | |||||
| ` | |||||
| this.header = this.shadowRoot!.querySelector("#header"); | |||||
| this.content = this.shadowRoot!.querySelector("#content"); | |||||
| this.header = this.shadowRoot!.querySelector('#header') | |||||
| this.content = this.shadowRoot!.querySelector('#content') | |||||
| this.header?.addEventListener("click", this.toggleContent.bind(this)); | |||||
| this.header?.addEventListener('click', this.toggleContent.bind(this)) | |||||
| } | } | ||||
| connectedCallback() { | connectedCallback() { | ||||
| this.renderJson(); | |||||
| this.renderJson() | |||||
| } | } | ||||
| static get observedAttributes() { | static get observedAttributes() { | ||||
| return ["data-json"]; | |||||
| return ['data-json'] | |||||
| } | } | ||||
| // eslint-disable-next-line @typescript-eslint/no-unused-vars | // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||||
| attributeChangedCallback(name: string, _oldValue: string, _newValue: string) { | attributeChangedCallback(name: string, _oldValue: string, _newValue: string) { | ||||
| if (name === "data-json") { | |||||
| this.renderJson(); | |||||
| if (name === 'data-json') { | |||||
| this.renderJson() | |||||
| } | } | ||||
| } | } | ||||
| private toggleContent() { | private toggleContent() { | ||||
| if (this.content) { | if (this.content) { | ||||
| this.content.style.display = this.content.style.display === "block" ? "none" : "block"; | |||||
| this.content.style.display = this.content.style.display === 'block' ? 'none' : 'block' | |||||
| } | } | ||||
| } | } | ||||
| private renderJson() { | private renderJson() { | ||||
| const json = this.getAttribute("data-json"); | |||||
| const json = this.getAttribute('data-json') | |||||
| if (this.content) { | if (this.content) { | ||||
| try { | try { | ||||
| const obj = JSON.parse(json || "{}"); | |||||
| const formattedJson = JSON.stringify(obj, null, 2); | |||||
| this.content.textContent = formattedJson; | |||||
| const obj = JSON.parse(json || '{}') | |||||
| const formattedJson = JSON.stringify(obj, null, 2) | |||||
| this.content.textContent = formattedJson | |||||
| } catch (e) { | } catch (e) { | ||||
| this.content.textContent = "Invalid JSON"; | |||||
| this.content.textContent = 'Invalid JSON' | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| export class MessageCollapse extends HTMLElement { | export class MessageCollapse extends HTMLElement { | ||||
| private header: HTMLDivElement | null = null; | |||||
| private content: HTMLDivElement | null = null; | |||||
| private isCollapsed = true; | |||||
| private header: HTMLDivElement | null = null | |||||
| private content: HTMLDivElement | null = null | |||||
| private isCollapsed = true | |||||
| constructor() { | constructor() { | ||||
| super(); | |||||
| this.attachShadow({ mode: "open" }); | |||||
| super() | |||||
| this.attachShadow({ mode: 'open' }) | |||||
| this.shadowRoot!.innerHTML = ` | this.shadowRoot!.innerHTML = ` | ||||
| <style> | <style> | ||||
| :host { | :host { | ||||
| @@ -103,51 +102,53 @@ export class MessageCollapse extends HTMLElement { | |||||
| </style> | </style> | ||||
| <div id="header"></div> | <div id="header"></div> | ||||
| <div id="content"></div> | <div id="content"></div> | ||||
| `; | |||||
| ` | |||||
| this.header = this.shadowRoot!.querySelector("#header"); | |||||
| this.content = this.shadowRoot!.querySelector("#content"); | |||||
| this.header = this.shadowRoot!.querySelector('#header') | |||||
| this.content = this.shadowRoot!.querySelector('#content') | |||||
| this.header?.addEventListener("click", this.toggleContent.bind(this)); | |||||
| this.header?.addEventListener('click', this.toggleContent.bind(this)) | |||||
| } | } | ||||
| connectedCallback() { | connectedCallback() { | ||||
| this.renderMessage(); | |||||
| this.renderMessage() | |||||
| } | } | ||||
| static get observedAttributes() { | static get observedAttributes() { | ||||
| return ["data-message"]; | |||||
| return ['data-message'] | |||||
| } | } | ||||
| attributeChangedCallback(name: string, _oldValue: string, _newValue: string) { | attributeChangedCallback(name: string, _oldValue: string, _newValue: string) { | ||||
| if (name === "data-message") { | |||||
| this.renderMessage(); | |||||
| console.log(_oldValue, _newValue) | |||||
| if (name === 'data-message') { | |||||
| this.renderMessage() | |||||
| } | } | ||||
| } | } | ||||
| private toggleContent() { | private toggleContent() { | ||||
| if (this.content) { | if (this.content) { | ||||
| this.isCollapsed = !this.isCollapsed; | |||||
| this.content.style.display = this.isCollapsed ? "none" : "block"; | |||||
| this.header!.textContent = this.isCollapsed ? this.getCollapsedMessage() : this.getFullMessage(); | |||||
| this.isCollapsed = !this.isCollapsed | |||||
| this.content.style.display = this.isCollapsed ? 'none' : 'block' | |||||
| this.header!.textContent = this.isCollapsed | |||||
| ? this.getCollapsedMessage() | |||||
| : this.getFullMessage() | |||||
| } | } | ||||
| } | } | ||||
| private renderMessage() { | private renderMessage() { | ||||
| const message = this.getAttribute("data-message") || ""; | |||||
| const message = this.getAttribute('data-message') || '' | |||||
| if (this.header && this.content) { | if (this.header && this.content) { | ||||
| this.header.textContent = this.getCollapsedMessage(); | |||||
| this.content.textContent = message; | |||||
| this.header.textContent = this.getCollapsedMessage() | |||||
| this.content.textContent = message | |||||
| } | } | ||||
| } | } | ||||
| private getCollapsedMessage() { | private getCollapsedMessage() { | ||||
| const message = this.getAttribute("data-message") || ""; | |||||
| return message.length > 50 ? message.substring(0, 50) + "..." : message; | |||||
| const message = this.getAttribute('data-message') || '' | |||||
| return message.length > 50 ? message.substring(0, 50) + '...' : message | |||||
| } | } | ||||
| private getFullMessage() { | private getFullMessage() { | ||||
| return this.getAttribute("data-message") || ""; | |||||
| return this.getAttribute('data-message') || '' | |||||
| } | } | ||||
| } | } | ||||
| @@ -36,7 +36,7 @@ | |||||
| <el-menu :default-active="currentConversation?.conversation_id" class="conversation-menu"> | <el-menu :default-active="currentConversation?.conversation_id" class="conversation-menu"> | ||||
| <div v-contextmenu:conversationMenu> | <div v-contextmenu:conversationMenu> | ||||
| <el-menu-item | <el-menu-item | ||||
| v-for="conversation in conversations" | |||||
| v-for="conversation in [...conversations].reverse()" | |||||
| :key="conversation.conversation_id" | :key="conversation.conversation_id" | ||||
| :index="conversation.conversation_id" | :index="conversation.conversation_id" | ||||
| @click="handleSwitchConversation(conversation)" | @click="handleSwitchConversation(conversation)" | ||||
| @@ -48,7 +48,14 @@ | |||||
| </el-menu> | </el-menu> | ||||
| </el-scrollbar> | </el-scrollbar> | ||||
| <div class="aside-buttons"> | <div class="aside-buttons"> | ||||
| <span class="agent-list align-middle small-font" @click="toKBConfig">知识库管理</span> | |||||
| <div> | |||||
| <span | |||||
| style="margin-right: 20%" | |||||
| class="agent-list align-middle small-font" | |||||
| @click="toKBConfig" | |||||
| >知识库管理</span | |||||
| > | |||||
| </div> | |||||
| <el-divider direction="horizontal" border-style="dashed" /> | <el-divider direction="horizontal" border-style="dashed" /> | ||||
| <span | <span | ||||
| class="agent-list align-middle small-font" | class="agent-list align-middle small-font" | ||||
| @@ -260,9 +267,10 @@ import { useKnowledgeBase } from './knowledgebase/kbapi' | |||||
| const { knowledgeBases, fetchAllKnowledgeBases } = useKnowledgeBase() | const { knowledgeBases, fetchAllKnowledgeBases } = useKnowledgeBase() | ||||
| const selectedKnowledgeBase = ref('') | const selectedKnowledgeBase = ref('') | ||||
| watch(selectedKnowledgeBase, (newKnowledgeBase) => { | |||||
| localConversationConfig.value.knowledge_base = newKnowledgeBase | |||||
| }) | |||||
| // 知识库设置暂时不可用 | |||||
| // watch(selectedKnowledgeBase, (newKnowledgeBase) => { | |||||
| // localConversationConfig.value.knowledge_base = newKnowledgeBase | |||||
| // }) | |||||
| /******************************************************************************/ | /******************************************************************************/ | ||||
| @@ -297,6 +305,9 @@ onMounted(async () => { | |||||
| // 对话相关 | // 对话相关 | ||||
| await fetchConversations() | await fetchConversations() | ||||
| // 进入界面直接创建一个对话 | |||||
| await createConversation(-1) | |||||
| // Deep Chat 初始化 | // Deep Chat 初始化 | ||||
| chatElementRef = document.getElementById('chat-element') as DeepChat | chatElementRef = document.getElementById('chat-element') as DeepChat | ||||
| @@ -961,7 +972,9 @@ const chatInputConfig = () => { | |||||
| background-color: #ffffff; /* Changed to white */ | background-color: #ffffff; /* Changed to white */ | ||||
| cursor: pointer; | cursor: pointer; | ||||
| } | } | ||||
| .aside-buttons div { | |||||
| text-align: center; | |||||
| } | |||||
| .main-container { | .main-container { | ||||
| display: flex; | display: flex; | ||||
| flex-direction: column; | flex-direction: column; | ||||
| @@ -1035,7 +1048,8 @@ const chatInputConfig = () => { | |||||
| font-weight: bold; | font-weight: bold; | ||||
| display: flex; | display: flex; | ||||
| align-items: center; | align-items: center; | ||||
| justify-content: center; | |||||
| justify-content: flex-start; | |||||
| margin-top: -10px; | |||||
| } | } | ||||
| .align-middle { | .align-middle { | ||||
| @@ -72,8 +72,8 @@ | |||||
| /> | /> | ||||
| <NewKBDialog | <NewKBDialog | ||||
| v-model:visible="isShowKnowledgeBaseDialog" | v-model:visible="isShowKnowledgeBaseDialog" | ||||
| v-model:form="knowledgeBaseForm" | |||||
| :loading="loading" | :loading="loading" | ||||
| :form="knowledgeBaseForm" | |||||
| @save="handleSaveKnowledgeBaseClick" | @save="handleSaveKnowledgeBaseClick" | ||||
| /> | /> | ||||
| </div> | </div> | ||||
| @@ -7,16 +7,32 @@ | |||||
| > | > | ||||
| <el-form :model="form" label-width="120px"> | <el-form :model="form" label-width="120px"> | ||||
| <el-form-item label="知识库名称"> | <el-form-item label="知识库名称"> | ||||
| <el-input v-model="form.knowledge_base_name" /> | |||||
| <el-input | |||||
| v-model=" | |||||
| // eslint-disable-next-line vue/no-mutating-props | |||||
| form.knowledge_base_name | |||||
| " | |||||
| /> | |||||
| </el-form-item> | </el-form-item> | ||||
| <el-form-item label="向量库类型"> | <el-form-item label="向量库类型"> | ||||
| <el-select v-model="form.vector_store_type"> | |||||
| <el-select | |||||
| v-model=" | |||||
| // eslint-disable-next-line vue/no-mutating-props | |||||
| form.vector_store_type | |||||
| " | |||||
| > | |||||
| <el-option label="Faiss" value="faiss" /> | <el-option label="Faiss" value="faiss" /> | ||||
| <!-- Add other options if needed --> | <!-- Add other options if needed --> | ||||
| </el-select> | </el-select> | ||||
| </el-form-item> | </el-form-item> | ||||
| <el-form-item label="知识库描述"> | <el-form-item label="知识库描述"> | ||||
| <el-input v-model="form.kb_info" type="textarea" /> | |||||
| <el-input | |||||
| v-model=" | |||||
| // eslint-disable-next-line vue/no-mutating-props | |||||
| form.kb_info | |||||
| " | |||||
| type="textarea" | |||||
| /> | |||||
| </el-form-item> | </el-form-item> | ||||
| </el-form> | </el-form> | ||||
| </div> | </div> | ||||