vue实现调用兼容openai api接口大模型聊天对话流式输出webui代码

代码语言:html

所属分类:其他

代码描述:vue实现调用兼容openai api接口大模型聊天对话流式输出webui代码,只要兼容openai的api协议,例如千问、智谱、本地离线大模型ollama等都可以使用,只要改一下api地址和key及model就行了,实现了流式输出、打字动画、复制、重新回答、本地离线消息记录、代码高亮、复制按钮、自动滚动与手动滚动、添加附件等主流大模型的ui交互效果。

代码标签: vue 调用 兼容 openai api 接口 大模型 聊天 对话 流式 输出 webui 代码

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">

    <link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/font-awesome-4.7.0/css/font-awesome.css">
    <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/highlight.js"></script>
    <link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/highlight.9.9.css">
    <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/marked.umd.min.js"></script>
           <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/localforage.min.js"></script>
    <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/vue@2.6.1-dev.js"></script>



    <style>
    body{
        padding: 0;
        margin: 0;
    }
    .cont{
        position: fixed;
        top:0;
        left: 0;
        right: 0;
        display:flex; flex-direction: column;height:100vh;
    }
        .historylist {
        
         flex: 1;
            overflow-y: scroll;
          
        }
        .historylist img{
           max-width: 100px; 
        }
        .mesay, .aisay {
            padding: 10px;
            margin: 10px;
            border-radius: 5px;
             line-height: 30px;
        }
        .mesay {
            background-color: #d0e7ff;
            text-align: right;
        }
        .aisay {
            background-color: aliceblue;
            text-align: left;
        }
        .inputpannel {
            display: flex;
            margin: 10px;
            background: white;
            align-items: flex-end;
            border: 2px solid grey;
            border-radius: 14px;
        }
        .footer{
            position: relative;
        }

        .inputpannel:focus-within {
    border-color: blue;
}
        
           .inputtext {
            margin-top: 4px;
           
          width: 100%;
          background: white;
          line-height: 20px;
          box-sizing: border-box;
          padding: 8px;
          font-family: inherit;
          font-size: 16px;
          resize: none;
          overflow: hidden;
          border: none;
          outline: none;
          height: 40px;
          
          min-height: 40px;
           overflow-y: auto;
          max-height: calc(24px * 5 );
         
        }
        .inputtext:focus {
          border: none;
          outline: none;
        }
        
        
textarea::placeholder {
   


}
 
    
        .historylist pre {
            white-space: pre-wrap;
            color: #ececec;
            background: black;
            border-radius: 4px;
            padding: 10px;
            margin: 0;
            
        }
        .historylist p {
            margin: 0;
            padding: 2px;
        }
        .typing-text {
            font-size: 24px;
            white-space: pre-wrap;
            border-right: 2px solid black;
            animation: blink 0.7s steps(2, start) infinite;
        }
        @keyframes blink {
            to {
                border-color: transparent;
            }
        }
             .code-header {
           position: absolute;
            top: 0;
            left:0;
            right: 0;
            width: 100%;
           color: #cdcdcd;
           height:24px;
          background : #6767;
            
           
        }
        .language-label {
            position: absolute;
            top: -4px;
            left: 0;
            padding: 0 10px;
            
            font-size: 0.8em;
            
        }
        .copy-button {
            position: absolute;
            top: 0;
            right: 0px;
            padding: 0.3em 0.6em;
           
            
            border: none;
            border-radius: 3px;
            cursor: pointer;
            font-size: 0.8em;
        }
        .code-content{
            line-height: 20px;
display: block;
    text-wrap: nowrap;
    margin-top: -40px;
        margin-bottom: -63px;
        overflow-x: scroll;
        }
        .historylist pre{
              position: relative;
            background: black;
            color: white;
             border-radius: 6px;
            padding: 1em;
            margin: 1em 0;
        }
.file-upload {
    position: relative;
   width: 30px;
   height: 30px;
   margin: 6px -1px 3px 10px;

    overflow: hidden;
 
    
 
}
.sendbtn{
    margin: 13px;
}

.file-upload input[type=file] {
    position: absolute;
    top: 0;
    left: 0;
   
    
    opacity: 0;
    cursor: pointer;
}



ol{
    list-style: none;
    padding: 0;margin: 10px;
}
i{
    cursor: pointer;

}
.recomminput li{
    background: aliceblue;
    border: 1px solid aliceblue;
    margin:  2px 0 4px 0;
        padding: 5px;
  
    width: 64%;
    font-size: 12px;
    cursor: pointer;
    border-radius: 5px;
}
.copybtn,.regenbtn{
    cursor: pointer;
    margin-right: 20px;
}
.scrollbar{
    position: absolute;
    top: -20px;
    width: 100%;
    right:0;
    left: 0;
}
.scrollbar i{
   width: 30px;
   height: 30px;
   border-radius: 15px;
   background: white;
   line-height: 30px;
}
.attachpannel{
      position: absolute;
      display: flex;
  
    width: 100%;
    height: 100px;
   
    left: 0;
    top:-80px;
}
    
        /* 隐藏默认滚动条 */
