Browse Source

导入编辑合并

zhengnaiwen_citu 2 tháng trước cách đây
mục cha
commit
cd1f0c6797

+ 20 - 0
src/api/dataChart.js

@@ -91,6 +91,21 @@ export function createTrainingData (param) {
   return http.post('/vanna/v0/training_data/create', param)
 }
 
+// 更新训练数据
+export function updateTrainingData (param) {
+  return http.post('/vanna/v0/training_data/update', param)
+}
+
+// 导入训练数据
+export function uploadTrainingData (param) {
+  return http.upload('/vanna/v0/training_data/upload', param)
+}
+
+// 合并训练数据
+export function combineTrainData (param) {
+  return http.post('/vanna/v0/training_data/combine', param)
+}
+
 // 删除训练数据,支持批量操作
 export function deleteTrainingData (param) {
   return http.post('/vanna/v0/training_data/delete', param)
@@ -164,3 +179,8 @@ export function uploadTasksList (taskId, param) {
 export function getTasksLog (taskId, param) {
   return http.post(`/vanna/v0/data_pipeline/tasks/${taskId}/logs/query`, param)
 }
+
+// PgVector 表备份
+export function getPgBackup (param) {
+  return http.post('/vanna/v0/data_pipeline/vector/backup', param)
+}

+ 23 - 0
src/router/routes.js

@@ -2477,6 +2477,29 @@ export default {
           name: 'model-train',
           alwaysShow: 0
         },
+        // {
+        //   hidden: 0,
+        //   icon: '',
+        //   type: 1,
+        //   title: 'PgVector表管理',
+        //   path: '/model-system/pg-vector',
+        //   children: [],
+        //   enName: 'pg vector',
+        //   redirect: '',
+        //   active: '',
+        //   label: 'PgVector表管理',
+        //   sort: 10,
+        //   component: 'modelSystem/pgVector',
+        //   meta: {
+        //     roles: [],
+        //     enName: 'pg vector',
+        //     icon: '',
+        //     title: 'PgVector表管理',
+        //     fullScreen: false
+        //   },
+        //   name: 'pg vector',
+        //   alwaysShow: 0
+        // },
         {
           hidden: 0,
           icon: '',

+ 24 - 3
src/views/modelSystem/modelTrainManage/index.vue

@@ -47,12 +47,21 @@
         :loading="tableLoading"
         :total="total"
         :page-info="pageInfo"
-        @edit="handleEdit"
         @delete="handleDelete"
         @pageHandleChange="pageHandleChange"
         @sort="handleSort"
         @add="handleAdd"
       >
+        <template #navBtn>
+          <v-btn color="primary" class="buttons mr-3" rounded elevation="5" @click="handleCombine">
+            <v-icon left>mdi-vector-combine</v-icon>
+            合并
+          </v-btn>
+          <v-btn color="primary" class="buttons" rounded elevation="5" @click="handleUpload">
+            <v-icon left>mdi-import</v-icon>
+            导入
+          </v-btn>
+        </template>
         <template #question="{ item }">
           <span style="max-width: 300px;" class="d-inline-block text-truncate">{{ item.question }}</span>
         </template>
@@ -61,11 +70,14 @@
         </template>
         <template #actions="{ item }">
           <v-btn text color="primary" @click="handleDetails(item)">查看</v-btn>
+          <v-btn text color="primary" @click="handleEdit(item)">编辑</v-btn>
           <v-btn text color="error" @click="handleDelete([item.id])">删除</v-btn>
         </template>
       </MTable>
     </div>
     <ModelTrainManageEdit ref="ModelTrainManageEditRefs" @success="onOpen"></ModelTrainManageEdit>
+    <ModelTrainManageCombine ref="modelTrainManageCombineRefs" @success="init"></ModelTrainManageCombine>
+    <ModelTrainManageUpload ref="modelTrainManageUploadRefs" @success="init"></ModelTrainManageUpload>
   </div>
 </template>
 
@@ -78,12 +90,16 @@ import {
 import MTable from '@/components/List/table.vue'
 import MSearch from '@/components/Filter'
 import ModelTrainManageEdit from './modelTrainManageEdit.vue'
+import ModelTrainManageCombine from './modelTrainManageCombine.vue'
+import ModelTrainManageUpload from './modelTrainManageUpload.vue'
 export default {
   name: 'ModelTrain',
   components: {
     MTable,
     MSearch,
-    ModelTrainManageEdit
+    ModelTrainManageEdit,
+    ModelTrainManageUpload,
+    ModelTrainManageCombine
   },
   data () {
     return {
@@ -161,7 +177,6 @@ export default {
         sort_order: undefined
       }
       if (this.orders.length) {
-        console.log(this.orders[0])
         Object.assign(orders, {
           sort_by: this.orders[0].column.replace(/`/g, ''),
           sort_order: this.orders[0].asc ? 'asc' : 'desc'
@@ -193,6 +208,12 @@ export default {
     handleDetails (item) {
       this.$refs.ModelTrainManageEditRefs.open(item, true)
     },
+    handleCombine () {
+      this.$refs.modelTrainManageCombineRefs.open()
+    },
+    async handleUpload (file) {
+      this.$refs.modelTrainManageUploadRefs.open()
+    },
     pageHandleChange (index) {
       this.pageInfo.current = index
       this.init()

+ 98 - 0
src/views/modelSystem/modelTrainManage/modelTrainManageCombine.vue

@@ -0,0 +1,98 @@
+<template>
+  <m-dialog title="合并训练数据" :visible.sync="show" @submit="handleSubmit">
+    <MForm ref="form" :items="formItems" v-model="formValues" v-loading="loading"></MForm>
+  </m-dialog>
+</template>
+
+<script>
+import MDialog from '@/components/Dialog'
+import MForm from '@/components/MForm'
+import {
+  combineTrainData
+} from '@/api/dataChart'
+export default {
+  name: 'modelTrainCombine',
+  components: {
+    MDialog,
+    MForm
+  },
+  data () {
+    return {
+      loading: false,
+      show: false,
+      formItems: [
+        {
+          label: '数据集合名称',
+          key: 'collections_names',
+          type: 'autocomplete',
+          rules: [v => v.length > 0 || '请输入数据集合名称'],
+          multiple: true,
+          noAttach: true,
+          items: [
+            { label: 'sql', value: 'sql' },
+            { label: 'ddl', value: 'ddl' },
+            { label: 'documentation', value: 'documentation' },
+            { label: 'error_sql', value: 'error_sql' }
+          ]
+        },
+        {
+          label: '保留策略',
+          key: 'keep_strategy',
+          type: 'autocomplete',
+          noAttach: true,
+          items: [
+            { label: '保留第一条记录', value: 'first' },
+            { label: '保留最后一条记录', value: 'last' },
+            { label: '保留最新记录', value: 'by_metadata_time' }
+          ]
+        },
+        {
+          label: '预览模式',
+          key: 'dry_run',
+          type: 'ifRadio',
+          items: [
+            { label: '是', value: true },
+            { label: '否', value: false }
+          ]
+        }
+      ],
+      formValues: {
+        collections_names: [],
+        keep_strategy: 'first',
+        dry_run: true
+      }
+    }
+  },
+  methods: {
+    open () {
+      this.show = true
+      this.formValues = {
+        collections_names: [],
+        keep_strategy: 'first',
+        dry_run: true
+      }
+      this.$nextTick(() => {
+        this.$refs.form.resetValidation()
+      })
+    },
+    async handleSubmit () {
+      if (!this.$refs.form.validate()) return
+      this.loading = true
+      try {
+        const { data } = await combineTrainData(this.formValues)
+        this.$snackbar.success(data.response)
+        this.show = false
+        this.$emit('success')
+      } catch (error) {
+        this.$snackbar.error(error.message)
+      } finally {
+        this.loading = false
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 27 - 11
src/views/modelSystem/modelTrainManage/modelTrainManageEdit.vue

@@ -8,7 +8,8 @@
 import MDialog from '@/components/Dialog'
 import MForm from '@/components/MForm'
 import {
-  createTrainingData
+  createTrainingData,
+  updateTrainingData
 } from '@/api/dataChart'
 export default {
   name: 'modelTrainManage',
@@ -21,7 +22,9 @@ export default {
       visible: false,
       readonly: false,
       formValues: {
-        training_data_type: 'sql'
+        training_data_type: 'sql',
+        question: '',
+        content: ''
       },
       kinds: {
         sql: {
@@ -59,13 +62,16 @@ export default {
           ],
           rules: [v => this.readonly || !!v || '请选择数据类型'],
           change: (val) => {
-            this.$refs.form.resetValidation()
+            this.$nextTick(() => {
+              this.$refs.form.resetValidation()
+            })
           }
         },
         {
           label: `提问内容 ${isSql ? '*' : ''}`,
           key: 'question',
           readonly: this.readonly,
+          hide: this.formValues.training_data_type !== 'sql' && this.formValues.training_data_type !== 'error_sql',
           type: 'textarea',
           rules: [v => !isSql || this.readonly ? true : !!v || '请输入提问内容']
         },
@@ -94,9 +100,12 @@ export default {
         return
       }
       this.formValues = { ...item }
-      this.$refs.form.resetValidation()
+      this.$nextTick(() => {
+        this.$refs.form.resetValidation()
+      })
     },
     async onSubmit () {
+      if (!this.$refs.form.validate()) return
       // const a = {
       //   data: {
       //     training_data_type: '选择的类型',
@@ -107,14 +116,21 @@ export default {
       //   }
       // }
       const { content, question, training_data_type: type } = this.formValues
+      const query = {
+        id: this.formValues.id,
+        training_data_type: type,
+        [this.kinds[type].key]: content,
+        question: type === 'sql' || type === 'error_sql' ? question : undefined
+      }
       try {
-        await createTrainingData({
-          data: {
-            training_data_type: type,
-            [this.kinds[type].key]: content,
-            question: type === 'sql' || type === 'error_sql' ? question : undefined
-          }
-        })
+        if (this.formValues.id) {
+          await updateTrainingData(query)
+        } else {
+          await createTrainingData({
+            data: query
+          })
+        }
+
         this.$snackbar.success('创建成功')
         this.visible = false
         this.$emit('success')

+ 91 - 0
src/views/modelSystem/modelTrainManage/modelTrainManageUpload.vue

@@ -0,0 +1,91 @@
+<template>
+  <m-dialog title="导入训练数据" :visible.sync="show" @submit="handleSubmit">
+    <MForm ref="form" :items="formItems" v-model="formValues" v-loading="loading"></MForm>
+  </m-dialog>
+</template>
+
+<script>
+import MDialog from '@/components/Dialog'
+import MForm from '@/components/MForm'
+import {
+  uploadTrainingData
+} from '@/api/dataChart'
+export default {
+  name: 'modelTrainManageUpload',
+  components: {
+    MDialog,
+    MForm
+  },
+  data () {
+    return {
+      show: false,
+      loading: false,
+      formValues: {},
+      formItems: [
+        {
+          label: '训练数据',
+          key: 'file',
+          type: 'upload',
+          multiple: true,
+          rules: [v => {
+            if (!v) {
+              return '请上传文件'
+            }
+            if (v.size > 500 * 1024) {
+              return '文件大小不能超过500KB'
+            }
+          }]
+        },
+        {
+          label: '文件类型',
+          key: 'file_type',
+          type: 'ifRadio',
+          items: [
+            { label: 'ddl', value: 'ddl' },
+            { label: 'markdown', value: 'markdown' },
+            { label: 'sql_pair_json', value: 'sql_pair_json' },
+            { label: 'sql_pair', value: 'sql_pair' },
+            { label: 'sql', value: 'sql' }
+          ]
+        }
+      ]
+    }
+  },
+  methods: {
+    open () {
+      this.show = true
+      this.formValues = {
+        file_type: 'ddl',
+        file: null
+      }
+      this.$nextTick(() => {
+        this.$refs.form.resetValidation()
+      })
+    },
+    async handleSubmit () {
+      const check = this.$refs.form.validate()
+      if (!check) {
+        return
+      }
+      this.loading = true
+      try {
+        const query = new FormData()
+        query.append('file', this.formValues.file)
+        query.append('training_data_type', this.formValues.training_data_type)
+        await uploadTrainingData()
+        this.$snackbar.success('导入成功')
+        this.show = false
+        this.$emit('success')
+      } catch (error) {
+        this.$snackbar.error(error)
+      } finally {
+        this.loading = false
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 102 - 0
src/views/modelSystem/pgVector/index.vue

@@ -0,0 +1,102 @@
+<template>
+  <div class="pa-3 white">
+    <m-filter :option="filter" @search="handleSearch" />
+    <m-table
+      class="mt-3"
+      :loading="loading"
+      :headers="headers"
+      :items="items"
+      :total="total"
+      :page-info="pageInfo"
+      @add="handleAdd"
+      @edit="handleEdit"
+      @delete="handleDelete"
+      @pageHandleChange="pageHandleChange"
+      @sort="handleSort"
+    >
+    </m-table>
+  </div>
+</template>
+
+<script>
+import MFilter from '@/components/Filter'
+import MTable from '@/components/List/table.vue'
+export default {
+  name: 'pgVector',
+  components: { MFilter, MTable },
+  data () {
+    return {
+      loading: false,
+      show: false,
+      filter: {
+        list: [
+          { type: 'textField', value: '', label: '名称', key: 'name' },
+          { type: 'autocomplete', value: null, label: '选择', key: 'type', items: [] }
+        ]
+      },
+      queryData: {
+        name: null
+      },
+      headers: [
+        { text: '名称', align: 'start', value: 'name' }
+      ],
+      itemData: {},
+      items: [],
+      orders: [],
+      pageInfo: {
+        size: 10,
+        current: 1
+      },
+      total: 0
+    }
+  },
+  computed: {
+    title () {
+      return Object.keys(this.itemData).length ? '编辑' : '新增'
+    }
+  },
+  created () {
+    this.init()
+  },
+  methods: {
+    async init () {},
+    handleSearch (val) {
+      Object.assign(this.queryData, val)
+      this.pageInfo.current = 1
+      this.init()
+    },
+    handleAdd () {
+      this.itemData = {}
+      this.show = true
+    },
+    async handleEdit (item) {
+      this.itemData = item
+      this.show = true
+    },
+    handleDelete (ids) {
+      if (Array.isArray(ids) && !ids.length) return this.$snackbar.warning('请选择要删除的选项')
+      this.$confirm('提示', '是否删除该选项')
+        .then(async () => {
+          try {
+            this.$snackbar.success('删除成功')
+            this.init()
+          } catch (error) {
+            this.$snackbar.error('删除失败')
+          }
+        })
+    },
+    pageHandleChange (page) {
+      this.pageInfo.current = page
+      this.init()
+    },
+    handleSort (val) {
+      this.orders = val
+      this.init()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>