liudong
2024-07-30 e6666db4911ee0214cc57564ded0cbb9534220a4
知识库页面测试和配置接口调用开发
7个文件已修改
389 ■■■■■ 已修改文件
.idea/codeStyles/Project.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/interceptor.ts 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/kbList.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/style/global.less 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dmx/knowledgeLib/config.vue 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dmx/knowledgeLib/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dmx/knowledgeLib/test.vue 151 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.idea/codeStyles/Project.xml
@@ -3,7 +3,7 @@
    <HTMLCodeStyleSettings>
      <option name="HTML_SPACE_INSIDE_EMPTY_TAG" value="true" />
    </HTMLCodeStyleSettings>
    <JSCodeStyleSettings>
    <JSCodeStyleSettings version="0">
      <option name="FORCE_SEMICOLON_STYLE" value="true" />
      <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
      <option name="FORCE_QUOTE_STYlE" value="true" />
@@ -11,7 +11,7 @@
      <option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
      <option name="SPACES_WITHIN_IMPORTS" value="true" />
    </JSCodeStyleSettings>
    <TypeScriptCodeStyleSettings>
    <TypeScriptCodeStyleSettings version="0">
      <option name="FORCE_SEMICOLON_STYLE" value="true" />
      <option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
      <option name="FORCE_QUOTE_STYlE" value="true" />
src/api/interceptor.ts
@@ -37,7 +37,7 @@
      }
      config.headers.Authorization = `${authorization}`;
    }
    config.headers.Authorization = 'Ijg3NmFjZjJlNGIzMzExZWY4NzI0MDI0MmFjMTIwMDA2Ig.ZqNvxw.Kgp8PcT4n2cxpzxFrYHttO4i2Eo';
    config.headers.Authorization = 'IjFjOWY3OWM0NGUxYzExZWZhMDk0MDI0MmFjMTIwMDA2Ig.ZqhQ-w.JmA9ESUTd_JKK2wtZ4PVgVmCNj8';
    return config;
  },
  (error) => {
src/api/kbList.ts
@@ -110,9 +110,18 @@
  return axios.post('/api/v1/document/change_status', params);
}
// 模型列表接口
export function queryModelList(params) {
  return axios.get('/api/v1/llm/list', {
    params
  });
}
// 测试接口
export function kbretrievalTest(params) {
  return axios.post('/api/v1/chunk/retrieval_test', params);
}
src/assets/style/global.less
@@ -95,4 +95,8 @@
.container {
    padding: 0 20px 20px 20px;
}
.arco-form .arco-slider{
  display: flex;
}
src/views/dmx/knowledgeLib/config.vue
@@ -7,12 +7,9 @@
    </div>
    <div class="main-container-lf">
      <div class="main-container-lf-down">
        <a-form ref="formRef" :size="form.size" :model="form" :style="{width:'100%'}" layout="vertical"
        <a-form ref="formRef" :rules="rules" :model="form" :style="{width:'100%'}" layout="vertical"
                @submit="handleSubmit">
          <a-form-item field="name" label="知识库名称"
                       :rules="[{required:true,message:'name is required'},{minLength:5,message:'must be greater than 5 characters'}]"
                       :validate-trigger="['change','input']"
          >
          <a-form-item field="name" label="知识库名称">
            <a-input v-model="form.name" placeholder="请输入" />
          </a-form-item>
          <a-form-item field="section" label="知识库图片">
@@ -27,8 +24,8 @@
                <template #upload-button>
                  <div
                    :class="`arco-upload-list-item${
            file && file.status === 'error' ? ' arco-upload-list-item-error' : ''
          }`"
                      file && file.status === 'error' ? ' arco-upload-list-item-error' : ''
                    }`"
                  >
                    <div
                      class="arco-upload-list-picture custom-upload-avatar"
@@ -44,11 +41,11 @@
                        type="circle"
                        size="mini"
                        :style="{
                position: 'absolute',
                left: '50%',
                top: '50%',
                transform: 'translateX(-50%) translateY(-50%)',
              }"
                          position: 'absolute',
                          left: '50%',
                          top: '50%',
                          transform: 'translateX(-50%) translateY(-50%)',
                        }"
                      />
                    </div>
                    <div class="arco-upload-picture-card" v-else>
