创新实训-角色疆界

项目概述
 

项目目标:构建一个智能电影角色扮演对话大模型,它能够模拟电影角色的性格和语调,为用户提供与电影角色对话的能力。
技术基础:项目基于“mPlug-Owl”大模型,一个先进的对话生成模型,我们计划通过微调这一模型,使其适应电影角色的对话风格。数据源自开源中文电影数据集Movie101,包括各种电影中的对话和角色信息。

环境准备

设备名称    LAPTOP-6H4TQA0G
处理器    Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz   2.11 GHz
机带 RAM    16.0 GB (15.8 GB 可用)
设备 ID    F70DB001-6823-4C4E-B54C-E82681868062
产品 ID    00342-35695-74487-AAOEM
系统类型    64 位操作系统, 基于 x64 的处理器
笔和触控    为 10 触摸点提供触控支持
 

主要任务

模型和后端有其他组员提供,我就主要负责将参数提供给接口和接口提供的参数可视化

接口实现

1.测试接口:https://env-00jxgsdmxhfk.dev-hz.cloudbasefunction.cn/generate

传参为:

  1. image_list:

    (二进制)

  2. prompt:

    1111111

回参为:

{
    "response": "text sequences....",
    "prompt": "",
    "image_list": [],

}

传参代码:建立一个表单将两个参数赋值传过去

const formData = new FormData();
formData.append('image_list', file);
formData.append('prompt', chatMsg);


fetch('https://env-00jxgsdmxhfk.dev-hz.cloudbasefunction.cn/generate', {                //api,补充修改
  method: 'POST',
  body: formData

返回参数处理:因为实现效果要类似chatgpt将回应msg一个个显示,用reader在响应对象中获取一个用于读取响应数据的 ReadableStreamDefaultReader 对象。以便逐步读取来自服务器的响应数据。这样我们可以通过读取数据块的方式逐步处理响应数据,而不是一次性将所有数据加载到内存中。这对于处理大量数据或长时间流式传输的情况非常有用。

}).then(response => {
  const reader = response.body.getReader();
  let content = '';

定义一个递归函数来读取数据流:数据读取结束后, 设置最后一个会话的 loading 状态为 false,且 设置当前会话的 loading 状态为 false。如果这是第一次发送消息,创建一个新的会话对象,就像刚进入chat,直接发消息而不选择会话时会产生一个新的会话

function readData() {
  return reader.read().then(({ done, value }) => {
    if (done) {        
      conv["loading"] = false; 
      that.convLoading = false; 
      if (first) { 
        var newConv = { 
          "id": that.cid,
          "title": "New chat"
        };

生成新的会话标题:

that.generateConvTitle(newConv); 

generateConvTitle(conv) {                         //产生会话标题
  var that = this; // 声明一个变量来引用当前的 Vue 实例
  var tsource = this.tsource = new EventSource(`/api/chat/title/${this.cid}`); // 创建一个新的 EventSource 实例来监听会话标题的 API

  // 如果服务器响应报文中没有指明事件,默认触发message事件
  conv.title = ""; // 设置会话标题为空字符串
  tsource.addEventListener("message", function (e) {
    if (e.data == "[DONE]") { // 如果收到 "[DONE]" 消息,则关闭连接
      tsource.close(); // 关闭 EventSource 连接
      that.selectConversation(conv, false); // 选择会话
      that.saveConversations(); // 保存会话列表
      that.tsource = undefined; // 重置 tsource 变量为 undefined
      return; // 停止处理
    }

    conv.title += e.data; // 将接收到的数据添加到会话标题
    that.selectConversation(conv, false); // 选择会话
  });

  tsource.addEventListener("error", function (e) {
    console.log("error:" + e.data); // 当发生错误时打印日志
    tsource.close(); // 关闭 EventSource 连接
    that.tsource = undefined; // 重置 tsource 变量为 undefined
  });
},

将新的会话添加到会话列表的开头:

that.conversations.unshift(newConv); 

选择新的会话:

that.selectConversation(newConv, false); 

selectConversation(conv, loadConv) {                   //选择对话??????
  var that = this; // 声明一个变量来引用当前的 Vue 实例
  if (this.oldConv) { // 如果旧的会话存在
    this.oldConv.selected = false; // 设置旧的会话的 selected 属性为 false
  }
  conv.selected = true; // 设置新选择的会话的 selected 属性为 true
  this.oldConv = conv; // 将新选择的会话设置为旧的会话

  document.title = conv.title || "chatai"; // 设置网页标题为新选择的会话的标题
  this.chatTitle = conv.title || "chatai"; // 设置聊天标题为新选择的会话的标题

  if (!loadConv) { // 如果不需要加载会话内容
    return; // 停止操作
  }

保存会话列表:

that.saveConversations(); 
saveConversations() {                 //保存会话列表
  var conversations = JSON.parse(JSON.stringify(this.conversations)); // 深度复制会话列表,避免直接修改原数据
  for (let idx in conversations) { // 遍历会话列表
    var conv = conversations[idx]; // 获取每个会话
    delete conv.editable; // 删除会话的编辑属性
    delete conv.selected; // 删除会话的选择属性
    delete conv.delete; // 删除会话的删除属性
  }
  let convs = JSON.stringify(conversations); // 将会话列表转换为 JSON 字符串
  localStorage.setItem("conversations", convs); // 将 JSON 字符串保存到 localStorage 中
},

刷新会话内容:

that.refrechConversation(); 
refrechConversation() {
  this.conversation = JSON.parse(JSON.stringify(this.conversation)); // 深度复制会话内容,避免直接修改原数据
},

将每次读取的Uint8Array转换为字符串,然后添加到textString中:

content = new TextDecoder('utf-8').decode(value);
if (content.includes("[ENTRY]")) { // 如果数据包含 "[ENTRY]",则替换为换行符
  content = content.replaceAll("[ENTRY]", "\n");
}

滚动到最下面并用正则将response匹配内容显示:

that.handleScrollBottom();

const regex = /"response":\s*"([^"]+)"/g;
let match;
while ((match = regex.exec(content)) !== null) {
  const targetText = match[1]; // 获取匹配到的内容
  conv["speeches"][0] += targetText; // 将内容赋值给 conv["speeches"][0]
}
window.console.log('content:            ',conv["speeches"][0])
that.refrechConversation(); // 刷新会话内容

之后递归调用:

  // 递归调用,继续读取下一块数据
        return readData();
      });
    }
    window.console.log('res:                  ',res["speeches"][0])
    // 开始读取数据
    return readData();
  }).catch(error => {
    console.log("error:" + error); //
    source.close();
    that.source = undefined;
  });
},

2. 测试接口:this.axios.post(`/api/generate/id`, {})

请求成功的回调函数

打印结果

获取响应数据即请求的会话id

设置会话 ID

清空当前会话内容

.then((result) => {
  console.log(result); 
  var resp = result.data; 

  that.cid = resp.data; 
  this.conversation = []; 
})

请求失败的回调函数

.catch((err) => { 
        console.log("无法加载会话ID")
      });
},

3.点击函数:

检查本地存储中的主题


更改主题


加载 ID


加载对话


加载头像


获取聊天容器元素


为聊天容器添加滚动事件监听器


将复制方法添加到窗口

mounted: function () {
  var theme = localStorage.getItem("theme") || "light"
  this.changeTheme(theme);
  this.loadId();
  this.loadConversations();
  this.loadAvatar();

  let chatDivEle = this.$refs.chatContainer;
  chatDivEle.addEventListener('scroll', this.isScrollAndNotBottom, true)

  window.copy = this.vueCopy
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值