st.html 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. <html>
  2. <head>
  3. <title>向量知识库管理</title>
  4. <meta charset="utf-8">
  5. <meta name="apple-mobile-web-app-capable" content="yes" />
  6. <meta name="mobile-web-app-capable" content="yes" />
  7. <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  8. <meta name="viewport" content="width=400, user-scalable=no">
  9. <link rel="shortcut icon" href="#" />
  10. <!-- <link href="https://npm.elemecdn.com/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet">
  11. <link href="https://npm.elemecdn.com/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">
  12. <script src="https://npm.elemecdn.com/vue@2.x/dist/vue.min.js"></script>
  13. <script src="https://npm.elemecdn.com/vuetify@2.x/dist/vuetify.min.js"></script> -->
  14. <link href="/static/mdi_font/css/materialdesignicons.min.css" rel="stylesheet">
  15. <link href="/static/vuetify.min.css" rel="stylesheet">
  16. <script src="/static/vue.js"></script>
  17. <script src="/static/vue-i18n.js"></script>
  18. <script src="/static/vuetify.min.js"></script>
  19. <script src="/static/markdown-it.min.js"></script>
  20. <script src="/static/strings.js"></script>
  21. <script defer src="/static/xlsx.core.min.js"></script>
  22. <style>
  23. .v-application--wrap {
  24. display: unset;
  25. margin: 30px;
  26. }
  27. .v-sheet.v-card {
  28. margin: 20px;
  29. padding: 10px;
  30. }
  31. </style>
  32. </head>
  33. <body>
  34. <div id="app" v-cloak>
  35. <v-app>
  36. <h1>向量知识库管理工具</h1>
  37. <v-card elevation="2">
  38. <v-card-title>知识库选择和管理</v-card-title>
  39. <v-divider></v-divider><br>
  40. <v-card-text>
  41. <v-row>
  42. <v-col cols="12" sm="6">
  43. <v-combobox v-model="memory_name" :items="l现有库" :label='$t("memory_name")'></v-combobox>
  44. </v-col>
  45. <v-col cols="12" sm="2">
  46. </v-col>
  47. </v-row>
  48. </v-card-text>
  49. <v-card-actions>
  50. <v-btn color="purple" dark size="x-large" @click="save_rtst()">
  51. {{$t("save_to_disk")}}
  52. </v-btn>
  53. </v-card-actions>
  54. </v-card>
  55. <v-card elevation="2">
  56. <v-card-title>批量上传</v-card-title>
  57. <v-divider></v-divider><br>
  58. <v-card-text>
  59. <v-data-table :headers="[{ text: '问题', value: '问题' },{ text: '回答', value: '回答' }]"
  60. :items="l表格读取结果"></v-data-table>
  61. </v-card-text>
  62. <v-card-actions>
  63. <v-btn color="purple" dark size="x-large" @click="f载入表格()">
  64. 载入表格
  65. </v-btn>
  66. <v-btn color="purple" dark size="x-large" @click="f载入自动总结问题json()">
  67. 载入问题JSON
  68. </v-btn>
  69. <v-btn color="purple" dark size="x-large" @click="f保存自动总结问题()">
  70. 保存问题为表格
  71. </v-btn>
  72. <v-btn color="purple" dark size="x-large" @click="f批量上传()" :loading="b批量上传中">
  73. {{$t("upload")}}
  74. </v-btn><template v-if="b批量上传中">{{i批量上传进度}}/{{l表格读取结果.length}}</template>
  75. </v-card-actions>
  76. </v-card>
  77. <v-card elevation="2">
  78. <v-card-title>测试查询</v-card-title>
  79. <v-divider></v-divider><br>
  80. <v-card-text>
  81. <v-row>
  82. <v-col cols="12" sm="6">
  83. <v-text-field v-model="test_zsk_prompt" label="关键词" clearable></v-text-field>
  84. </v-col>
  85. <v-col cols="12" sm="6">
  86. <v-text-field v-model="test_zsk_step" label="上下文数量" clearable></v-text-field>
  87. </v-col>
  88. </v-row>
  89. <v-data-table
  90. :headers="[{ text: '来源', value: 'title' },{ text: '分数', value: 'score' },{ text: '内容', value: 'content' }]"
  91. :items="zhishiku" hide-default-footer></v-data-table>
  92. </v-card-text>
  93. <v-card-actions>
  94. <v-btn color="purple" dark size="x-large"
  95. @click="find_in_memory(test_zsk_prompt,test_zsk_step,memory_name)">
  96. 查询
  97. </v-btn>
  98. </v-card-actions>
  99. </v-card>
  100. <v-card elevation="2">
  101. <v-card-title>单条上传</v-card-title>
  102. <v-divider></v-divider><br>
  103. <v-card-text>
  104. <v-row>
  105. <v-col cols="12" sm="6">
  106. <v-text-field v-model="title" :label='$t("title")' clearable></v-text-field>
  107. </v-col>
  108. <v-col cols="12" sm="6">
  109. </v-col>
  110. <v-textarea :placeholder='$t("content")' v-model="content">
  111. </v-textarea>
  112. </v-row>
  113. </v-card-text>
  114. <v-card-actions>
  115. <v-btn color="purple" dark size="x-large" @click="upload_rtst_zhishiku(title,content)">
  116. {{$t("upload")}}
  117. </v-btn>
  118. </v-card-actions>
  119. </v-card>
  120. </v-app>
  121. </div>
  122. <script>
  123. f读取现有库 = async () => {
  124. response = await fetch("/api/list_rtst_in_disk", {
  125. method: 'post',
  126. })
  127. let list_rtst_in_disk = await response.json()
  128. list_rtst_in_disk = list_rtst_in_disk.map(decodeURI)
  129. let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
  130. genID = () => 'xxxxxxxxxxxx'.replace(/x/g, function () {
  131. return chars[Math.random() * 62 | 0]
  132. })
  133. if (!localStorage['wenda_rtst_ID']) localStorage['wenda_rtst_ID'] = genID()
  134. list_rtst_in_disk.push(localStorage['wenda_rtst_ID'])
  135. app.l现有库 = list_rtst_in_disk
  136. }
  137. app = new Vue({
  138. el: '#app',
  139. vuetify: new Vuetify(),
  140. i18n: i18n,
  141. data: () => ({
  142. content: '',
  143. title: '',
  144. memory_name: 'default',
  145. test_zsk_prompt: "",
  146. test_zsk_step: 1,
  147. zhishiku: [],
  148. l表格读取结果: [],
  149. b批量上传中: false,
  150. i批量上传进度: 0,
  151. l现有库: []
  152. }),
  153. methods: {
  154. }
  155. })
  156. f读取现有库()
  157. find_in_memory = async (s, step, memory_name) => {
  158. response = await fetch("/api/find_rtst_in_memory", {
  159. method: 'post',
  160. body: JSON.stringify({
  161. prompt: s,
  162. step: step,
  163. memory_name: encodeURI(app.memory_name)
  164. }),
  165. headers: {
  166. 'Content-Type': 'application/json'
  167. }
  168. })
  169. let json = await response.json()
  170. console.table(json)
  171. app.zhishiku = json
  172. return json
  173. }
  174. upload_rtst_zhishiku = async (title, txt, show_result = true) => {
  175. response = await fetch("/api/upload_rtst_zhishiku", {
  176. method: 'post',
  177. body: JSON.stringify({
  178. title: title,
  179. txt: txt,
  180. memory_name: encodeURI(app.memory_name)
  181. }),
  182. headers: { 'Content-Type': 'application/json' }
  183. })
  184. show_result && alert(await response.text())
  185. }
  186. save_rtst = async () => {
  187. response = await fetch("/api/save_rtst_zhishiku", {
  188. method: 'post',
  189. body: JSON.stringify({
  190. memory_name: encodeURI(app.memory_name)
  191. }),
  192. headers: { 'Content-Type': 'application/json' }
  193. })
  194. alert(await response.text())
  195. }
  196. f载入表格 = async () => {
  197. await new Promise(resolve => {
  198. let input = document.createElement('input')
  199. input.type = 'file'
  200. input.accept = '.xlsx'
  201. input.onchange = function () {
  202. var file = input.files[0];
  203. var reader = new FileReader();
  204. reader.onload = function (e) {
  205. let contents = e.target.result;
  206. var workbook = XLSX.read(new Uint8Array(contents), {
  207. type: 'array'
  208. });
  209. app.l表格读取结果 = XLSX.utils.sheet_to_json(workbook.Sheets[workbook.SheetNames[0]])
  210. resolve()
  211. };
  212. reader.readAsArrayBuffer(file);
  213. }
  214. input.click()
  215. })
  216. }
  217. f载入自动总结问题json = async () => {
  218. let contents = ''
  219. await new Promise(resolve => {
  220. let input = document.createElement('input')
  221. input.type = 'file'
  222. input.accept = '.json'
  223. input.onchange = function () {
  224. var file = input.files[0];
  225. var reader = new FileReader();
  226. reader.onload = function (e) {
  227. contents = e.target.result;
  228. resolve()
  229. };
  230. reader.readAsText(file);
  231. }
  232. input.click()
  233. })
  234. contents = JSON.parse(contents)
  235. let l = [];
  236. contents.forEach(e => { e.question.forEach(qa => { l.push({ 问题: qa.Q, 回答: qa.A, 来源: e.paragraph }) }) })
  237. app.l表格读取结果 = l
  238. }
  239. f保存自动总结问题 = async () => {
  240. let sheetName = '闻达自动总结问题'
  241. let wb = XLSX.utils.book_new()
  242. let ws = XLSX.utils.json_to_sheet(app.l表格读取结果)
  243. wb.SheetNames.push(sheetName)
  244. wb.Sheets[sheetName] = ws
  245. let wopts = {
  246. bookType: 'xlsx',
  247. bookSST: false,
  248. type: 'binary'
  249. };
  250. let wbout = XLSX.write(wb, wopts)
  251. let blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' })
  252. saveAs(blob, sheetName + '.xlsx')
  253. }
  254. const s2ab = s => {
  255. var buf;
  256. if (typeof ArrayBuffer !== 'undefined') {
  257. buf = new ArrayBuffer(s.length)
  258. var view = new Uint8Array(buf)
  259. for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
  260. return buf
  261. } else {
  262. buf = new Array(s.length);
  263. for (let i = 0; i != s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
  264. return buf;
  265. }
  266. }
  267. function saveAs(obj, fileName) {//当然可以自定义简单的下载文件实现方式
  268. var tmpa = document.createElement("a");
  269. tmpa.download = fileName ? fileName + '.xlsx' : new Date().getTime() + '.xlsx';
  270. tmpa.href = URL.createObjectURL(obj); //绑定a标签
  271. tmpa.click(); //模拟点击实现下载
  272. setTimeout(function () { //延时释放
  273. URL.revokeObjectURL(obj); //用URL.revokeObjectURL()来释放这个object URL
  274. }, 100);
  275. }
  276. f批量上传 = async () => {
  277. app.b批量上传中 = true
  278. for (question_index in app.l表格读取结果) {
  279. app.i批量上传进度 = question_index
  280. let question = app.l表格读取结果[question_index]
  281. await upload_rtst_zhishiku(question.问题, question.回答, false)
  282. }
  283. app.b批量上传中 = false
  284. }
  285. </script>
  286. </body>
  287. </html>
粤ICP备19079148号