@@ -65,21 +62,21 @@
          <a-form-item field="section" label="描述">
            <a-textarea placeholder="" allow-clear />
          </a-form-item>
          <a-form-item field="section" label="语言" :rules="[{match:/section one/,message:'请选择'}]">
            <a-select v-model="form.section" placeholder="请选择" allow-clear>
              <a-option value="0">中文</a-option>
              <a-option value="1">英文</a-option>
            </a-select>
          </a-form-item>
<!--          <a-form-item field="section" label="语言" :rules="[{match:/section one/,message:'请选择'}]">-->
<!--            <a-select v-model="form.section" placeholder="请选择" allow-clear>-->
<!--              <a-option value="0">中文</a-option>-->
<!--              <a-option value="1">英文</a-option>-->
<!--            </a-select>-->
<!--          </a-form-item>-->
          <a-form-item field="section" label="嵌入模型" :rules="[{match:/section one/,message:'请选择'}]">
            <a-select v-model="form.section" placeholder="请选择" allow-clear>
            <a-select v-model="form.embd_id" placeholder="请选择" allow-clear>
              <a-option value="section one">Section One</a-option>
              <a-option value="section two">Section Two</a-option>
              <a-option value="section three">Section Three</a-option>
            </a-select>
          </a-form-item>
          <a-form-item field="section" label="解析方法" :rules="[{match:/section one/,message:'请选择'}]">
            <a-select v-model="form.section" placeholder="请选择" allow-clear>
            <a-select v-model="form.parser_id" placeholder="请选择" allow-clear>
              <a-option value="section one">Section One</a-option>
              <a-option value="section two">Section Two</a-option>
              <a-option value="section three">Section Three</a-option>
@@ -87,9 +84,9 @@
          </a-form-item>
          <a-form-item field="slider" label="块Token数"
                       :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
            <a-slider v-model="form.score" :max="10" />
            <a-input-number v-model="form.score" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"
                            placeholder="Please Enter" class="input-demo" :min="10" :max="1000" />
            <a-slider v-model="form.chunk_token_num" :max="100"  show-input />
<!--            <a-input-number v-model="form.score" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"-->
<!--                            placeholder="Please Enter" class="input-demo" :min="10" :max="1000" />-->
          </a-form-item>
          <a-form-item field="slider" label="布局识别" :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
            <a-space direction="vertical" size="large">
@@ -98,38 +95,38 @@
          </a-form-item>
          <a-form-item field="raptor" label="使用召回增强RAPTOR策略">
            <a-space direction="vertical" size="large">
              <a-switch v-model="form.raptor" @change="onChangeRAPTOR" />
              <a-switch v-model="form.use_raptor" @change="onChangeRAPTOR" />
            </a-space>
          </a-form-item>
          <div v-if="form.raptor">
            <a-form-item field="section" label="提示词">
          <div v-if="form.use_raptor">
            <a-form-item field="prompt" label="提示词">
              <a-textarea
                v-model="form.prompt"
                style="height: 10rem;border: 1px solid  var(--color-fill-3);border-radius: 4px" placeholder=""
                allow-clear />
                style="height: 10rem;border: 1px solid  var(--color-fill-3);border-radius: 4px"
                placeholder="请填写提示词" />
            </a-form-item>
            <a-form-item field="slider" label="最大token数"
                         :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
              <a-slider v-model="form.score" :max="10" />
              <a-input-number v-model="form.score" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"
              <a-slider v-model="form.max_token" :min="1" :max="1000" />
              <a-input-number v-model="form.max_token" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"
                              placeholder="Please Enter" class="input-demo" :min="10" :max="1000" />
            </a-form-item>
            <a-form-item field="slider" label="阈值" :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
              <a-slider v-model="form.score" :max="10" />
              <a-input-number v-model="form.score" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"
                              placeholder="Please Enter" class="input-demo" :min="10" :max="1000" />
              <a-slider v-model="form.threshold" :max="1" />
              <a-input-number v-model="form.threshold" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"
                              placeholder="Please Enter" class="input-demo" :min="0" :max="1" />
            </a-form-item>
            <a-form-item field="slider" label="最大聚类数"
                         :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
              <a-slider v-model="form.score" :max="10" />
              <a-input-number v-model="form.score" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"
              <a-slider v-model="form.max_cluster" :max="1000" />
              <a-input-number v-model="form.max_cluster" :style="{width:'100px',marginLeft:'2rem',borderRadius:'4px'}"
                              placeholder="Please Enter" class="input-demo" :min="10" :max="1000" />
            </a-form-item>
            <a-form-item field="slider" label="随机种子"
            <a-form-item field="slider" label="随机种子" v-model="form.random_seed"
                         :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
              <a-input-number v-model="form.score" :style="{width:'300px',marginRight:'1rem',borderRadius:'4px'}"
              <a-input-number v-model="form.random_seed" :style="{width:'300px',marginRight:'1rem',borderRadius:'4px'}"
                              placeholder="请输入" class="input-demo" :min="10" :max="100" />
              <a-button type="primary" @click="">
              <a-button type="primary" @click="randomNumber">
                <icon-plus />
              </a-button>
