先展示下最终效果:

第一步:先安装ollama,并配置对应的开源大模型。

安装步骤可以查看上一篇博客:

ollama搭建本地ai大模型并应用调用

 第二步:需要注意两个配置,页面才可以调用
1)OLLAMA_HOST= "0.0.0.0:11434"
2)若应用部署服务器后想调用,需要配置:OLLAMA_ORIGINS=*
 
第三步:js流式调用大模型接口方法
async startStreaming(e) {
if(e.ctrkey&&e.keyCode==13){
this.form.desc+='\n';
}
document.getElementById("txt_suiwen").disabled="true";
// 如果已经有一个正在进行的流式请求,则中止它
if (this.controller) {
this.controller.abort();
} setTimeout(()=>{
this.scrollToBottom();
},50);
var mymsg=this.form.desc.trim();
if(mymsg.length>0){
this.form.desc='';
this.message.push({
user:this.username,
msg:mymsg
})
this.message.push({
user:'GPT',
msg:'',
dot:''
}); // 创建一个新的 AbortController 实例
this.controller = new AbortController();
const signal = this.controller.signal;
this.arequestData.messages.push({role:"user",content:mymsg}); try {
const response = await fetch('http://127.0.0.1:11434/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body:JSON.stringify(this.arequestData),
signal
}); if (!response.body) {
this.message[this.message.length-1].msg='ReadableStream not yet supported in this browser.';
throw new Error('ReadableStream not yet supported in this browser.');
} const reader = response.body.getReader();
const decoder = new TextDecoder();
let result = '';
this.message[this.message.length-1].dot='';
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
result += decoder.decode(value, { stream: true }); // 处理流中的每一块数据,这里假设每块数据都是完整的 JSON 对象
const jsonChunks = result.split('\n').filter(line => line.trim());
//console.log(result)
for (const chunk of jsonChunks) {
try {
const data = JSON.parse(chunk);
//console.log(data.message.content)
this.message[this.message.length-1].msg+=data.message.content;
setTimeout(()=>{
this.scrollToBottom();
},50);
} catch (e) {
//this.message[this.message.length-1].msg=e;
// 处理 JSON 解析错误
//console.error('Failed to parse JSON:', e);
}
} // 清空 result 以便处理下一块数据
result = '';
}
} catch (error) {
if (error.name === 'AbortError') {
console.log('Stream aborted');
this.message[this.message.length-1].msg='Stream aborted';
} else {
console.error('Streaming error:', error);
this.message[this.message.length-1].msg='Stream error'+error;
}
}
this.message[this.message.length-1].dot='';
this.arequestData.messages.push({
role: 'assistant',//this.message[this.message.length-1].user,//"GPT",
content: this.message[this.message.length-1].msg
})
setTimeout(()=>{
this.scrollToBottom();
},50); }else{
this.form.desc='';
}
document.getElementById("txt_suiwen").disabled="";
document.getElementById("txt_suiwen").focus();
}
}
vue完整代码如下:
<template>
<el-row :gutter="12" class="demo-radius">
<div
class="radius"
:style="{
borderRadius: 'base'
}">
<div class="messge" id="messgebox" ref="scrollDiv">
<ul>
<li v-for="(item, index) in message" :key="index" style="list-style-type:none;">
<div v-if="item.user == username" class="mymsginfo" style="float:right">
<div>
<el-avatar style="float: right;margin-right: 30px;background: #01bd7e;">
<!-- {{ item.user.substring(0, 2) }} -->
<img :alt="item.user.substring(0, 2)" :src=userphoto />
</el-avatar>
</div><div style="float: right;margin-right: 10px;margin-top:10px;width:80%;text-align: right;"> {{ item.msg }} </div>
</div>
<div v-else class="chatmsginfo" >
<div>
<el-avatar style="float: left;margin-right: 10px;"> {{ item.user }} </el-avatar>
</div>
<div style="float: left;margin-top:10px;width:80%;">
<img alt="loading" v-if="item.msg == ''" class="loading" src="../../assets/loading.gif"/>
<MdPreview style="margin-top:-20px;" :autoFoldThreshold="9999" :editorId="id" :modelValue=" item.msg + item.dot " />
<!-- {{ item.msg }} -->
</div>
</div>
</li>
</ul>
</div>
<div class="inputmsg">
<el-form :model="form" >
<el-form-item >
<el-avatar style="float: left;background: #01bd7e;margin-bottom: -44px;margin-left: 4px;z-index: 999;width: 30px;height: 30px;">
<img alt="jin" :src=userphoto />
</el-avatar>
<el-input id="txt_suiwen" :prefix-icon="userphoto" resize="none" autofocus="true" :autosize="{ minRows: 1, maxRows: 2 }" v-model="form.desc" placeholder="说说你想问点啥....按Enter键可直接发送" @keydown.enter.native.prevent="startStreaming($event)" type="textarea" />
</el-form-item>
</el-form>
</div>
</div>
</el-row> </template>
<script setup>
import { MdPreview, MdCatalog } from 'md-editor-v3';
import 'md-editor-v3/lib/preview.css'; const id = 'preview-only';
</script>
<script>
export default {
data() {
return {
form: {
desc: ''
},
message:[],
username:sessionStorage.name,
userphoto:sessionStorage.photo,
loadingtype:false,
controller: null,
arequestData : {
model: "qwen2",//"llama3.1",
messages: []
}
}
},
mounted() {
},
methods: {
scrollToBottom() {
let elscroll=this.$refs["scrollDiv"];
elscroll.scrollTop = elscroll.scrollHeight+30 },
clearForm(formName){
this.form.desc='';
},
async startStreaming(e) {
if(e.ctrkey&&e.keyCode==13){
this.form.desc+='\n';
}
document.getElementById("txt_suiwen").disabled="true";
// 如果已经有一个正在进行的流式请求,则中止它
if (this.controller) {
this.controller.abort();
} setTimeout(()=>{
this.scrollToBottom();
},50);
var mymsg=this.form.desc.trim();
if(mymsg.length>0){
this.form.desc='';
this.message.push({
user:this.username,
msg:mymsg
})
this.message.push({
user:'GPT',
msg:'',
dot:''
}); // 创建一个新的 AbortController 实例
this.controller = new AbortController();
const signal = this.controller.signal;
this.arequestData.messages.push({role:"user",content:mymsg}); try {
const response = await fetch('http://127.0.0.1:11434/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body:JSON.stringify(this.arequestData),
signal
}); if (!response.body) {
this.message[this.message.length-1].msg='ReadableStream not yet supported in this browser.';
throw new Error('ReadableStream not yet supported in this browser.');
} const reader = response.body.getReader();
const decoder = new TextDecoder();
let result = '';
this.message[this.message.length-1].dot='';
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
result += decoder.decode(value, { stream: true });
// 处理流中的每一块数据,这里假设每块数据都是完整的 JSON 对象
const jsonChunks = result.split('\n').filter(line => line.trim());
//console.log(result)
for (const chunk of jsonChunks) {
try {
const data = JSON.parse(chunk);
//console.log(data.message.content)
this.message[this.message.length-1].msg+=data.message.content;
setTimeout(()=>{
this.scrollToBottom();
},50);
} catch (e) {
//this.message[this.message.length-1].msg=e;
// 处理 JSON 解析错误
//console.error('Failed to parse JSON:', e);
}
}
// 清空 result 以便处理下一块数据
result = '';
}
} catch (error) {
if (error.name === 'AbortError') {
console.log('Stream aborted');
this.message[this.message.length-1].msg='Stream aborted';
} else {
console.error('Streaming error:', error);
this.message[this.message.length-1].msg='Stream error'+error;
}
}
this.message[this.message.length-1].dot='';
this.arequestData.messages.push({
role: 'assistant',//this.message[this.message.length-1].user,//"GPT",
content: this.message[this.message.length-1].msg
})
setTimeout(()=>{
this.scrollToBottom();
},50); }else{
this.form.desc='';
}
document.getElementById("txt_suiwen").disabled="";
document.getElementById("txt_suiwen").focus();
}
},
beforeDestroy() {
// 组件销毁时中止流式请求
if (this.controller) {
this.controller.abort();
}
}
}
</script>
<style scoped>
.radius{
margin:0 auto;
}
.demo-radius .title {
color: var(--el-text-color-regular);
font-size: 18px;
margin: 10px 0;
}
.demo-radius .value {
color: var(--el-text-color-primary);
font-size: 16px;
margin: 10px 0;
}
.demo-radius .radius {
min-height: 580px;
height: 85vh;
width: 70%;
border: 1px solid var(--el-border-color);
border-radius: 14px;
margin-top: 10px;
}
.messge{
width:96%;
height:84%;
/* border:1px solid red; */
margin: 6px auto;
overflow: hidden;
overflow-y: auto;
}
.inputmsg{
width:96%;
height:12%;
/* border:1px solid blue; */
border-top:2px solid #ccc;
margin: 4px auto;
padding-top: 10px;
}
.mymsginfo{
width:100%;
height:auto;
min-height:50px;
} ::-webkit-scrollbar {width: 6px;height: 5px;
}
::-webkit-scrollbar-track {background-color: rgba(0, 0, 0, 0.2);border-radius: 10px;
}
::-webkit-scrollbar-thumb {background-color: rgba(0, 0, 0, 0.5);border-radius: 10px;
}
::-webkit-scrollbar-button {background-color: #7c2929;height: 0;width: 0px;
}
::-webkit-scrollbar-corner {background-color: black;
} </style>
<style>
.el-textarea__inner{
padding-left: 45px;
padding-top: .75rem;
padding-bottom: .75rem;
}
</style>
 
 

