Open main menu
首页
专栏
课程
分类
归档
Chat
Sci-Hub
谷歌学术
Libgen
GitHub镜像
登录/注册
搜索
搜索
关闭
Previous
Previous
Next
Next
「GPT实战」GPT接入直播间实现虚拟人互动
sockstack
/
143
/
2023-11-27 12:02:40
<p><span style="color: red; font-size: 18px">ChatGPT 可用网址,仅供交流学习使用,如对您有所帮助,请收藏并推荐给需要的朋友。</span><br><a href="https://ckai.xyz/?sockstack§ion=detail" target="__blank">https://ckai.xyz</a><br><br></p> <article class="baidu_pl"><div id="article_content" class="article_content clearfix"> <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css"> <link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-25cebea3f9.css"> <div id="content_views" class="markdown_views prism-atom-one-dark"> <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path></svg><h1> <a id="_0"></a>摘要</h1> <p>ChatGPT和元宇宙都是当前数字化领域中非常热门的技术和应用。结合两者的优势和特点,可以探索出更多的应用场景和商业模式。例如,在元宇宙中使用ChatGPT进行自然语言交互,可以为用户提供更加智能化、个性化的服务和支持;在ChatGPT中使用元宇宙进行虚拟现实体验,可以为用户提供更加真实、丰富、多样化的交互体验。<br> 下面我将结合元宇宙和ChatGPT的优势,实战开发一个GPT虚拟直播的Demo并推流到抖音平台,</p> <h1> <a id="NodeJSChatGPTZIM_4"></a>NodeJS接入ChatGPT与即构ZIM</h1> <p>上一篇文章《如何基于ChatGPT+Avatar搭建24小时无人直播间》,主要介绍了如何使用ChatGPT+即构Avatar做虚拟人直播。由于篇幅原因,对代码具体实现部分描述的不够详细。收到不少读者询问代码相关问题,接下来笔者将代码实现部分拆分2部分来详细描述:</p> <ol> <li>NodeJS接入ChatGPT与即构ZIM</li> <li>ChatGPT与即构Avatar虚拟人对接直播</li> </ol> <p>本文主要讲解如何接入ChatGPT并实现后期能与Avatar对接能力。</p> <p>在开始讲具体流程之前,我们先来回顾一下整个GPT虚拟直播Demo的实现流程图,本文要分享的内容是下图的右边部分的实现逻辑。</p> <p><img referrerpolicy="no-referrer" src="https://img-blog.csdnimg.cn/f87f8c6916994cca844fca7a92061e19.jpeg#pic_center" alt="在这里插入图片描述"></p> <h1> <a id="1__16"></a>1 基本原理</h1> <p>ChatGPT是纯文本互动,那么如何让它跟Avatar虚拟人联系呢?<br> 首先我们已知一个先验:</p> <ul> <li>即构Avatar有文本驱动能力,即给Avatar输入一段文本,Avatar根据文本渲染口型+播报语音</li> <li>将观众在直播间发送的弹幕消息抓取后,发送给OpenAI的ChatGPT服务器</li> <li>得到ChatGPT回复后将回复内容通过Avatar语音播报<br> 在观众看来,这就是在跟拥有ChatGPT一样智商的虚拟人直播互动了。</li> </ul> <h1> <a id="2__24"></a>2 本文使用的工具</h1> <ul> <li>GPT虚拟直播弹幕:即构ZIM语聊房群聊弹幕</li> <li>GPT4.0:New bing</li> <li>GPT3.5:ChatGPT</li> </ul> <h1> <a id="3_ChatGPT_30"></a>3 对接ChatGPT</h1> <p>这里主要推荐2个库:</p> <ul> <li>chatgpt-api</li> <li>chatgpt</li> </ul> <p>chatgpt-api封装了基于bing的chatgpt4.0,chatgpt基于openAI官方的chatgpt3.5。具体如何创建bing账号以及如何获取Cookie值以及如何获取apiKey,可以参考我另一篇文章《人人都能用ChatGPT4.0做Avatar虚拟人直播》。</p> <h2> <a id="31_chatgptapi_37"></a>3.1 chatgpt-api</h2> <p>安装:</p> <pre><code class="prism language-BASH">npm i @waylaidwanderer/chatgpt-api </code></pre> <p>bing还没有对中国大陆开放chatgpt,因此需要一个代理,因此需要把代理地址也一起封装。代码如下:</p> <pre><code class="prism language-javascript"> <span class="token keyword">import</span> <span class="token punctuation">{<!-- --></span> BingAIClient <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@waylaidwanderer/chatgpt-api'</span><span class="token punctuation">;</span><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">BingGPT</span> <span class="token punctuation">{<!-- --></span><span class="token comment">/** http_proxy, apiKey**/</span><span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">http_proxy<span class="token punctuation">,</span> userCookie</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">this</span><span class="token punctuation">.</span>api <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span>http_proxy<span class="token punctuation">,</span> userCookie<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">this</span><span class="token punctuation">.</span>conversationSignature <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><span class="token keyword">this</span><span class="token punctuation">.</span>conversationId <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><span class="token keyword">this</span><span class="token punctuation">.</span>clientId <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><span class="token keyword">this</span><span class="token punctuation">.</span>invocationId <span class="token operator">=</span> <span class="token string">""</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token parameter">http_proxy<span class="token punctuation">,</span> userCookie</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>http_proxy<span class="token punctuation">,</span> userCookie<span class="token punctuation">)</span><span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span> host<span class="token operator">:</span> <span class="token string">'https://www.bing.com'</span><span class="token punctuation">,</span> userToken<span class="token operator">:</span> userCookie<span class="token punctuation">,</span><span class="token comment">// If the above doesn't work, provide all your cookies as a string instead</span>cookies<span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span><span class="token comment">// A proxy string like "http://<ip>:<port>"</span>proxy<span class="token operator">:</span> http_proxy<span class="token punctuation">,</span><span class="token comment">// (Optional) Set to true to enable `console.debug()` logging</span>debug<span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">BingAIClient</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token comment">//</span><span class="token comment">//此处省略chat函数......</span><span class="token comment">//</span> <span class="token punctuation">}</span> </code></pre> <p>上面代码完成了VPN和BingAIClient的封装,还缺少聊天接口,因此添加chat函数完成聊天功能:</p> <pre><code class="prism language-javascript"><span class="token comment">//调用chatpgt </span> <span class="token function">chat</span><span class="token punctuation">(</span><span class="token parameter">text<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">var</span> res<span class="token operator">=</span><span class="token string">""</span><span class="token keyword">var</span> that <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"正在向bing发送提问"</span><span class="token punctuation">,</span> text <span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>api<span class="token punctuation">.</span><span class="token function">sendMessage</span><span class="token punctuation">(</span>text<span class="token punctuation">,</span> <span class="token punctuation">{<!-- --></span> toneStyle<span class="token operator">:</span> <span class="token string">'balanced'</span><span class="token punctuation">,</span><span class="token function-variable function">onProgress</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">token</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">if</span><span class="token punctuation">(</span>token<span class="token punctuation">.</span>length<span class="token operator">==</span><span class="token number">2</span> <span class="token operator">&&</span> token<span class="token punctuation">.</span><span class="token function">charCodeAt</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token operator">==</span><span class="token number">55357</span><span class="token operator">&&</span>token<span class="token punctuation">.</span><span class="token function">charCodeAt</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token operator">==</span><span class="token number">56842</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span><span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> res<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span> res<span class="token operator">+=</span>token<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">response</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> that<span class="token punctuation">.</span>conversationSignature <span class="token operator">=</span> response<span class="token punctuation">.</span>conversationSignature<span class="token punctuation">;</span>that<span class="token punctuation">.</span>conversationId <span class="token operator">=</span> response<span class="token punctuation">.</span>conversationId<span class="token punctuation">;</span>that<span class="token punctuation">.</span>clientId <span class="token operator">=</span> response<span class="token punctuation">.</span>clientId<span class="token punctuation">;</span>that<span class="token punctuation">.</span>invocationId <span class="token operator">=</span> response<span class="token punctuation">.</span>invocationId<span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>在使用的时候只需如下调用:</p> <pre><code class="prism language-javascript"><span class="token keyword">var</span> bing <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">BingGPT</span><span class="token punctuation">(</span><span class="token constant">HTTP_PROXY</span><span class="token punctuation">,</span> <span class="token constant">BING_USER_COOKIE</span><span class="token punctuation">)</span><span class="token punctuation">;</span> bing<span class="token punctuation">.</span><span class="token function">chat</span><span class="token punctuation">(</span><span class="token string">"这里传入提问内容XXXX?"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">succ<span class="token punctuation">,</span> response</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span><span class="token keyword">if</span><span class="token punctuation">(</span>succ<span class="token punctuation">)</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"回复内容:"</span><span class="token punctuation">,</span> response<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> </code></pre> <p>需要注意的是,基于bing的chatgpt4.0主要是通过模拟浏览器方式封住。在浏览器端有很多防机器人检测,因此容易被卡断。这里笔者建议仅限自己体验,不适合作为产品接口使用。如果需要封装成产品,建议使用下一节2.2内容。</p> <h2> <a id="32_chatgpt_112"></a>3.2 chatgpt</h2> <p>安装:</p> <pre><code class="prism language-bash"><span class="token function">npm</span> <span class="token function">install</span> chatgpt </code></pre> <p>跟上一小节2.1类似,基于openAI的chatgpt3.5依旧需要梯子才能使用。chatgpt库没有内置代理能力,因此我们可以自己安装代理库:</p> <pre><code class="prism language-bash"><span class="token function">npm</span> <span class="token function">install</span> https-proxy-agent node-fetch </code></pre> <p>接下来将代理和chatgpt库一起集成封装成一个类:</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{<!-- --></span> ChatGPTAPI <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"chatgpt"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> proxy <span class="token keyword">from</span> <span class="token string">"https-proxy-agent"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> nodeFetch <span class="token keyword">from</span> <span class="token string">"node-fetch"</span><span class="token punctuation">;</span><span class="token keyword">export</span> <span class="token keyword">class</span> <span class="token class-name">ChatGPT</span> <span class="token punctuation">{<!-- --></span><span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">http_proxy<span class="token punctuation">,</span> apiKey</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">this</span><span class="token punctuation">.</span>api <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">init</span><span class="token punctuation">(</span>http_proxy<span class="token punctuation">,</span> apiKey<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">this</span><span class="token punctuation">.</span>conversationId <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span><span class="token keyword">this</span><span class="token punctuation">.</span>ParentMessageId <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token function">init</span><span class="token punctuation">(</span><span class="token parameter">http_proxy<span class="token punctuation">,</span> apiKey</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>http_proxy<span class="token punctuation">,</span> apiKey<span class="token punctuation">)</span><span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ChatGPTAPI</span><span class="token punctuation">(</span><span class="token punctuation">{<!-- --></span>apiKey<span class="token operator">:</span> apiKey<span class="token punctuation">,</span><span class="token function-variable function">fetch</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token parameter">url<span class="token punctuation">,</span> options <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{<!-- --></span><span class="token keyword">const</span> defaultOptions <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span>agent<span class="token operator">:</span> <span class="token function">proxy</span><span class="token punctuation">(</span>http_proxy<span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token keyword">const</span> mergedOptions <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span><span class="token operator">...</span>defaultOptions<span class="token punctuation">,</span><span class="token operator">...</span>options<span class="token punctuation">,</span><span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token function">nodeFetch</span><span class="token punctuation">(</span>url<span class="token punctuation">,</span> mergedOptions<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">,</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token comment">//...</span><span class="token comment">//此处省略chat函数</span><span class="token comment">//...</span> <span class="token punctuation">}</span> </code></pre> <p>完成ChatGPTAPI的封装后,接下来添加聊天接口:</p> <pre><code class="prism language-javascript"><span class="token comment">//调用chatpgt </span> <span class="token function">chat</span><span class="token punctuation">(</span><span class="token parameter">text<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">let</span> that <span class="token operator">=</span> <span class="token keyword">this</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"正在向ChatGPT发送提问:"</span><span class="token punctuation">,</span> text<span class="token punctuation">)</span>that<span class="token punctuation">.</span>api<span class="token punctuation">.</span><span class="token function">sendMessage</span><span class="token punctuation">(</span>text<span class="token punctuation">,</span> <span class="token punctuation">{<!-- --></span>conversationId<span class="token operator">:</span> that<span class="token punctuation">.</span>ConversationId<span class="token punctuation">,</span>parentMessageId<span class="token operator">:</span> that<span class="token punctuation">.</span>ParentMessageId<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>that<span class="token punctuation">.</span>ConversationId <span class="token operator">=</span> res<span class="token punctuation">.</span>conversationIdthat<span class="token punctuation">.</span>ParentMessageId <span class="token operator">=</span> res<span class="token punctuation">.</span>idcb <span class="token operator">&&</span> <span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> res<span class="token punctuation">.</span>text<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span>cb <span class="token operator">&&</span> <span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>使用时就非常简单:</p> <pre><code class="prism language-javascript"><span class="token keyword">var</span> chatgpt <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ChatGPT</span><span class="token punctuation">(</span><span class="token constant">HTTP_PROXY</span><span class="token punctuation">,</span> <span class="token constant">API_KEY</span><span class="token punctuation">)</span><span class="token punctuation">;</span> chatgpt<span class="token punctuation">.</span><span class="token function">chat</span><span class="token punctuation">(</span><span class="token string">"这里传入提问内容XXXX?"</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">succ<span class="token punctuation">,</span> response</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span><span class="token keyword">if</span><span class="token punctuation">(</span>succ<span class="token punctuation">)</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"回复内容:"</span><span class="token punctuation">,</span> response<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> </code></pre> <p>chatgpt库主要基于openAI的官方接口,相对来说比较稳定,推荐这种方式使用。</p> <h2> <a id="33__189"></a>3.3 两库一起封装</h2> <p>为了更加灵活方便使用,随意切换chatgpt3.5和chatgpt4.0。将以上两个库封装到一个接口中。</p> <p>首先创建一个文件保存各种配置, KeyCenter.js:</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> <span class="token constant">HTTP_PROXY</span> <span class="token operator">=</span> <span class="token string">"http://127.0.0.1:xxxx"</span><span class="token punctuation">;</span><span class="token comment">//本地vpn代理端口</span> <span class="token comment">//openAI的key, </span> <span class="token keyword">const</span> <span class="token constant">API_KEY</span> <span class="token operator">=</span> <span class="token string">"sk-xxxxxxxxxxxxxxxxxxxxxxxxx"</span><span class="token punctuation">;</span> <span class="token comment">//bing cookie</span> <span class="token keyword">const</span> <span class="token constant">BING_USER_COOKIE</span> <span class="token operator">=</span> <span class="token string">'xxxxxxxxxxxxxxxxxxxxxxxx--BA'</span><span class="token punctuation">;</span>module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span> <span class="token constant">HTTP_PROXY</span><span class="token operator">:</span> <span class="token constant">HTTP_PROXY</span><span class="token punctuation">,</span><span class="token constant">API_KEY</span><span class="token operator">:</span> <span class="token constant">API_KEY</span><span class="token punctuation">,</span><span class="token constant">BING_USER_COOKIE</span><span class="token operator">:</span><span class="token constant">BING_USER_COOKIE</span> <span class="token punctuation">}</span></code></pre> <p>注意,以上相关配置内容需要读者替换。</p> <p>接下来封装两个不同版本的chatGPT:</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> <span class="token constant">KEY_CENTER</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"../KeyCenter.js"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> ChatGPTObj <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">,</span> BingGPTObj <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span> <span class="token comment">//初始化chatgpt</span> <span class="token keyword">function</span> <span class="token function">getChatGPT</span><span class="token punctuation">(</span><span class="token parameter">onInitedCb</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">if</span> <span class="token punctuation">(</span>ChatGPTObj <span class="token operator">!=</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">onInitedCb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> ChatGPTObj<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{<!-- --></span><span class="token keyword">let</span> <span class="token punctuation">{<!-- --></span> ChatGPT <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">"./chatgpt.mjs"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">ChatGPT</span><span class="token punctuation">(</span><span class="token constant">KEY_CENTER</span><span class="token punctuation">.</span><span class="token constant">HTTP_PROXY</span><span class="token punctuation">,</span> <span class="token constant">KEY_CENTER</span><span class="token punctuation">.</span><span class="token constant">API_KEY</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>ChatGPTObj <span class="token operator">=</span> obj<span class="token punctuation">;</span><span class="token function">onInitedCb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> obj<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">onInitedCb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token keyword">function</span> <span class="token function">getBingGPT</span><span class="token punctuation">(</span><span class="token parameter">onInitedCb</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span><span class="token keyword">if</span><span class="token punctuation">(</span>BingGPTObj<span class="token operator">!=</span><span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">onInitedCb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> BingGPTObj<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{<!-- --></span><span class="token keyword">let</span> <span class="token punctuation">{<!-- --></span> BingGPT <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">import</span><span class="token punctuation">(</span><span class="token string">"./binggpt.mjs"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">BingGPT</span><span class="token punctuation">(</span><span class="token constant">KEY_CENTER</span><span class="token punctuation">.</span><span class="token constant">HTTP_PROXY</span><span class="token punctuation">,</span> <span class="token constant">KEY_CENTER</span><span class="token punctuation">.</span><span class="token constant">BING_USER_COOKIE</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>BingGPTObj <span class="token operator">=</span> obj<span class="token punctuation">;</span><span class="token function">onInitedCb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> obj<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token function">onInitedCb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>上面两个函数<code>getBingGPT</code>和<code>getChatGPT</code>分别对应<code>2.1节</code>和<code>2.2节</code>封装的版本。在切换版本的时候直接调用对应的函数即可,但笔者认为,还不够优雅!使用起来还是不够舒服,因为需要维护不同的对象。最好能进一步封装,调用的时候一行代码来使用是最好的。那进一步封装,补充以下代码:</p> <pre><code class="prism language-javascript"><span class="token comment">//调用chatgpt聊天</span> <span class="token keyword">function</span> <span class="token function">chatGPT</span><span class="token punctuation">(</span><span class="token parameter">text<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">getChatGPT</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">succ<span class="token punctuation">,</span> obj</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">if</span> <span class="token punctuation">(</span>succ<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>obj<span class="token punctuation">.</span><span class="token function">chat</span><span class="token punctuation">(</span>text<span class="token punctuation">,</span> cb<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>cb <span class="token operator">&&</span> <span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">"chatgpt not inited!!!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token keyword">function</span> <span class="token function">chatBing</span><span class="token punctuation">(</span><span class="token parameter">text<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span><span class="token function">getBingGPT</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">succ<span class="token punctuation">,</span> obj</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">if</span> <span class="token punctuation">(</span>succ<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>obj<span class="token punctuation">.</span><span class="token function">chat</span><span class="token punctuation">(</span>text<span class="token punctuation">,</span> cb<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>cb <span class="token operator">&&</span> <span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> <span class="token string">"chatgpt not inited!!!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">}</span>module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span>chatGPT<span class="token operator">:</span> chatGPT<span class="token punctuation">,</span>chatBing<span class="token operator">:</span>chatBing <span class="token punctuation">}</span> </code></pre> <p>加了以上代码后,就舒服多了:想要使用bing的chatgpt4.0,那就调用chatBing函数好了;想要使用openAI官方的chatgpt3.5,那就调用chatGPT函数就好!</p> <h1> <a id="4_Avatar_279"></a>4 对接Avatar</h1> <h2> <a id="41__281"></a>4.1 基本思路</h2> <p>好了,第2节介绍了对chatgpt的封装,不同的版本只需调用不同函数即可实现与chatgpt对话。接下来怎么将chatGPT的文本对话内容传递给Avatar呢?即构Avatar是即构推出的一款虚拟形象产品,它可以跟即构内的其他产品对接,比如即时通讯ZIM和音视频通话RTC。这就好办了,我们只需利用ZIM或RTC即可。</p> <p>这里我们主要利用即构ZIM实现,因为即构ZIM非常方便实时文本内容。即构ZIM群聊消息稳定可靠,延迟低,全球任何一个地区都有接入服务的节点保障到达。</p> <p><strong>尤其是ZIM群聊有弹幕功能,相比发送聊天消息,发送弹幕消息不会被存储,更适合直播间评论功能。</strong></p> <h2> <a id="42__290"></a>4.2 代码实现</h2> <p>即构官方提供的js版本库主要是基于浏览器,需要使用到浏览器的特性如DOM、localStorage等。而这里我们主要基于NodeJS,没有浏览器环境。因此我们需要安装一些必要的库, 相关库已经在package.json有记录,直接执行如下命令即可:</p> <pre><code class="prism language-cmd">npm install </code></pre> <h3> <a id="421__296"></a>4.2.1 创建模拟浏览器环境</h3> <p>首先执行浏览器环境模拟,通过fake-indexeddb、jsdom、node-localstorage库模拟浏览器环境以及本地存储环境。创建WebSocket、XMLHttpRequest等全局对象。</p> <pre><code class="prism language-javascript"><span class="token keyword">var</span> fs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'fs'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//先清理缓存</span> fs<span class="token punctuation">.</span><span class="token function">readdirSync</span><span class="token punctuation">(</span><span class="token string">'./local_storage'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">fileName</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>fs<span class="token punctuation">.</span><span class="token function">unlinkSync</span><span class="token punctuation">(</span><span class="token string">'./local_storage/'</span> <span class="token operator">+</span> fileName<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">const</span> <span class="token constant">KEY_CENTER</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"../KeyCenter.js"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token constant">APPID</span> <span class="token operator">=</span> <span class="token constant">KEY_CENTER</span><span class="token punctuation">.</span><span class="token constant">APPID</span><span class="token punctuation">,</span> <span class="token constant">SERVER_SECRET</span> <span class="token operator">=</span> <span class="token constant">KEY_CENTER</span><span class="token punctuation">.</span><span class="token constant">SERVER_SECRET</span><span class="token punctuation">;</span> <span class="token keyword">const</span> generateToken04 <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./TokenUtils.js'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>generateToken04<span class="token punctuation">;</span> <span class="token keyword">var</span> LocalStorage <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'node-localstorage'</span><span class="token punctuation">)</span><span class="token punctuation">.</span>LocalStorage<span class="token punctuation">;</span> localStorage <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LocalStorage</span><span class="token punctuation">(</span><span class="token string">'./local_storage'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">var</span> indexedDB <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"fake-indexeddb/auto"</span><span class="token punctuation">)</span><span class="token punctuation">.</span>indexedDB<span class="token punctuation">;</span> <span class="token keyword">const</span> jsdom <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"jsdom"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token punctuation">{<!-- --></span> <span class="token constant">JSDOM</span> <span class="token punctuation">}</span> <span class="token operator">=</span> jsdom<span class="token punctuation">;</span> <span class="token keyword">const</span> dom <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">JSDOM</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">,</span> <span class="token punctuation">{<!-- --></span>url<span class="token operator">:</span> <span class="token string">"http://localhost/"</span><span class="token punctuation">,</span>referrer<span class="token operator">:</span> <span class="token string">"http://localhost/"</span><span class="token punctuation">,</span>contentType<span class="token operator">:</span> <span class="token string">"text/html"</span><span class="token punctuation">,</span>includeNodeLocations<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>storageQuota<span class="token operator">:</span> <span class="token number">10000000</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> window <span class="token operator">=</span> dom<span class="token punctuation">.</span>window<span class="token punctuation">;</span> document <span class="token operator">=</span> window<span class="token punctuation">.</span>document<span class="token punctuation">;</span> navigator <span class="token operator">=</span> window<span class="token punctuation">.</span>navigator<span class="token punctuation">;</span> location <span class="token operator">=</span> window<span class="token punctuation">.</span>location<span class="token punctuation">;</span> WebSocket <span class="token operator">=</span> window<span class="token punctuation">.</span>WebSocket<span class="token punctuation">;</span> XMLHttpRequest <span class="token operator">=</span> window<span class="token punctuation">.</span>XMLHttpRequest<span class="token punctuation">;</span> </code></pre> <h3> <a id="422_ZIM_330"></a>4.2.2 创建ZIM对象</h3> <p>将即构官方下载的index.js引入,获取ZIM类并实例化,这个过程封装到createZIM函数中。需要注意的是登录需要Token,为了安全考虑,Token建议在服务器端生成。接下来把整个初始化过程封装到initZego函数中,包含注册监听接收消息,监控Token过期并重置。</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> <span class="token constant">ZIM</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./index.js'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token constant">ZIM</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">newToken</span><span class="token punctuation">(</span><span class="token parameter">userId</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">const</span> token <span class="token operator">=</span> <span class="token function">generateToken04</span><span class="token punctuation">(</span><span class="token constant">APPID</span><span class="token punctuation">,</span> userId<span class="token punctuation">,</span> <span class="token constant">SERVER_SECRET</span><span class="token punctuation">,</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">60</span> <span class="token operator">*</span> <span class="token number">24</span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span> token<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/*** 创建ZIM对象 */</span> <span class="token keyword">function</span> <span class="token function">createZIM</span><span class="token punctuation">(</span><span class="token parameter">onError<span class="token punctuation">,</span> onRcvMsg<span class="token punctuation">,</span> onTokenWillExpire</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">var</span> zim <span class="token operator">=</span> <span class="token constant">ZIM</span><span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token constant">APPID</span><span class="token punctuation">)</span><span class="token punctuation">;</span>zim<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'error'</span><span class="token punctuation">,</span> onError<span class="token punctuation">)</span><span class="token punctuation">;</span>zim<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'receivePeerMessage'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> msgObj</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"收到P2P消息"</span><span class="token punctuation">)</span><span class="token function">onRcvMsg</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> zim<span class="token punctuation">,</span> msgObj<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">// 收到群组消息的回调</span>zim<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'receiveRoomMessage'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> msgObj</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"收到群组消息"</span><span class="token punctuation">)</span><span class="token function">onRcvMsg</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> zim<span class="token punctuation">,</span> msgObj<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>zim<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'tokenWillExpire'</span><span class="token punctuation">,</span> onTokenWillExpire<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">return</span> zim<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/* *初始化即构ZIM */</span> <span class="token keyword">function</span> <span class="token function">initZego</span><span class="token punctuation">(</span><span class="token parameter">onError<span class="token punctuation">,</span> onRcvMsg<span class="token punctuation">,</span> myUID</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">var</span> token <span class="token operator">=</span> <span class="token function">newToken</span><span class="token punctuation">(</span>myUID<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">var</span> startTimestamp <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token keyword">function</span> <span class="token function">_onError</span><span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">onError</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">function</span> <span class="token function">_onRcvMsg</span><span class="token punctuation">(</span><span class="token parameter">isFromGroup<span class="token punctuation">,</span> zim<span class="token punctuation">,</span> msgObj</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">var</span> msgList <span class="token operator">=</span> msgObj<span class="token punctuation">.</span>messageList<span class="token punctuation">;</span><span class="token keyword">var</span> fromConversationID <span class="token operator">=</span> msgObj<span class="token punctuation">.</span>fromConversationID<span class="token punctuation">;</span>msgList<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">msg</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">if</span> <span class="token punctuation">(</span>msg<span class="token punctuation">.</span>timestamp <span class="token operator">-</span> startTimestamp <span class="token operator">>=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//过滤掉离线消息</span><span class="token keyword">var</span> out <span class="token operator">=</span> <span class="token function">parseMsg</span><span class="token punctuation">(</span>zim<span class="token punctuation">,</span> isFromGroup<span class="token punctuation">,</span> msg<span class="token punctuation">.</span>message<span class="token punctuation">,</span> fromConversationID<span class="token punctuation">)</span><span class="token keyword">if</span> <span class="token punctuation">(</span>out<span class="token punctuation">)</span><span class="token function">onRcvMsg</span><span class="token punctuation">(</span>out<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token keyword">function</span> <span class="token function">onTokenWillExpire</span><span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> second</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>token <span class="token operator">=</span> <span class="token function">newToken</span><span class="token punctuation">(</span>userId<span class="token punctuation">)</span><span class="token punctuation">;</span>zim<span class="token punctuation">.</span><span class="token function">renewToken</span><span class="token punctuation">(</span>token<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token keyword">var</span> zim <span class="token operator">=</span> <span class="token function">createZIM</span><span class="token punctuation">(</span>_onError<span class="token punctuation">,</span> _onRcvMsg<span class="token punctuation">,</span> onTokenWillExpire<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token function">login</span><span class="token punctuation">(</span>zim<span class="token punctuation">,</span> myUID<span class="token punctuation">,</span> token<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">succ<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">if</span> <span class="token punctuation">(</span>succ<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"登录成功!"</span><span class="token punctuation">)</span><span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"登录失败!"</span><span class="token punctuation">,</span> data<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token keyword">return</span> zim<span class="token punctuation">;</span> <span class="token punctuation">}</span></code></pre> <h3> <a id="423__400"></a>4.2.3 登录、创建房间、加入房间、离开房间</h3> <p>调用zim对象的login函数完成登录,封装到login函数中;调用zim对象的joinRoom完成加入房间,封装到joinRoom函数中;调用zim的leaveRoom函数完成退出房间,封装到leaveRoom函数中。</p> <pre><code class="prism language-javascript"><span class="token comment">/*** 登录即构ZIM */</span> <span class="token keyword">function</span> <span class="token function">login</span><span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> userId<span class="token punctuation">,</span> token<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token keyword">var</span> userInfo <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span> userID<span class="token operator">:</span> userId<span class="token punctuation">,</span> userName<span class="token operator">:</span> userId <span class="token punctuation">}</span><span class="token punctuation">;</span>zim<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>userInfo<span class="token punctuation">,</span> token<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/*** 加入房间 */</span> <span class="token keyword">function</span> <span class="token function">joinRoom</span><span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> roomId<span class="token punctuation">,</span> cb <span class="token operator">=</span> <span class="token keyword">null</span></span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>zim<span class="token punctuation">.</span><span class="token function">joinRoom</span><span class="token punctuation">(</span>roomId<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{<!-- --></span> roomInfo <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>cb <span class="token operator">&&</span> <span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> roomInfo<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>cb <span class="token operator">&&</span> <span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/*** 离开房间 */</span> <span class="token keyword">function</span> <span class="token function">leaveRoom</span><span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> roomId</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>zim<span class="token punctuation">.</span><span class="token function">leaveRoom</span><span class="token punctuation">(</span>roomId<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{<!-- --></span> roomID <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token comment">// 操作成功</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"已离开房间"</span><span class="token punctuation">,</span> roomID<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token comment">// 操作失败</span>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"离开房间失败"</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <h3> <a id="424__446"></a>4.2.4 发送消息、解析消息</h3> <p>发送消息分为一对一发送和发送到房间,这里通过isGroup参数来控制,如下sendMsg函数所示。将接收消息UID和发送内容作为sendMsg参数,最终封装并调用ZIM的sendMessage函数完成消息发送。</p> <p>接收到消息后,在我们的应用中设置了发送的消息内容是个json对象,因此需要对内容进行解析,具体的json格式可以参考完整源码,这里不做详细讲解。</p> <pre><code class="prism language-javascript"><span class="token comment">/*** 发送消息 */</span> <span class="token keyword">function</span> <span class="token function">sendMsg</span><span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> isGroup<span class="token punctuation">,</span> msg<span class="token punctuation">,</span> toUID<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">var</span> type <span class="token operator">=</span> isGroup <span class="token operator">?</span> <span class="token number">1</span> <span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// 会话类型,取值为 单聊:0,房间:1,群组:2</span><span class="token keyword">var</span> config <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span>priority<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token comment">// 设置消息优先级,取值为 低:1(默认),中:2,高:3</span><span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">var</span> messageTextObj <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span> type<span class="token operator">:</span> <span class="token number">20</span><span class="token punctuation">,</span> message<span class="token operator">:</span> msg<span class="token punctuation">,</span> extendedData<span class="token operator">:</span> <span class="token string">''</span> <span class="token punctuation">}</span><span class="token punctuation">;</span><span class="token keyword">var</span> notification <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span><span class="token function-variable function">onMessageAttached</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">message</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"已发送"</span><span class="token punctuation">,</span> message<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">}</span> zim<span class="token punctuation">.</span><span class="token function">sendMessage</span><span class="token punctuation">(</span>messageTextObj<span class="token punctuation">,</span> toUID<span class="token punctuation">,</span> type<span class="token punctuation">,</span> config<span class="token punctuation">,</span> notification<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{<!-- --></span> message <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token comment">// 发送成功</span><span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token comment">// 发送失败</span><span class="token function">cb</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">,</span> err<span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/*** 解析收到的消息 */</span> <span class="token keyword">function</span> <span class="token function">parseMsg</span><span class="token punctuation">(</span><span class="token parameter">zim<span class="token punctuation">,</span> isFromGroup<span class="token punctuation">,</span> msg<span class="token punctuation">,</span> fromUid</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span><span class="token comment">//具体实现略</span> <span class="token punctuation">}</span> </code></pre> <h3> <a id="425__484"></a>4.2.5 导出接口</h3> <p>有了以上的实现后,把关键函数导出暴露给其他业务调用:</p> <pre><code class="prism language-javascript">module<span class="token punctuation">.</span>exports <span class="token operator">=</span> <span class="token punctuation">{<!-- --></span>initZego<span class="token operator">:</span> initZego<span class="token punctuation">,</span>sendMsg<span class="token operator">:</span> sendMsg<span class="token punctuation">,</span>joinRoom<span class="token operator">:</span> joinRoom <span class="token punctuation">}</span> </code></pre> <p>以上代码主要封装:</p> <ol> <li>即构ZIM初始化</li> <li>发送消息</li> <li>加入房间</li> </ol> <p>至此,我们就具备了将chatgpt消息群发到一个房间的能力、加入房间、接收到房间的弹幕消息能力。</p> <p>更多关于即构ZIM接口与官方Demo可以点击参考这里,对即构ZIM了解更多可以点击这里</p> <p>关于Avatar如何播报chatgpt内容,我们在下一篇文章实现。</p> <h1> <a id="5__506"></a>5 相关代码</h1> <ol><li>nodejs接入chatgpt与即构zim</li></ol> </div> <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/markdown_views-98b95bb57c.css" rel="stylesheet"> <link href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/style-c216769e99.css" rel="stylesheet"> </div> <div id="treeSkill"></div> </article>
「GPT实战」GPT接入直播间实现虚拟人互动
作者
sockstack
许可协议
CC BY 4.0
发布于
2023-11-27
修改于
2024-09-05
上一篇:软件:常用 Linux 软件汇总,值得收藏
下一篇:国内版 ChatGPT值不值得上手----PlumGPT测评
尚未登录
登录 / 注册
文章分类
博客重构之路
5
Spring Boot简单入门
4
k8s 入门教程
0
MySQL 知识
1
NSQ 消息队列
0
ThinkPHP5 源码分析
5
使用 Docker 从零开始搭建私人代码仓库
3
日常开发汇总
3
标签列表
springboot
hyperf
swoole
webman
php
多线程
数据结构
docker
k8s
thinkphp
mysql
tailwindcss
flowbite
css
前端