@@ -152,7 +149,7 @@
    <div class="main-container-rt">
      <section data-inspector-line="34" data-inspector-column="4"
               data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx"
               class="categoryPanelWrapper___yI4rY" ><h4
               class="categoryPanelWrapper___yI4rY"><h4
        class="ant-typography topTitle___tNiB9 css-dev-only-do-not-override-1wxecgq" data-inspector-line="37"
        data-inspector-column="10"
        data-inspector-relative-path="src\pages\add-knowledge\components\knowledge-setting\category-panel.tsx">"General"
@@ -203,94 +200,55 @@
import { onMounted, onBeforeMount, reactive, ref } from "vue";
import { Message } from "@arco-design/web-vue";
const props = defineProps({
  record: {
    type: Object,
    default: () => {
      return {};
    }
  }
const props = defineProps(["kbtenantInfo", "kbobj", "kbdetail"]);
// const emit =  defineEmits(['upTabdateItem'])
const kbtenantInfo = props.kbtenantInfo;
let parser_ids = kbtenantInfo.parser_ids.split(",").map((item) => {
  const [value1, value2] = item.split(":");
  return {
    name: value2,
    value: value1
  };
});
const visible = ref(false);
const configIsShow = ref(false);
const loading = ref(false);
const formRef = ref(null);
const form = reactive({
  size: "medium",
  name: "",
  age: undefined,
  section: "0",
  province: "haidian",
  options: [],
  date: "",
  time: "",
  radio: "radio one",
  slider: 5,
  score: 5,
  switch: false,
  multiSelect: ["section one"],
  treeSelect: "",
  raptor: false,
  prompt: '请总结以下段落。 小心数字,不要编造。 段落如下:\n' +
    '      {cluster_content}\n' +
    '以上就是你需要总结的内容。',
  name: '',
  avatar: '',//
  max_token: 698,
  threshold: 0.32,
  max_cluster: 233,
  random_seed: 1500,
  chunk_token_num: 128,
  use_raptor: false,
  pages: {},
  prompt: "请总结以下段落。 小心数字,不要编造。 段落如下:\n" +
    "      {cluster_content}\n" +
    "以上就是你需要总结的内容。",
  description: "",
  language: "English",
  permission: "",
  embd_id: "",
  parser_id: "",
  layout_recognize: true
});
const options = [
  {
    value: "beijing",
    label: "Beijing",
    children: [
      {
        value: "chaoyang",
        label: "ChaoYang",
        children: [
          {
            value: "datunli",
            label: "Datunli"
          }
        ]
      },
      {
        value: "haidian",
        label: "Haidian"
      },
      {
        value: "dongcheng",
        label: "Dongcheng"
      },
      {
        value: "xicheng",
        label: "XiCheng"
      }
    ]
  },
  {
    value: "shanghai",
    label: "Shanghai",
    children: [
      {
        value: "shanghaishi",
        label: "Shanghai",
        children: [
          {
            value: "huangpu",
            label: "Huangpu"
          }
        ]
      }
    ]
  }
];
const rules = {
  name: [
    {
      required: true,
      message:'知识库名称不允许为空',
    },
  ],
}
const sayHello = () => {
  Message.info("hello");
};
let visible = ref(false);
let loading = ref(false);
const formRef = ref(null);
const modelList = ref({});
const file = ref();
const onChange = (_, currentFile) => {
@@ -308,9 +266,15 @@
  console.log("values:", values, "\nerrors:", errors);
};
function randomNumber() {
  // 生成一个介于min和max之间的随机整数(包含min和max)
  const min = 1; // 最小值
  const max = 10000; // 最大值
  form.random_seed = Math.floor(Math.random() * (max - min + 1)) + min;
}
const onChangeRAPTOR = () => {
  console.log(form.raptor);
  console.log(form);
};
@@ -374,6 +338,7 @@
  //background: #626aea;
  background: #ffffff;
  padding-top: 80px;
  &-lf {
    width: 40%;
    //height: 100%;
@@ -432,7 +397,8 @@
    border-radius: 10px;
    overflow: hidden;
    padding: 20px;
    section{
    section {
      width: 100%;
      color: #333333;
    }
src/views/dmx/knowledgeLib/index.vue
@@ -26,7 +26,6 @@
                  <a-popconfirm content="确定删除吗?" @ok="deleteKnowledge(tab.id)" type="warning">
                    <span style="cursor: pointer;color: #0960bd;font-size: 12px"><icon-delete />删除</span>
                  </a-popconfirm>
                </template>
              </a-popover>
            </div>
@@ -234,12 +233,12 @@
          </a-tab-pane>
          <a-tab-pane key="2" :title="t('dmx.list.test')">
            <div class="rt-container-main">
              <test ></test>
              <test :kbobj="kbobj"></test>
            </div>
          </a-tab-pane>
          <a-tab-pane key="3" :title="t('dmx.list.disposition')">
            <div class="rt-container-main">
              <config ></config>
              <config :kbtenantInfo="kbtenantInfo" :kbdetail="kbdetail" :kbobj="kbobj"></config>
            </div>
          </a-tab-pane>
        </a-tabs>
src/views/dmx/knowledgeLib/test.vue
@@ -6,25 +6,37 @@
        <div class="main-container-lf-down">
          <div style="color: #999;">最后一步! 成功后,剩下的就交给Infiniflow AI吧。</div>
          <a-divider style="margin-top: 10px" />
          <a-form ref="formRef" :size="form.size" :model="form" :style="{width:'100%'}" layout="vertical"  @submit="handleSubmit">
            <a-form-item field="slider" label="相似度阈值" :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
              <a-slider v-model="form.slider" :max="10" />
          <a-form ref="formRef"  :model="form" :style="{width:'100%'}" layout="vertical"  @submit="handleSubmit">
            <a-form-item field="similarity_threshold" label="相似度阈值">
              <a-slider v-model="form.similarity_threshold"  :format-tooltip="formatter" />
            </a-form-item>
            <a-form-item field="slider" label="关键字相似度权重" :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
              <a-slider v-model="form.score" :max="10" />
              <a-slider v-model="form.vector_similarity_weight"  :format-tooltip="formatter" />
            </a-form-item>
            <a-form-item field="section" label="Rerank模型" :rules="[{match:/section one/,message:'请选择'}]">
              <a-select v-model="form.section" placeholder="请选择" allow-clear>
                <a-option value="section one">Section One</a-option>
                <a-option value="section two">Section Two</a-option>
                <a-option value="section three">Section Three</a-option>
              </a-select>
              <a-space direction="vertical" size="large">
                <a-select :size="'large'" :default-value="form.rerank_id" :style="{width:'100%'}" placeholder="请选择 ..." allow-clear>
                  <a-optgroup  :label="index" v-for="(item,index) in modelList" :key=index>
                    <a-option
                      v-for="(obj) in item"
                      :key=obj.fid
                      :disabled="!obj.available"
                      :value="obj.llm_name"
                    >
                      {{obj.llm_name}}
                    </a-option>
                  </a-optgroup>
                </a-select>
              </a-space>
            </a-form-item>
            <a-form-item field="slider" label="Top-K" :rules="[{type:'number', min:5,message:'slider is min than 5'}]">
              <a-slider v-model="form.top_k" :min="1" :max="2048" />
            </a-form-item>
            <a-form-item field="section" :rules="[{match:/section one/,message:'请选择'}]">
              <div class="main-container-form-item-extra">
                <div class="main-container-form-item-extra-top">测试文本</div>
                <div class="main-container-form-item-extra-down">
                  <a-textarea style="height: 10rem;border: 1px solid  var(--color-fill-3);border-radius: 4px" placeholder="" allow-clear/>
                  <a-textarea v-model="form.question" style="height: 10rem;border: 1px solid  var(--color-fill-3);border-radius: 4px" placeholder="" allow-clear/>
                </div>
                <div class="main-container-form-item-extra-btn">
                  <a-button type="primary" html-type="submit">测试</a-button>
@@ -73,95 +85,50 @@
<script lang="ts" setup>
import { onMounted ,onBeforeMount, reactive, ref } from "vue";
import { Message } from '@arco-design/web-vue';
import { kbretrievalTest, queryModelList } from "@/api/kbList";
const props = defineProps({
  record: {
  kbobj: {
    type: Object,
    default: () => {
      return {}
    }
  }
})
const visible = ref(false);
const loading = ref(false);
let visible = ref(false);
let loading = ref(false);
const formRef = ref(null);
const form = reactive({
  size: 'medium',
  name: '',
  age: undefined,
  section: '',
  province: 'haidian',
  options: [],
  date: '',
  time: '',
  radio: 'radio one',
  slider: 5,
  score: 5,
  switch: false,
  multiSelect: ['section one'],
  treeSelect: ''
const modelList = ref({});
let form = reactive({
  kb_id: props.kbobj.kb_id,
  page: 1,
  question: '',
  rerank_id: '',
  similarity_threshold: 20,
  size: 10,
  top_k: 1024,
  vector_similarity_weight: 30,
});
const options = [
  {
    value: 'beijing',
    label: 'Beijing',
    children: [
      {
        value: 'chaoyang',
        label: 'ChaoYang',
        children: [
          {
            value: 'datunli',
            label: 'Datunli',
          },
        ],
      },
      {
        value: 'haidian',
        label: 'Haidian',
      },
      {
        value: 'dongcheng',
        label: 'Dongcheng',
      },
      {
        value: 'xicheng',
        label: 'XiCheng',
      },
    ],
  },
  {
    value: 'shanghai',
    label: 'Shanghai',
    children: [
      {
        value: 'shanghaishi',
        label: 'Shanghai',
        children: [
          {
            value: 'huangpu',
            label: 'Huangpu',
          },
        ],
      },
    ],
  },
];
const formatter = (value) => {
  return value / 100
};
const sayHello = () => {
  Message.info('hello');
};
const handleSubmit = ({values, errors}) => {
  console.log('values:', values, '\nerrors:', errors)
const handleSubmit = async ({values, errors}) => {
  if (!form.question){
    return
  }
  form.similarity_threshold = form.similarity_threshold/100;
  form.vector_similarity_weight = form.vector_similarity_weight/100;
   const data = await kbretrievalTest(form);
  console.log(data);
}
const handleClick = () => {
@@ -190,14 +157,28 @@
    txt: '',// 备注
  });
  formRef.value.resetFields();
  console.log(props.record, 'record');
  // console.log(props.record, 'record');
  // if(props.edit == 'edit'){
  //   Object.assign(form,props.record);
  // }
}
const queryModel = async (params) => {
  try {
    const data = await queryModelList(params);
    console.log(data.data, '大模型列表');
    modelList.value = {
      BAAI: [data.data.BAAI[1]],
      Jina: data.data.Jina,
      youdao: data.data.youdao
    };
  } catch (err) {
    // you can report use errorHandler or other
  } finally {
  }
};
onBeforeMount(()=>{
  queryModel({})
})
onMounted(()=>{