Browse Source

添加应用配置

yangg 8 months ago
parent
commit
86f897b60b

+ 1 - 1
.env.development

@@ -2,5 +2,5 @@
 ENV = 'development'
 port = 8080
 # base api
-VUE_APP_BASE_API = 'http://192.168.1.188:8084'
+VUE_APP_BASE_API = 'http://58.246.234.210:8084'
 #192.168.1.199

+ 20 - 1
src/api/knowledge.js

@@ -212,7 +212,7 @@ export function modelList(data) {
 
 export function configSave(data) {
   return request({
-    url: 'chatbot/configSave/',
+    url: 'chatbot/configCreart/',
     method: 'post',
     data
   })
@@ -265,3 +265,22 @@ export function configDelete(data) {
       data
     })
   } 
+
+  /* 应用配置类型 */
+  export function application_types(data) {
+    return request({
+      url: '/chatbot/application-types/',
+      method: 'post',
+      data
+    })
+  } 
+
+  /* 设置为默认 /chatbot/configuration/set_default/ */
+
+  export function set_default(data) {
+    return request({
+      url: '/chatbot/configuration/set_default/',
+      method: 'post',
+      data
+    })
+  } 

+ 20 - 1
src/components/webAi/css/ChatBox.css

@@ -384,7 +384,7 @@ textarea {
 }
 
 .card {
-  width: calc(20% - 15px);
+  width: calc(20% - 16px);
   background-color: #fff;
   height: 300px;
   border-radius: 8px;
@@ -464,4 +464,23 @@ textarea {
 .header_btn{
   display: flex;
   justify-content: flex-end;
+}
+
+::v-deep .el-form--inline .el-form-item{
+  display: block;
+}
+.truncate-text {
+  max-width: calc(100% - 30px); /* 调整这个值以适应下拉菜单的宽度 */
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+/* Add this to your existing styles */
+.knowledge-base-name {
+  display: inline-block;
+  max-width: 100px; /* Adjust this value as needed */
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+  margin-right: 5px; /* Add some spacing between spans */
 }

+ 639 - 57
src/components/webAi/index.vue

@@ -15,21 +15,12 @@
           :rules="rules"
           ref="AIformRef"
           class="demo-form-inline"
-          style="margin-top: 15px"
-          label-position="right"
+          style="margin-top: 15px; margin-left: 50px"
+          label-position="top"
           label-width="90px"
         >
           <el-row :gutter="24">
-            <el-col :span="8">
-              <!--  <el-form-item label="模型库:" prop="modelLibrary">
-              <el-select
-                v-model="AIform.modelLibrary"
-                placeholder="ollama"
-                style="width: 100%"
-              >
-                <el-option label="ollama" value="ollama"></el-option>
-              </el-select>
-            </el-form-item> -->
+            <el-col :span="12">
               <el-form-item label="应用名称:" prop="chat_name">
                 <el-input
                   v-model="AIform.chat_name"
@@ -37,16 +28,26 @@
                 ></el-input>
               </el-form-item>
             </el-col>
-            <el-col :span="8">
-              <!-- <el-form-item label="模型类型:" prop="model_type">
-              <el-select
-                v-model="AIform.model_type"
-                placeholder="请输入选择"
-                style="width: 100%"
-              >
-                <el-option label="chat" value="chat"></el-option>
-              </el-select>
-            </el-form-item> -->
+            <el-col :span="12">
+              <el-form-item label="应用类型:" prop="application_type">
+                <el-select
+                  v-model="AIform.application_type"
+                  placeholder="应用类型"
+                  style="width: 100%"
+                  clearable
+                >
+                  <el-option
+                    v-for="(item, index) in appTypeList"
+                    :label="item.label"
+                    :value="item.value"
+                    :key="index"
+                  ></el-option>
+                </el-select>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
               <el-form-item label="模型名称:" prop="model_name">
                 <el-select
                   v-model="AIform.model_name"
@@ -63,7 +64,7 @@
                 </el-select>
               </el-form-item>
             </el-col>
-            <el-col :span="8">
+            <el-col :span="12">
               <el-form-item label="知识库:" prop="knowledge_base_names">
                 <el-select
                   v-model="AIform.knowledge_base_names"
@@ -84,7 +85,7 @@
             ></el-col>
           </el-row>
           <el-row :gutter="24">
-            <el-col :span="8">
+            <el-col :span="12">
               <el-form-item label="文档目录:" prop="document_directories">
                 <el-select
                   v-model="AIform.document_directories"
@@ -103,7 +104,7 @@
                   ></el-option>
                 </el-select> </el-form-item
             ></el-col>
-            <el-col :span="8">
+            <el-col :span="12">
               <el-form-item label="文  档:" prop="documents">
                 <el-select
                   v-model="AIform.documents"
@@ -123,13 +124,279 @@
                 </el-select>
               </el-form-item>
             </el-col>
-            <el-col :span="8">
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
               <el-form-item label="描 述:">
                 <el-input
                   v-model="AIform.role_description"
+                  placeholder="请输入描述"
+                  type="textarea"
+                ></el-input>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="温度:" prop="temperature">
+                <div style="display: flex; justify-content: space-between;">
+                  <el-slider
+                  style="width: 60%;"
+                    v-model="AIform.temperature"
+                    :min="0"
+                    :max="1"
+                    :step="0.1"
+                  ></el-slider>
+                  <el-input-number
+                    v-model="AIform.temperature"
+                    :min="0"
+                    :max="1"
+                  ></el-input-number>
+                </div>
+                <div class="hint">
+                  控制生成文本的随机性,0为最保守,1为最创新
+                </div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="最大token数:" prop="max_tokens">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                style="width: 60%;"
+                  v-model="AIform.max_tokens"
+                  :min="1"
+                  :max="4096"
+                  :step="1"
+                ></el-slider>
+                <el-input-number
+                    v-model="AIform.max_tokens"
+                    :min="0"
+                    :max="4096"
+                    :step="1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">限制生成文本的最大长度</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="核采样参数:" prop="top_p">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                 style="width: 60%;"
+                  v-model="AIform.top_p"
+                  :min="0"
+                  :max="1"
+                  :step="0.1"
+                ></el-slider>
+                <el-input-number
+                    v-model="AIform.top_p"
+                    :min="0"
+                    :max="1"
+                    :step="0.1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">控制词汇多样性,1为考虑所有可能性</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="重复内容惩罚:" prop="frequency_penalty">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                style="width: 60%;"
+                  v-model="AIform.frequency_penalty"
+                  :min="-2"
+                  :max="2"
+                  :step="0.1"
+                ></el-slider>
+                <el-input-number
+                    v-model="AIform.frequency_penalty"
+                    :min="-2"
+                    :max="2"
+                    :step="0.1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">防止重复,正值减少重复,负值增加重复</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="新话题偏好:" prop="presence_penalty">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                  style="width: 60%;"
+                  v-model="AIform.presence_penalty"
+                  :min="-2"
+                  :max="2"
+                  :step="0.1"
+                ></el-slider>
+                <el-input-number
+                    v-model="AIform.presence_penalty"
+                    :min="-2"
+                    :max="2"
+                    :step="0.1"
+                  ></el-input-number>
+                </div>
+                <div class="hint">正值鼓励新话题,负值保持话题一致性</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="响应格式:" prop="response_format">
+                <el-input
+                  v-model="AIform.response_format"
+                  placeholder="text"
+                ></el-input>
+                <div class="hint">指定AI响应的格式,如text, json等</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="上下文窗口:" prop="context_window">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                  style="width: 60%;"
+                  v-model="AIform.context_window"
+                  :min="1"
+                  :max="4096"
+                ></el-slider>
+                <el-input-number
+                    v-model="AIform.presence_penalty"
+                    :min="1"
+                    :max="4096"
+                    :step="1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">AI考虑的上下文token数量</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="会话ID:" prop="session_id">
+                <el-input
+                  v-model="AIform.session_id"
+                  placeholder="可选"
+                ></el-input>
+                <div class="hint">特定会话的唯一标识符,如果有的话</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="语言:" prop="language">
+                <el-select v-model="AIform.language" style="width: 100%">
+                  <el-option label="中文" value="zh"></el-option>
+                  <el-option label="English" value="en"></el-option>
+                  <el-option label="日本語" value="ja"></el-option>
+                  <el-option label="한국어" value="ko"></el-option>
+                  <el-option label="Français" value="fr"></el-option>
+                  <el-option label="Deutsch" value="de"></el-option>
+                </el-select>
+                <div class="hint">选择AI响应的主要语言</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="请求超时:" prop="timeout">
+                <el-input-number
+                  v-model="AIform.timeout"
+                  :min="1"
+                  :max="60"
+                ></el-input-number>
+                <div class="hint">设置请求的最大等待时间(秒)</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="角色名称:" prop="role_name">
+                <el-input
+                  v-model="AIform.role_name"
+                  placeholder="例如: 客服专员"
+                ></el-input>
+                <div class="hint">为AI助手设定一个角色名称</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row :gutter="24">
+            <el-col :span="24">
+              <el-form-item label="角色描述:" prop="role_description">
+                <el-input
+                  v-model="AIform.role_description"
+                  type="textarea"
+                  :rows="3"
+                  placeholder="例如: 你是一位专业的客服专员,负责解答客户关于我们产品和服务的问题。"
+                ></el-input>
+                <div class="hint">详细描述AI助手的角色和职责</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="角色权限:" prop="role_permissions">
+                <el-input
+                  v-model="AIform.role_permissions"
+                  placeholder='["回答产品问题", "处理退换货请求", "升级复杂问题"]'
+                ></el-input>
+                <div class="hint">输入JSON数组,列出AI助手的具体权限</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="自定义变量:" prop="custom_variables">
+                <el-input
+                  v-model="AIform.custom_variables"
+                  placeholder='{"custom_greeting": "很高兴为您服务!", "company_name": "ABC公司"}'
+                ></el-input>
+                <div class="hint">
+                  输入JSON对象,定义可在提示模板中使用的自定义变量
+                </div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row :gutter="24">
+            <el-col :span="24">
+              <el-form-item label="自定义提示模板:" prop="custom_prompt">
+                <el-input
+                  v-model="AIform.custom_prompt"
                   type="textarea"
-                  style="width: 350px"
+                  :rows="6"
+                  placeholder="使用以下上下文来回答问题。如果你不知道答案,就说你不知道,不要试图编造答案。
+                    上下文: {context}
+                    人类: {question}
+                    AI助手: 让我根据提供的上下文来回答你的问题。{custom_greeting}"
                 ></el-input>
+                <div class="hint">
+                  自定义AI助手的回答模板,可使用变量如{context}, {question}等
+                </div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item
+                label="是否启用API_key:"
+                prop="generate_new_api_key"
+              >
+                <el-switch
+                  v-model="AIform.generate_new_api_key"
+                  active-color="#13ce66"
+                  inactive-color="#ff4949"
+                >
+                </el-switch>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="是否设为默认:" prop="is_default">
+                <el-switch
+                  v-model="AIform.is_default"
+                  active-color="#13ce66"
+                  inactive-color="#ff4949"
+                >
+                </el-switch>
               </el-form-item>
             </el-col>
           </el-row>
@@ -146,12 +413,6 @@
               <span>{{ getDocumentNames }}</span>
             </p>
           </div>
-          <!-- <el-button
-              type="primary"
-              class="generate-button"
-              @click="generateApplication"
-              >生成应用</el-button
-            > -->
         </div>
       </div>
       <span slot="footer" class="dialog-footer">
@@ -174,7 +435,7 @@
       <div class="card-container">
         <div class="card" v-for="(card, index) in knowledgeBases" :key="index">
           <div class="card-header">
-            <h2>{{ card.chat_name }}</h2>
+            <h2 class="truncate-text">{{ card.chat_name }}</h2>
             <el-dropdown>
               <span class="el-dropdown-link">
                 <i class="el-icon-more"></i>
@@ -198,6 +459,7 @@
               <span
                 v-for="(count, type) in card.knowledge_base_names"
                 :key="type"
+                class="knowledge-base-name"
                 >{{ count }}</span
               >
             </div>
@@ -213,7 +475,17 @@
               <span @click="openChatDialog(card)" style="cursor: pointer"
                 >进入应用</span
               >
-              <span style="margin-left: 20px">默认选择</span>
+              <span
+                v-if="card.is_default"
+                style="margin-left: 20px; cursor: pointer; color: #97a8be"
+                >已默认</span
+              >
+              <span
+                v-else
+                @click="setDefault(card)"
+                style="margin-left: 20px; cursor: pointer"
+                >设为默认</span
+              >
             </div>
             <!-- <span class="update-time"></span> -->
           </div>
@@ -296,9 +568,11 @@
         :rules="rules"
         ref="editFormRef"
         label-width="120px"
+        style="margin: 20px 50px"
+        label-position="top"
       >
         <el-row :gutter="24">
-          <el-col :span="8">
+          <el-col :span="12">
             <el-form-item label="应用名称:" prop="chat_name">
               <el-input
                 v-model="editForm.chat_name"
@@ -315,7 +589,26 @@
               </el-select>
             </el-form-item> -->
           </el-col>
-          <el-col :span="8">
+          <el-col :span="12">
+            <el-form-item label="应用类型:" prop="application_type">
+              <el-select
+                v-model="editForm.application_type"
+                placeholder="应用类型"
+                style="width: 100%"
+                clearable
+              >
+                <el-option
+                  v-for="(item, index) in appTypeList"
+                  :label="item.label"
+                  :value="item.value"
+                  :key="index"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
             <el-form-item label="模型名称:" prop="model_name">
               <el-select
                 v-model="editForm.model_name"
@@ -341,7 +634,7 @@
               </el-select>
             </el-form-item> -->
           </el-col>
-          <el-col :span="8">
+          <el-col :span="12">
             <el-form-item label="知识库:" prop="knowledge_base_names">
               <el-select
                 v-model="editForm.knowledge_base_names"
@@ -363,7 +656,7 @@
           </el-col>
         </el-row>
         <el-row :gutter="24">
-          <el-col :span="8">
+          <el-col :span="12">
             <el-form-item label="文档目录:" prop="document_directories">
               <el-select
                 v-model="editForm.document_directories"
@@ -377,7 +670,7 @@
                 "
                 @change="handleEditDirectoryChange"
                 clearable
-                  filterable
+                filterable
               >
                 <el-option
                   v-for="(dir, index) in editDirectoryList"
@@ -388,16 +681,16 @@
               </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="8">
+          <el-col :span="12">
             <el-form-item label="文  档:" prop="documents">
               <el-select
                 v-model="editForm.documents"
                 multiple
                 placeholder="请选择文档"
                 style="width: 100%"
-                :disabled="editForm.document_directories==''"
+                :disabled="editForm.document_directories == ''"
                 clearable
-                  filterable
+                filterable
               >
                 <el-option
                   v-for="(doc, index) in editDocumentList"
@@ -408,13 +701,276 @@
               </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="8">
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
             <el-form-item label="描 述:">
               <el-input
                 v-model="editForm.role_description"
+                placeholder="请输入描述"
+                type="textarea"
+              ></el-input>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="温度:" prop="temperature">
+                <div style="display: flex; justify-content: space-between;">
+                  <el-slider
+                  style="width: 60%;"
+                    v-model="editForm.temperature"
+                    :min="0"
+                    :max="1"
+                    :step="0.1"
+                  ></el-slider>
+                  <el-input-number
+                    v-model="editForm.temperature"
+                    :min="0"
+                    :max="1"
+                  ></el-input-number>
+                </div>
+                <div class="hint">
+                  控制生成文本的随机性,0为最保守,1为最创新
+                </div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="最大token数:" prop="max_tokens">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                style="width: 60%;"
+                  v-model="editForm.max_tokens"
+                  :min="1"
+                  :max="4096"
+                  :step="1"
+                ></el-slider>
+                <el-input-number
+                    v-model="editForm.max_tokens"
+                    :min="0"
+                    :max="4096"
+                    :step="1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">限制生成文本的最大长度</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="核采样参数:" prop="top_p">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                 style="width: 60%;"
+                  v-model="editForm.top_p"
+                  :min="0"
+                  :max="1"
+                  :step="0.1"
+                ></el-slider>
+                <el-input-number
+                    v-model="editForm.top_p"
+                    :min="0"
+                    :max="1"
+                    :step="0.1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">控制词汇多样性,1为考虑所有可能性</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="重复内容惩罚:" prop="frequency_penalty">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                style="width: 60%;"
+                  v-model="editForm.frequency_penalty"
+                  :min="-2"
+                  :max="2"
+                  :step="0.1"
+                ></el-slider>
+                <el-input-number
+                    v-model="editForm.frequency_penalty"
+                    :min="-2"
+                    :max="2"
+                    :step="0.1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">防止重复,正值减少重复,负值增加重复</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="新话题偏好:" prop="presence_penalty">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                  style="width: 60%;"
+                  v-model="editForm.presence_penalty"
+                  :min="-2"
+                  :max="2"
+                  :step="0.1"
+                ></el-slider>
+                <el-input-number
+                    v-model="editForm.presence_penalty"
+                    :min="-2"
+                    :max="2"
+                    :step="0.1"
+                  ></el-input-number>
+                </div>
+                <div class="hint">正值鼓励新话题,负值保持话题一致性</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="响应格式:" prop="response_format">
+                <el-input
+                  v-model="editForm.response_format"
+                  placeholder="text"
+                ></el-input>
+                <div class="hint">指定AI响应的格式,如text, json等</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+
+          <el-row :gutter="24">
+            <el-col :span="12">
+              <el-form-item label="上下文窗口:" prop="context_window">
+                <div style="display: flex; justify-content: space-between;">
+                <el-slider
+                  style="width: 60%;"
+                  v-model="editForm.context_window"
+                  :min="1"
+                  :max="4096"
+                ></el-slider>
+                <el-input-number
+                    v-model="editForm.presence_penalty"
+                    :min="1"
+                    :max="4096"
+                    :step="1"
+                  ></el-input-number>
+              </div>
+                <div class="hint">AI考虑的上下文token数量</div>
+              </el-form-item>
+            </el-col>
+            <el-col :span="12">
+              <el-form-item label="会话ID:" prop="session_id">
+                <el-input
+                  v-model="editForm.session_id"
+                  placeholder="可选"
+                ></el-input>
+                <div class="hint">特定会话的唯一标识符,如果有的话</div>
+              </el-form-item>
+            </el-col>
+          </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="语言:" prop="language">
+              <el-select v-model="editForm.language" style="width: 100%">
+                <el-option label="中文" value="zh"></el-option>
+                <el-option label="English" value="en"></el-option>
+                <el-option label="日本語" value="ja"></el-option>
+                <el-option label="한국어" value="ko"></el-option>
+                <el-option label="Français" value="fr"></el-option>
+                <el-option label="Deutsch" value="de"></el-option>
+              </el-select>
+              <div class="hint">选择AI响应的主要语言</div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="请求超时:" prop="timeout">
+              <el-input-number
+                v-model="editForm.timeout"
+                :min="1"
+                :max="60"
+              ></el-input-number>
+              <div class="hint">设置请求的最大等待时间(秒)</div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="角色名称:" prop="role_name">
+              <el-input
+                v-model="editForm.role_name"
+                placeholder="例如: 客服专员"
+              ></el-input>
+              <div class="hint">为AI助手设定一个角色名称</div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="24">
+          <el-col :span="24">
+            <el-form-item label="角色描述:" prop="role_description">
+              <el-input
+                v-model="editForm.role_description"
+                type="textarea"
+                :rows="3"
+                placeholder="例如: 你是一位专业的客服专员,负责解答客户关于我们产品和服务的问题。"
+              ></el-input>
+              <div class="hint">详细描述AI助手的角色和职责</div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="角色权限:" prop="role_permissions">
+              <el-input
+                v-model="editForm.role_permissions"
+                placeholder='["回答产品问题", "处理退换货请求", "升级复杂问题"]'
+              ></el-input>
+              <div class="hint">输入JSON数组,列出AI助手的具体权限</div>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="自定义变量:" prop="custom_variables">
+              <el-input
+                v-model="editForm.custom_variables"
+                placeholder='{"custom_greeting": "很高兴为您服务!", "company_name": "ABC公司"}'
+              ></el-input>
+              <div class="hint">
+                输入JSON对象,定义可在提示模板中使用的自定义变量
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+
+        <el-row :gutter="24">
+          <el-col :span="24">
+            <el-form-item label="自定义提示模板:" prop="custom_prompt">
+              <el-input
+                v-model="editForm.custom_prompt"
                 type="textarea"
-                style="width: 350px"
+                :rows="6"
+                placeholder="使用以下上下文来回答问题。如果你不知道答案,就说你不知道,不要试图编造答案。
+                    上下文: {context}
+                    人类: {question}
+                    AI助手: 让我根据提供的上下文来回答你的问题。{custom_greeting}"
               ></el-input>
+              <div class="hint">
+                自定义AI助手的回答模板,可使用变量如{context}, {question}等
+              </div>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="24">
+          <el-col :span="12">
+            <el-form-item label="是否启用API_key:" prop="generate_new_api_key">
+              <el-switch
+                v-model="editForm.generate_new_api_key"
+                active-color="#13ce66"
+                inactive-color="#ff4949"
+              >
+              </el-switch>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="是否设为默认:" prop="is_default">
+              <el-switch
+                v-model="editForm.is_default"
+                active-color="#13ce66"
+                inactive-color="#ff4949"
+              >
+              </el-switch>
             </el-form-item>
           </el-col>
         </el-row>
@@ -432,18 +988,44 @@
       :append-to-body="true"
     >
       <div v-if="viewForm" style="padding: 0 20px">
-        <p><strong>应用名称:</strong> {{ viewForm.chat_name }}</p>
-        <p><strong>模型名称:</strong> {{ viewForm.model_name }}</p>
-        <p>
-          <strong>知识库:</strong>
-          {{ viewForm.knowledge_base_names.join(", ") }}
-        </p>
-        <p>
-          <strong>文档目录:</strong>
-          {{ viewForm.document_directories.join(", ") }}
-        </p>
-        <p><strong>文档:</strong> {{ viewForm.documents.join(", ") }}</p>
-        <p><strong>描述:</strong> {{ viewForm.role_description }}</p>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <p><strong>应用名称:</strong> {{ viewForm.chat_name }}</p>
+            <p><strong>模型名称:</strong> {{ viewForm.model_name }}</p>
+            <p>
+              <strong>知识库:</strong>
+              {{ viewForm.knowledge_base_names.join(", ") }}
+            </p>
+            <p>
+              <strong>文档目录:</strong>
+              {{ viewForm.document_directories.join(", ") }}
+            </p>
+            <p><strong>文档:</strong> {{ viewForm.documents.join(", ") }}</p>
+            <p><strong>描述:</strong> {{ viewForm.role_description }}</p>
+            <p><strong>温度:</strong> {{ viewForm.temperature }}</p>
+            <p><strong>最大token数:</strong> {{ viewForm.max_tokens }}</p>
+            <p><strong>核采样参数:</strong> {{ viewForm.top_p }}</p>
+            <p>
+              <strong>重复内容惩罚:</strong> {{ viewForm.frequency_penalty }}
+            </p>
+            <p><strong>新话题偏好:</strong> {{ viewForm.presence_penalty }}</p>
+          </el-col>
+          <el-col :span="12">
+            <p><strong>响应格式:</strong> {{ viewForm.response_format }}</p>
+            <p><strong>上下文窗口:</strong> {{ viewForm.context_window }}</p>
+            <p><strong>会话ID:</strong> {{ viewForm.session_id }}</p>
+            <p><strong>语言:</strong> {{ viewForm.language }}</p>
+            <p><strong>请求超时:</strong> {{ viewForm.timeout }}</p>
+            <p><strong>角色名称:</strong> {{ viewForm.role_name }}</p>
+            <p><strong>角色描述:</strong> {{ viewForm.role_description }}</p>
+            <p>
+              <strong>角色权限:</strong>
+              {{ viewForm.role_permissions.join(", ") }}
+            </p>
+            <p><strong>自定义变量:</strong> {{ viewForm.custom_variables }}</p>
+            <p><strong>自定义提示模板:</strong> {{ viewForm.custom_prompt }}</p>
+          </el-col>
+        </el-row>
       </div>
     </el-dialog>
     <!-- 添加 LoginModal 组件 -->

+ 87 - 34
src/components/webAi/js/ChatBox.js

@@ -1,7 +1,7 @@
 import LoginModal from "@/components/LoginModal";
 import MarkdownIt from "markdown-it";
 import { pcInnerAi,getMinioURl } from "@/api/api";
-import {modelList,listBuckets,selectTypeList,getBucketContents,configSave,configList,configDelete} from "@/api/knowledge"
+import {modelList,listBuckets,selectTypeList,getBucketContents,configSave,configList,configDelete,application_types,set_default} from "@/api/knowledge"
 import axios from 'axios';
 const md = new MarkdownIt();
 
@@ -46,18 +46,23 @@ export default {
         documents: [],
         temperature: 0.7,
         max_tokens: 150,
-         top_p: 1.0,
-         frequency_penalty: 0.0,
-         presence_penalty: 0.0,
-         response_format: "text",
-         context_window: 2048,
-         user_id: "user123",
-         session_id: "session456",
-         language: "en",
-         timeout: 30,
-         role_name: "Admin",
-         role_description: "",
-         role_permissions: ["read", "write", "delete"]
+        top_p: 1.0,
+        frequency_penalty: 0.0,
+        presence_penalty: 0.0,
+        response_format: "text",
+        context_window: 2048,
+        user_id: "user123",
+        session_id: "session456",
+        language: "en",
+        timeout: 30,
+        role_name: "Admin",
+        role_description: "",
+        role_permissions: "",
+        custom_variables:"",
+        custom_prompt:'',
+        application_type: "",
+        is_default: false,
+        generate_new_api_key: true  
       },
       /* 模型库 */
       modelList:[],
@@ -117,7 +122,12 @@ export default {
         timeout: 30,
         role_name: "Admin",
         role_description: "",
-        role_permissions: ["read", "write", "delete"]
+        role_permissions:"['read', 'write', 'delete']",
+        custom_variables:'',
+        custom_prompt:'',
+        application_type: "",
+        is_default: false,
+        generate_new_api_key: true  
       },
       editDirectoryList: [],
       editDocumentList: [],
@@ -125,6 +135,8 @@ export default {
       viewDialogVisible: false,
       viewForm: null,
       session_id:"",
+       /* 配置类型列表 */
+       appTypeList:[]
     };
   },
   created() {
@@ -174,6 +186,12 @@ export default {
     }
   },
   methods: {
+    /* 设为默认 */
+    setDefault(val){
+      set_default({id:val.id}).then(res=>{
+        
+      })
+    },
     /* 重置表单 */
     resetForm() {
       if (this.$refs.AIformRef) {
@@ -192,20 +210,26 @@ export default {
         top_p: 1.0,
         frequency_penalty: 0.0,
         presence_penalty: 0.0,
-        response_format: "text",
+        response_format: "",
         context_window: 2048,
-        user_id: "user123",
-        session_id: "session456",
+        user_id: "",
+        session_id: "",
         language: "en",
         timeout: 30,
         role_name: "Admin",
         role_description: "",
-        role_permissions: ["read", "write", "delete"]
+        role_permissions: "['read', 'write', 'delete']",
+        custom_variables:'',
+        custom_prompt:'',
+        application_type: "",
+        is_default: false,
+        generate_new_api_key: true 
       };
     },
     /* 新增聊天应用 */
     addApplication() {
-      this.resetForm();
+       this.resetForm();
+      /*console.log(this.AIform); */
       this.applicationDialogVisible = true;
     },
 
@@ -228,6 +252,7 @@ export default {
     },
     /* 查看 */
     viewApplication(card) {
+      console.log(card);
       this.viewForm = { ...card };
       this.viewDialogVisible = true;
     },
@@ -283,15 +308,39 @@ export default {
     },
     /* 编辑 */
     editApplication(card) {
-        // 根据 card 的数据填充 editForm
-      
+      // 根据 card 的数据填充 editForm
       this.editForm = JSON.parse(JSON.stringify(card)); // 深拷贝以避免直接修改原对象
+      
+      // 处理 knowledge_base_names
       this.editForm.knowledge_base_names = this.editForm.knowledge_base_names.map(name => {
         const kb = this.kneList.find(kb => kb.name === name);
         return kb ? kb.id : name; // 如果找不到对应的知识库,保留原名称
       });
+
+      // 处理 role_permissions
+      if (this.editForm.role_permissions) {
+        if (typeof this.editForm.role_permissions !== 'string') {
+          try {
+            this.editForm.role_permissions = JSON.stringify(this.editForm.role_permissions);
+          } catch (error) {
+            console.error('Error stringifying role_permissions:', error);
+            this.editForm.role_permissions = '';
+          }
+        }
+      } else {
+        this.editForm.role_permissions = '';
+      }
+
+      // 处理 custom_variables
+      if (this.editForm.custom_variables) {
+        this.editForm.custom_variables = JSON.stringify(this.editForm.custom_variables);     
+      } else {
+        this.editForm.custom_variables = {};
+      }
+
       this.editDialogVisible = true;
       console.log(this.editForm);
+
       // 加载知识库对应的目录列表
       this.loadEditDirectoryList(this.editForm.knowledge_base_names);
    
@@ -351,23 +400,22 @@ export default {
     
     loadEditDocumentList(val) {
       // 找到选中目录的名称
-      const selectedDirectoryName = val[0];
+      const selectedDirectoryName = val;
       const id= this.directoryList.find(el=>el.id==val)
       // 从 kneList 中找到对应的知识库
       const selectedKnowledgeBase = this.kneList.find(kb => 
-        kb.name === this.editForm.knowledge_base_names[0]
+        kb.id === this.editForm.knowledge_base_names[0]
       );
     
       /* if (!selectedKnowledgeBase) {
         console.error('No matching knowledge base found');
         return;
       } */
-    
       let queryForm = {
         page: 1,
         pageSize: 9999,
-        bucket_id:selectedDirectoryName === '全部' ? this.editForm.knowledge_base_names[0]:id.kb_id,
-        doc_type_id: selectedDirectoryName === '全部' ? 0 : this.getDirectoryIdByName(selectedDirectoryName),
+        bucket_id:selectedKnowledgeBase.id,
+        doc_type_id: selectedDirectoryName === '001' ? '' : this.getDirectoryIdByName(selectedDirectoryName),
       };
     
       getBucketContents(queryForm).then(res => {
@@ -453,7 +501,6 @@ export default {
     },
     /*  */
     openChatDialog(card) {
-      console.log(card);
       this.currentChat = card;
       this.chatDialogVisible = true;
       // 可能需要在这里初始化聊天记录或执行其他操作
@@ -462,7 +509,7 @@ export default {
       this.messages.push({
         user: "bot",
         messageType: "TEXT",
-        message: `欢迎使用 ${card.name} 聊天应用`,
+        message: `欢迎使用 ${card.chat_name} 聊天应用`,
         html: "",
         time: "",
         done: true,
@@ -509,7 +556,7 @@ export default {
             console.log('Converted form:', convertedForm);
 
             // 使用 axios 发送 POST 请求
-            const response = await axios.post(`${process.env.VUE_APP_BASE_API}/chatbot/configSave/`, convertedForm, {
+            const response = await axios.post(`${process.env.VUE_APP_BASE_API}/chatbot/configCreart/`, convertedForm, {
               headers: {
                 'Content-Type': 'application/json'
               }
@@ -615,7 +662,7 @@ export default {
         page: 1,
         pageSize: 9999,
         bucket_id:val=='001'?this.bucket_id : id.kb_id,//this.bucket_id,
-        doc_type_id: val=='001'?0 :val,
+        doc_type_id: val=='001'?'' :val,
       }
       getBucketContents(queryForm).then(res=>{
         this.documentList=res.data.documents
@@ -718,7 +765,7 @@ newChat() {
         }
       }
       const chatId = this.getUuid();
-      const wsUrl ='http://58.246.234.210:8084/chatbot/chat'//this.wsUrl//'http://58.246.234.210:7860/api/v1/run/3ef7369e-b617-40d2-9e2e-54f3ee76ed2e?stream=false'
+      const wsUrl =`${process.env.VUE_APP_BASE_API}/chatbot/chat`//this.wsUrl//'http://58.246.234.210:7860/api/v1/run/3ef7369e-b617-40d2-9e2e-54f3ee76ed2e?stream=false'
       let message = this.userInput.trim();
       if (message) {
         // Markdown换行:在每个换行符之前添加两个空格
@@ -760,6 +807,7 @@ newChat() {
               message: message,
               /* output_type: "chat",
               input_type: "chat", */
+              chat_config_id:this.currentChat.id,
               user_id:this.$store.state.user.id,
               session_id:this.session_id||''
              /* tweaks:this.tweaks  {
@@ -779,7 +827,7 @@ newChat() {
           const result = await response.json();
           this.session_id=result.data.session_id
           console.log(result.status);
-          if (result.status!==200) {
+          if (result.status!=='success') {
             const errorText = await response.text(); // 获取错误文本
             throw new Error(
               `HTTP error! status: ${response.status}, message: ${errorText}`
@@ -823,7 +871,7 @@ newChat() {
       try {
         console.log("Sending to backend:", JSON.stringify(idObject));
 
-        const response = await axios.post('http://58.246.234.210:8084/milvus/getMinioURl', idObject, {
+        const response = await axios.post(`${process.env.VUE_APP_BASE_API}/milvus/getMinioURl`, idObject, {
           headers: {
             'Content-Type': 'application/json'
           }
@@ -872,7 +920,7 @@ newChat() {
     },
   
     async handleResponse(value, existingMessage) {
-      const data = value.data.response//outputs[0].outputs[0].results.message;
+      const data = value.data.answer//outputs[0].outputs[0].results.message;
       
       existingMessage.messageType = data;
       /* existingMessage.time = data.timestamp; */
@@ -992,6 +1040,11 @@ newChat() {
         this.knowledgeBases=res.data
         console.log(res);
       })
+      /* 获取应用类型 */
+      application_types().then(res=>{
+        if(res.status!==200) return
+        this.appTypeList=res.data.application_types
+      })
     }
   },
   updated() {