textarea::-webkit-scrollbar {
    display: none;
}

/* 添加自定义滚动条 */
textarea {
    scrollbar-width: thin; /* 调整滚动条宽度 */
    scrollbar-color: #ccc transparent; /* 调整滚动条颜色 */
    overflow-y: auto; /* 确保溢出时出现滚动条 */
}

/* Firefox 上的滚动条样式 */
textarea {
    scrollbar-width: thin;
}

/* WebKit 上的滚动条样式 */
textarea::-webkit-scrollbar {
    width: 8px; /* 调整滚动条宽度 */
}

textarea::-webkit-scrollbar-track {
    background-color: transparent; /* 滚动条背景颜色 */
}

textarea::-webkit-scrollbar-thumb {
    background-color: #ccc; /* 滚动条颜色 */
    border-radius: 4px; /* 滚动条圆角 */
}

textarea::-webkit-scrollbar-thumb:hover {
  
    background-color: #999; /* 鼠标悬停时的滚动条颜色 */
}

    
        /* 隐藏默认滚动条 */
.historylist::-webkit-scrollbar {
    display: none;
}

/* 添加自定义滚动条 */
.historylist {
    scrollbar-width: thin; /* 调整滚动条宽度 */
    scrollbar-color: #ccc transparent; /* 调整滚动条颜色 */
    overflow-y: auto; /* 确保溢出时出现滚动条 */
}

/* Firefox 上的滚动条样式 */
.historylist {
    scrollbar-width: thin;
}

/* WebKit 上的滚动条样式 */
.historylist::-webkit-scrollbar {
    width: 8px; /* 调整滚动条宽度 */
}
.historylist::-webkit-scrollbar-track {
    background-color: transparent; /* 滚动条背景颜色 */
}

.historylist::-webkit-scrollbar-thumb {
    background-color: #ccc; /* 滚动条颜色 */
    border-radius: 4px; /* 滚动条圆角 */
}

.historylist::-webkit-scrollbar-thumb:hover {
  
    background-color: #999; /* 鼠标悬停时的滚动条颜色 */
}
   
        /* 隐藏默认滚动条 */
.code-content::-webkit-scrollbar {
    display: none;
}

/* 添加自定义滚动条 */
.code-content {
    scrollbar-width: thin; /* 调整滚动条宽度 */
    scrollbar-color: #ccc transparent; /* 调整滚动条颜色 */
    overflow-y: auto; /* 确保溢出时出现滚动条 */
}

/* Firefox 上的滚动条样式 */
.code-content{
    scrollbar-width: thin;
}

/* WebKit 上的滚动条样式 */
.code-content::-webkit-scrollbar {
    width: 8px; /* 调整滚动条宽度 */
}
.code-content::-webkit-scrollbar-track {
    background-color: transparent; /* 滚动条背景颜色 */
}

.code-content::-webkit-scrollbar-thumb {
    background-color: #ccc; /* 滚动条颜色 */
    border-radius: 4px; /* 滚动条圆角 */
}

.code-content::-webkit-scrollbar-thumb:hover {
  
    background-color: #999; /* 鼠标悬停时的滚动条颜色 */
}

    #overlay {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.8);
            z-index: 9999;
            justify-content: center;
            align-items: center;
        }

        #overlay img {
            max-width: 100%;
            max-height: 100%;
        }

        #closeBtn {
            position: absolute;
            top: 10px;
            right: 10px;
          
            color: white;
            border: none;
            padding: 10px;
            cursor: pointer;
            font-size: 16px;
        }
.feedbackpanel{
    font-size: 12px;
}
    </style>
</head>

<body>
    
<div id="overlay" onclick="hideImage()">

    <i id="closeBtn" onclick="hideImage()" class="fa fa-lg fa-times-circle"></i>
    <img id="overlayImage" src="" alt="Fullscreen Image">
</div>



    <div id="app" class="cont" >
        
         <div style="text-align:center;">
        <h2>CHATGPT API实现AI聊天</h2>    
        </div>
        <div id="historylist"  @scroll="handleScroll"  class="historylist">
            <div v-for="(msg,index) in newmess" :key="index" :class="{'mesay': msg.role === 'user', 'aisay': msg.role === 'system'}" >
                
                <div v-html="msg.content"></div>
                 <div  v-if="aistatus==1&&msg.content==''&&msg.role === 'system'"><img style="height:30px;" src='//repo.bfw.wiki/bfwrepo/icon/667d490a27acd.gif' /></div>
                  <div  v-if="aistatus==2&&msg.content==''&&msg.role === 'system'">调用插件中……</div>
                   
                 <div v-if="msg.role === 'system'&&msg.isfinished" class="feedbackpanel"><a title="复制" class="copybtn"  @click="copy(index)"><i class="fa  fa-copy"></i></a><a title="重新生成" class="regenbtn" @click="regen(index)"><i class="fa  fa-rotate-left"></i></a>
                 <a title="非常好" class="regenbtn" ><i class="fa  fa-thumbs-o-up"></i></a>
                .........完整代码请登录后点击上方下载按钮下载查看

网友评论0