| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302 |
- <html>
- <head>
- <title>向量知识库管理</title>
- <meta charset="utf-8">
- <meta name="apple-mobile-web-app-capable" content="yes" />
- <meta name="mobile-web-app-capable" content="yes" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=400, user-scalable=no">
- <link rel="shortcut icon" href="#" />
- <!-- <link href="https://npm.elemecdn.com/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet">
- <link href="https://npm.elemecdn.com/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
- <script src="https://npm.elemecdn.com/vue@2.x/dist/vue.min.js"></script>
- <script src="https://npm.elemecdn.com/vuetify@2.x/dist/vuetify.min.js"></script> -->
- <link href="/static/mdi_font/css/materialdesignicons.min.css" rel="stylesheet">
- <link href="/static/vuetify.min.css" rel="stylesheet">
- <script src="/static/vue.js"></script>
- <script src="/static/vue-i18n.js"></script>
- <script src="/static/vuetify.min.js"></script>
- <script src="/static/markdown-it.min.js"></script>
- <script src="/static/strings.js"></script>
- <script defer src="/static/xlsx.core.min.js"></script>
- <style>
- .v-application--wrap {
- display: unset;
- margin: 30px;
- }
- .v-sheet.v-card {
- margin: 20px;
- padding: 10px;
- }
- </style>
- </head>
- <body>
- <div id="app" v-cloak>
- <v-app>
- <h1>向量知识库管理工具</h1>
- <v-card elevation="2">
- <v-card-title>知识库选择和管理</v-card-title>
- <v-divider></v-divider><br>
- <v-card-text>
- <v-row>
- <v-col cols="12" sm="6">
- <v-combobox v-model="memory_name" :items="l现有库" :label='$t("memory_name")'></v-combobox>
- </v-col>
- <v-col cols="12" sm="2">
- </v-col>
- </v-row>
- </v-card-text>
- <v-card-actions>
- <v-btn color="purple" dark size="x-large" @click="save_rtst()">
- {{$t("save_to_disk")}}
- </v-btn>
- </v-card-actions>
- </v-card>
- <v-card elevation="2">
- <v-card-title>批量上传</v-card-title>
- <v-divider></v-divider><br>
- <v-card-text>
- <v-data-table :headers="[{ text: '问题', value: '问题' },{ text: '回答', value: '回答' }]"
- :items="l表格读取结果"></v-data-table>
- </v-card-text>
- <v-card-actions>
- <v-btn color="purple" dark size="x-large" @click="f载入表格()">
- 载入表格
- </v-btn>
- <v-btn color="purple" dark size="x-large" @click="f载入自动总结问题json()">
- 载入问题JSON
- </v-btn>
- <v-btn color="purple" dark size="x-large" @click="f保存自动总结问题()">
- 保存问题为表格
- </v-btn>
- <v-btn color="purple" dark size="x-large" @click="f批量上传()" :loading="b批量上传中">
- {{$t("upload")}}
- </v-btn><template v-if="b批量上传中">{{i批量上传进度}}/{{l表格读取结果.length}}</template>
- </v-card-actions>
- </v-card>
- <v-card elevation="2">
- <v-card-title>测试查询</v-card-title>
- <v-divider></v-divider><br>
- <v-card-text>
- <v-row>
- <v-col cols="12" sm="6">
- <v-text-field v-model="test_zsk_prompt" label="关键词" clearable></v-text-field>
- </v-col>
- <v-col cols="12" sm="6">
- <v-text-field v-model="test_zsk_step" label="上下文数量" clearable></v-text-field>
- </v-col>
- </v-row>
- <v-data-table
- :headers="[{ text: '来源', value: 'title' },{ text: '分数', value: 'score' },{ text: '内容', value: 'content' }]"
- :items="zhishiku" hide-default-footer></v-data-table>
- </v-card-text>
- <v-card-actions>
- <v-btn color="purple" dark size="x-large"
- @click="find_in_memory(test_zsk_prompt,test_zsk_step,memory_name)">
- 查询
- </v-btn>
- </v-card-actions>
- </v-card>
- <v-card elevation="2">
- <v-card-title>单条上传</v-card-title>
- <v-divider></v-divider><br>
- <v-card-text>
- <v-row>
- <v-col cols="12" sm="6">
- <v-text-field v-model="title" :label='$t("title")' clearable></v-text-field>
- </v-col>
- <v-col cols="12" sm="6">
- </v-col>
- <v-textarea :placeholder='$t("content")' v-model="content">
- </v-textarea>
- </v-row>
- </v-card-text>
- <v-card-actions>
- <v-btn color="purple" dark size="x-large" @click="upload_rtst_zhishiku(title,content)">
- {{$t("upload")}}
- </v-btn>
- </v-card-actions>
- </v-card>
- </v-app>
- </div>
- <script>
- f读取现有库 = async () => {
- response = await fetch("/api/list_rtst_in_disk", {
- method: 'post',
- })
- let list_rtst_in_disk = await response.json()
- list_rtst_in_disk = list_rtst_in_disk.map(decodeURI)
- let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
- genID = () => 'xxxxxxxxxxxx'.replace(/x/g, function () {
- return chars[Math.random() * 62 | 0]
- })
- if (!localStorage['wenda_rtst_ID']) localStorage['wenda_rtst_ID'] = genID()
- list_rtst_in_disk.push(localStorage['wenda_rtst_ID'])
- app.l现有库 = list_rtst_in_disk
- }
- app = new Vue({
- el: '#app',
- vuetify: new Vuetify(),
- i18n: i18n,
- data: () => ({
- content: '',
- title: '',
- memory_name: 'default',
- test_zsk_prompt: "",
- test_zsk_step: 1,
- zhishiku: [],
- l表格读取结果: [],
- b批量上传中: false,
- i批量上传进度: 0,
- l现有库: []
- }),
- methods: {
- }
- })
- f读取现有库()
- find_in_memory = async (s, step, memory_name) => {
- response = await fetch("/api/find_rtst_in_memory", {
- method: 'post',
- body: JSON.stringify({
- prompt: s,
- step: step,
- memory_name: encodeURI(app.memory_name)
- }),
- headers: {
- 'Content-Type': 'application/json'
- }
- })
- let json = await response.json()
- console.table(json)
- app.zhishiku = json
- return json
- }
- upload_rtst_zhishiku = async (title, txt, show_result = true) => {
- response = await fetch("/api/upload_rtst_zhishiku", {
- method: 'post',
- body: JSON.stringify({
- title: title,
- txt: txt,
- memory_name: encodeURI(app.memory_name)
- }),
- headers: { 'Content-Type': 'application/json' }
- })
- show_result && alert(await response.text())
- }
- save_rtst = async () => {
- response = await fetch("/api/save_rtst_zhishiku", {
- method: 'post',
- body: JSON.stringify({
- memory_name: encodeURI(app.memory_name)
- }),
- headers: { 'Content-Type': 'application/json' }
- })
- alert(await response.text())
- }
- f载入表格 = async () => {
- await new Promise(resolve => {
- let input = document.createElement('input')
- input.type = 'file'
- input.accept = '.xlsx'
- input.onchange = function () {
- var file = input.files[0];
- var reader = new FileReader();
- reader.onload = function (e) {
- let contents = e.target.result;
- var workbook = XLSX.read(new Uint8Array(contents), {
- type: 'array'
- });
- app.l表格读取结果 = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]])
- resolve()
- };
- reader.readAsArrayBuffer(file);
- }
- input.click()
- })
- }
- f载入自动总结问题json = async () => {
- let contents = ''
- await new Promise(resolve => {
- let input = document.createElement('input')
- input.type = 'file'
- input.accept = '.json'
- input.onchange = function () {
- var file = input.files[0];
- var reader = new FileReader();
- reader.onload = function (e) {
- contents = e.target.result;
- resolve()
- };
- reader.readAsText(file);
- }
- input.click()
- })
- contents = JSON.parse(contents)
- let l = [];
- contents.forEach(e => { e.question.forEach(qa => { l.push({ 问题: qa.Q, 回答: qa.A, 来源: e.paragraph }) }) })
- app.l表格读取结果 = l
- }
- f保存自动总结问题 = async () => {
- let sheetName = '闻达自动总结问题'
- let wb = XLSX.utils.book_new()
- let ws = XLSX.utils.json_to_sheet(app.l表格读取结果)
- wb.SheetNames.push(sheetName)
- wb.Sheets[sheetName] = ws
- let wopts = {
- bookType: 'xlsx',
- bookSST: false,
- type: 'binary'
- };
- let wbout = XLSX.write(wb, wopts)
- let blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
- saveAs(blob, sheetName + '.xlsx')
- }
- const s2ab = s => {
- var buf;
- if (typeof ArrayBuffer !== 'undefined') {
- buf = new ArrayBuffer(s.length)
- var view = new Uint8Array(buf)
- for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
- return buf
- } else {
- buf = new Array(s.length);
- for (let i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
- return buf;
- }
- }
- function saveAs(obj, fileName) {//当然可以自定义简单的下载文件实现方式
- var tmpa = document.createElement("a");
- tmpa.download = fileName ? fileName + '.xlsx' : new Date().getTime() + '.xlsx';
- tmpa.href = URL.createObjectURL(obj); //绑定a标签
- tmpa.click(); //模拟点击实现下载
- setTimeout(function () { //延时释放
- URL.revokeObjectURL(obj); //用URL.revokeObjectURL()来释放这个object URL
- }, 100);
- }
- f批量上传 = async () => {
- app.b批量上传中 = true
- for (question_index in app.l表格读取结果) {
- app.i批量上传进度 = question_index
- let question = app.l表格读取结果[question_index]
- await upload_rtst_zhishiku(question.问题, question.回答, false)
- }
- app.b批量上传中 = false
- }
- </script>
- </body>
- </html>
|