ai聊天问答知识库机器人源码,基于gpt实现的本地知识库问答实现,聊天对话效果,发送回复以及流式输出
现在基于gpt做自己项目的问答机器人,效果非常的好。可以把自己的文档上传上去,让机器人根据文档来进行回答。
想要实现智能AI问答功能,现在大部分都是基于向量数据库的形式。
整体的流程就是:上传文档===>openai向量接口 ====> 存入向量数据库
访客咨询: 咨询问题 ====> openai向量接口 ====>搜索向量数据库 ====> 组织prompt 到 openai的chat接口
下面的源码是前端逻辑,实现的界面以及问答的聊天对话效果,发送回复以及流式输出
效果图的前端源码
<template> <div class="chatpdf"> <div class="pannel"> <div class="fileList"> <div class="fileTitle" v-bind:class="{'active': collect==item.name}" @click="selectCollect(item.name)" v-for="(item,index) in collects"> <svg t="1682317088056" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1403" width="16" height="16"><path d="M512 64c259.2 0 469.333333 200.576 469.333333 448s-210.133333 448-469.333333 448a484.48 484.48 0 0 1-232.725333-58.88l-116.394667 50.645333a42.666667 42.666667 0 0 1-58.517333-49.002666l29.76-125.013334C76.629333 703.402667 42.666667 611.477333 42.666667 512 42.666667 264.576 252.8 64 512 64z m0 64C287.488 128 106.666667 300.586667 106.666667 512c0 79.573333 25.557333 155.434667 72.554666 219.285333l5.525334 7.317334 18.709333 24.192-26.965333 113.237333 105.984-46.08 27.477333 15.018667C370.858667 878.229333 439.978667 896 512 896c224.512 0 405.333333-172.586667 405.333333-384S736.512 128 512 128z m-157.696 341.333333a42.666667 42.666667 0 1 1 0 85.333334 42.666667 42.666667 0 0 1 0-85.333334z m159.018667 0a42.666667 42.666667 0 1 1 0 85.333334 42.666667 42.666667 0 0 1 0-85.333334z m158.997333 0a42.666667 42.666667 0 1 1 0 85.333334 42.666667 42.666667 0 0 1 0-85.333334z" fill="#ffffff" p-id="1404"></path></svg> {{item.name}}</div> </div> </div> <div class="chatpdfBox"> <div class="chatpdfLine"> <div class="chatpdfLineScroll"> <h1>欢迎使用知识库AI</h1> <h2>由 AI 支持的网页版 Copilot</h2> <div class="chatpdfRow " v-bind:class="{'chatpdfAsk': item.type=='ask'}" v-for="(item,index) in msgList"> <div class="chatpdfContent" v-html="html(item.content)"></div> </div> </div> </div> <div class="chatpdfArea"> <button @click="clearHistory"> <svg t="1682398861245" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1371" width="20" height="20"><path d="M883.2 403.2l-147.2-44.8 57.6-224c0-6.4 0-19.2-6.4-25.6-6.4-6.4-12.8-12.8-19.2-12.8L627.2 57.6c-6.4 0-19.2 0-25.6 0C595.2 70.4 588.8 76.8 588.8 83.2L524.8 300.8 358.4 256c-6.4 0-19.2 0-25.6 0S320 275.2 320 281.6l-89.6 320C211.2 684.8 128 768 128 768c-6.4 6.4-12.8 19.2-6.4 32 0 12.8 12.8 19.2 25.6 25.6l524.8 140.8c0 0 6.4 0 6.4 0 6.4 0 19.2-6.4 25.6-12.8 6.4-6.4 83.2-89.6 115.2-179.2 32-83.2 89.6-326.4 89.6-332.8C908.8 422.4 896 409.6 883.2 403.2zM755.2 748.8c-25.6 57.6-70.4 115.2-89.6 147.2l-70.4-19.2c32-38.4 70.4-96 89.6-160 6.4-19.2-6.4-32-25.6-38.4-19.2-6.4-32 6.4-38.4 25.6-19.2 70.4-76.8 134.4-96 153.6l-57.6-12.8c32-38.4 70.4-96 83.2-153.6 6.4-19.2-6.4-32-25.6-38.4-19.2-6.4-32 6.4-38.4 25.6-19.2 64-70.4 128-89.6 153.6l-64-19.2c32-38.4 70.4-96 89.6-153.6 6.4-19.2-6.4-32-25.6-38.4C384 608 364.8 620.8 364.8 633.6c-19.2 64-70.4 128-96 153.6l-57.6-19.2c32-38.4 70.4-96 83.2-153.6l76.8-294.4 166.4 44.8c6.4 0 19.2 0 25.6 0C569.6 364.8 576 358.4 582.4 352L640 128l83.2 19.2-57.6 224c-6.4 19.2 6.4 32 19.2 38.4L832 454.4C819.2 524.8 780.8 691.2 755.2 748.8z" p-id="1372" fill="#ffffff"></path><path d="M364.8 473.6C364.8 492.8 371.2 505.6 390.4 512l339.2 96c0 0 6.4 0 6.4 0 12.8 0 25.6-6.4 32-25.6 6.4-19.2-6.4-32-19.2-38.4L409.6 448C390.4 448 371.2 454.4 364.8 473.6z" p-id="1373" fill="#ffffff"></path> </svg> </button> <textarea @keydown.prevent.enter="sendAsk" v-model="askContent"></textarea> </div> </div> </div> </template> <script> import MarkdownIt from 'markdown-it'; import hljs from 'highlight.js'; import 'highlight.js/styles/monokai-sublime.css'; export default { name: 'ChatPage', data() { return { apiPost:"http://127.0.0.1:8083", collects:[], collect:"test", askContent:"", msgList:[ {type:"ask",content:"自建私有数据知识库 · 与知识库AI聊天"}, {type:"answer",content:"我是知识库机器人,一个专门响应人类指令的大模型"}, ], } }, methods: { sendAsk(){ if(this.askContent=="") return; let msg={ 'type':'ask', 'content':this.askContent, } this.msgList.push(msg); let data=JSON.stringify(this.msgList); localStorage.setItem("data_"+this.collect,data); this.scrollBottom(); this.getReplyFromApi(); }, selectCollect(name){ this.collect=name; this.msgList=[]; this.getHistory(); }, getCollects(){ let _this=this; fetch(this.apiPost+'/collects', { method: 'get', }) .then((response) => response.json()) .then((response) => { console.log(response); _this.collects=response.result.collections; }) }, getReplyFromApi(){ let _this=this; let msg={ 'type':'answer', 'content':"正在为你生成答案...", } _this.msgList.push(msg); let i=0; var xhr = new XMLHttpRequest(); xhr.open("GET", this.apiPost+"/"+this.collect+"/searchStream?keywords="+_this.askContent); xhr.setRequestHeader("Content-Type", "text/html"); xhr.onprogress = function(event) { console.log(i,event.currentTarget.responseText); _this.msgList[_this.msgList.length-1].content=event.currentTarget.responseText; _this.scrollBottom(); }; xhr.onreadystatechange = () => { if (xhr.readyState === XMLHttpRequest.DONE) { let data=JSON.stringify(this.msgList); localStorage.setItem("data_"+this.collect,data); } }; xhr.send(); this.askContent=""; }, getHistory(name){ let str=localStorage.getItem("data_"+this.collect); if(!str) return; let data=JSON.parse(str); this.msgList=data; }, //滚动到底部 scrollBottom:function(){ var _this=this; this.$nextTick(function(){ var container = _this.$el.querySelector(".chatpdfLine"); container.scrollTop = 999999999; }); }, html(sourceStr) { const md = new MarkdownIt({ highlight: function (str, lang) { if (lang && hljs.getLanguage(lang)) { try { return '<pre class="hljs"><code>' + hljs.highlight(lang, str, true).value + '</code></pre>'; } catch (__) {} } return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'; } }); return md.render(sourceStr); }, clearHistory(){ localStorage.removeItem("data_"+this.collect); this.msgList=[]; }, getQuery(key) { // 获取所有参数 var query = window.location.search.substring(1); var hash = window.location.hash.substring(1); // 如果锚点后面有参数,把锚点后面的参数加入到search参数中 if(hash.indexOf("?") > -1){ query += "&" + hash.split("?")[1]; } var key_values = query.split("&"); var params = {}; // 遍历参数并存入params对象 key_values.map(function (key_val){ var key_val_arr = key_val.split("="); params[key_val_arr[0]] = key_val_arr[1]; }); // 如果找到了key对应的参数,返回对应值 if(typeof params[key]!="undefined"){ return params[key]; } // 如果没找到,返回空字符串 return ""; } }, mounted: function () { let collect=this.getQuery("collect"); if(collect){ this.collect=collect; } this.getCollects(); this.getHistory(); } } </script> <style> .chatpdf{ display: flex; height: 100vh; flex-direction: row; } .chatpdf .pannel{ width: 255px; background-color: rgb(0, 21, 41); display: none; } .chatpdfBox{ display: flex; flex-direction: column; flex: 1; background: linear-gradient(to bottom right,#dbe6fb, #f3f4f8); background-size: cover; background-attachment: fixed; } .chatpdfHeader{ font-size: 18px; padding: 10px; text-align: center; width: 100%; } .chatpdfLine{ flex: 1; width: 100%; overflow-y: auto; } .chatpdfLine h1{ color: #111111; text-align: center; margin-top: 80px; margin-bottom: 20px; font-size: 36px; } .chatpdfLine h2{ color: #1e1e1e; text-align: center; font-size: 20px; font-weight: 400; } .chatpdfLineScroll{ max-width: 1000px; margin: 0 auto; } .chatpdfRow{ margin: 20px 10px; display: flex; } .chatpdfAsk{ justify-content: flex-end; } .chatpdfContent{ line-height: 23px; display: inline-block; border-radius: 8px; padding: 12px 15px; max-width: 700px; background: rgba(255, 255, 255, 0.6); font-size: 14px; box-shadow: 0px 0.3px 0.9px rgba(0, 0, 0, 0.12), 0px 1.6px 3.6px rgba(0, 0, 0, 0.16); } .chatpdfAsk .chatpdfContent{ background: linear-gradient(90deg, #2870EA 10.79%, #1B4AEF 87.08%);; color: #fff; } .chatpdfContent pre{ padding: 10px; } .chatpdfArea{ display: flex; margin-bottom: 10px; max-width: 1000px; margin: 0 auto; width: 98%; margin-bottom: 15px; transition: all 0.3s,height 0s; } .chatpdfArea textarea{ flex: 1; border: none; resize: none; outline: none; padding: 0px 5px; height: 40px; line-height: 35px; color: #404040; border-radius: 10px; box-shadow: 0px 0.3px 0.9px rgba(0, 0, 0, 0.12), 0px 1.6px 3.6px rgba(0, 0, 0, 0.08); } .chatpdfArea:hover{ border-color: #4096ff; } .chatpdfArea button{ height: 40px; color: #fff; background: linear-gradient(90deg, #1B4AEF 10.79%, #2870EA 87.08%); box-shadow: 0 2px 0 rgba(5, 145, 255, 0.1); border: none; padding: 0 20px; border-radius: 15px; cursor: pointer; box-shadow: 0px 0.3px 0.9px rgba(0, 0, 0, 0.12), 0px 1.6px 3.6px rgba(0, 0, 0, 0.08); margin-right: 10px; } .chatpdfArea button:hover{ background-color: #388aff; } .chatpdf .fileTitle{ background-color: #1677ff; color: #fff; border-radius: 8px; padding: 10px; margin: 10px; font-size: 14px; cursor: pointer; display: flex; } .chatpdf .fileTitle svg{ margin-right: 5px; } .chatpdf .fileTitle.active{ background-color: #66a6ff; } @media (max-width: 768px) { .pannel{ display: none; } } </style>
十年开发经验程序员,离职全心创业中,历时三年开发出的产品《唯一客服系统》
一款基于Golang+Vue开发的在线客服系统,软件著作权编号:2021SR1462600。一套可私有化部署的网站在线客服系统,编译后的二进制文件可直接使用无需搭开发环境,下载zip解压即可,仅依赖MySQL数据库,是一个开箱即用的全渠道在线客服系统,致力于帮助广大开发者/公司快速部署整合私有化客服功能。
开源地址:唯一客服(开源学习版)
官网地址:唯一客服官网