vue通过ollama接口调用开源模型的更多相关文章

  1. node.js 接口调用示例

    测试用例git地址(node.js部分):https://github.com/wuyongxian20/node-api.git 项目架构如下: controllers: 文件夹下为接口文件 log ...

  2. Vue之状态管理(vuex)与接口调用

    Vue之状态管理(vuex)与接口调用 一,介绍与需求 1.1,介绍 1,状态管理(vuex) Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态 ...

  3. Vue——项目中接口返回值为函数回调,回调函数定义方法(Vue的方法给原生调用)

    在接口调用中,有时会返回给我们一个函数回调,来自动执行我们在前端定义好的某个函数(多出现于通过回调的方式传递某个数值).在原生项目中,我们只要提供一下这个方法就好了,通过函数回调会自动执行.问题就出现 ...

  4. 云极知客开放平台接口调用方法(C#)

    云极知客为企业提供基于SAAS的智能问答服务.支持企业个性化知识库的快速导入,借助语义模型的理解和分析,使企业客户立即就拥有本行业的24小时客服小专家.其SAAS模式实现零成本投入下的实时客服数据的可 ...

  5. SmartRoute之远程接口调用和负载

    基于接口的调用远比基于基础消息交互来得更简单和便于维护,特别在业务展现上,接口作为业务表现更适合其便利性.为了让SmartRoute更适合业务应用集成,在新的一年开始SmartRoute集成了远程接口 ...

  6. Vue+axios统一接口管理

    通过axios请求接口已经很简单了,但最近在做一个vue项目,想着把axios请求再封装一下,这样api就可以只在一处配置成方法,在使用的时候直接调用这个方法. 但咱们不用每个接口都定义成一个啰嗦的a ...

  7. 记一次TCP重发接口调用的问题

    问题描述:基于微软RDP协议,使用开源rdp库与微软skpye软件进行基于tcp的p2p通讯,由于rdp协议传输原始图片数据较大,调用公司内部ice p2p通讯接口处会导致失败. 错误思路:一开始是怀 ...

  8. Angular4+NodeJs+MySQL 入门-04 接口调用类

    上一篇文章说一下,后台接口的创建,这篇说一下如果调用接口. 创建一个目录helpers 此目录下有三个文件分别是 ApiClient.ts.clientMiddleware.ts.Core.ts,前面 ...

  9. uni-app 环境配置,uni.request封装,接口配置,全局配置,接口调用的封装

    1.环境配置 (可参考uni-官网的环境配置) common文件夹下新建config.js let url_config = "" if(process.env.NODE_ENV ...

  10. Vue-cli开发笔记二----------接口调用、配置全局变量

    我做的一个项目,本身是没用任何框架,纯手写的前端及数据交互,项目已经完结.最近学Vue,于是借用这个项目,改装成vue项目. (一)接口问题:使用axios的调用方法,proxyTable解决开发环境 ...

随机推荐

  1. Ubuntu16.04使用命令行安装jdk1.8

    在Ubuntu中安装jdk过于麻烦,有时设置不好可能就没有办法使用,卸载也难以卸载干净,所以这篇文章使用相对简单的命令行来安装jdk,只需简单的四个命令,省去许多麻烦,下面是方法. 进入Ubuntu打 ...

  2. MSI Afterburner 使用

    MSI Afterburner 是一款显卡超频软件,同时可以监测硬件运行数据(CPU 温度.GPU 温度.帧率.帧生成时间等).与其捆绑安装的 RivaTuner Statistics Server ...

  3. Cloudflare D1 - 免费数据存储

    前言 自从上次将博客项目的图片从 七牛云 迁到了 Cloudflare R2 之后就发现,Cloudflare 这个赛博菩萨的产品是真的不错,非常的适合白嫖,DevNow 项目作为一个开源博客,整体来 ...

  4. 技术实践 | 在线 KTV 实现过程(内附demo体验)

    ​ 你在线上K过歌吗? 在线K歌自2014年兴起以来,已经发展出了无比庞大的用户群体,每两人中就有就有一人体验过在线 K歌,其前景不可小觑. 如此庞大的市场规模,以及音视频技术使用门槛逐步降低的加持, ...

  5. 深度学习批次(batch)、迭代(iteration)、周期(epoch)、前向传播(forward propagation)、反向传播(backward propagation)、学习率(learning rate)概念解释

    虽然现在应该是已经熟练掌握这些基础概念的时候,但是我是鱼的记忆,上一秒的事情,下一秒就忘了,除非是重要的人的重要的事情,呜呜呜呜,我这个破脑子. 还是写一下吧,直接GPT出来的(人类之光,欢呼~). ...

  6. Facebook Ads – 笔记

    前言 记入一些小东西 参考 YouTube – 这是第一次广告投放回报做到11倍!Facebook广告高广告投资回报2023年终极策略密码分享 价值阶梯 先卖便宜 value 低的东西给客户,甚至免费 ...

  7. SpringMVC —— RESTful案例

    案例:基于RESTful页面数据交互            

  8. 使用 Flutter 加速应用开发

    作者 / Larry McKenzie 本文由 eBay 技术负责人 Larry Mckenzie 和 Corey Sprague 撰写.您可以收听他们在 Google Apps, Games &am ...

  9. Hugging Face 论文平台 Daily Papers 功能全解析

    文/ Adeena, 在快速发展的研究领域,保持对最新进展的关注至关重要.为了帮助开发者和研究人员跟踪 AI 领域的前沿动态,Hugging Face 推出了 Daily Papers 页面.自发布以 ...

  10. YAML编写应用的资源清单文件(十五)

    上面我们在 Kubernetes 中部署了我们的第一个容器化应用,我们了解到要部署应用最重要的就是编写应用的资源清单文件.那么如何编写资源清单文件呢?日常使用的时候我们都是使用 YAML 文件来编写, ...