打造个人知识库-chatwithrtx接口研究

前言

之前安装了chatwithrtx,确实挺好用的。但是如果想用其对外提供服务的话,还需要研究是否能够提供api接口进行调用,所以今天来进行一下研究。

gradio介绍

web的访问是通过gradio框架进行开发的。在user_interface.py中可以发现如下引用

import gradio as gr

Gradio 是一个用于快速创建和共享机器学习模型的Web界面的Python库。它允许开发者和研究人员轻松地为他们的模型创建交互式的、可分享的Web应用,无需编写前端代码。通过Gradio,用户可以通过简单的图形界面与机器学习模型进行交互,比如上传图片进行分类、输入文本进行翻译或情感分析、或者使用其他输入数据类型。

Gradio 的主要特点包括:
1、易于使用:只需几行代码,就可以为模型创建交互式界面。
2、支持多种输入和输出类型:包括文本、图片、音频、视频等。
3、可分享:Gradio 应用可以生成URL,方便与他人分享或嵌入到网站中。
4、集成:可以轻松集成到Jupyter笔记本中,也支持与主流的机器学习库(如Ten5、sorFlow、PyTorch)和数据科学库(如pandas)一起使用。
6、自动文档:Gradio 可以自动生成接口的使用文档。
7、Gradio 被广泛用于机器学习、数据科学项目的原型设计、演示和评估阶段,让非技术用户也能轻松地理解和使用复杂的模型。

前端调试

通过F12调试,我们发现如下结论0c0a6ba59fcd2959805521f407a7399f.png

问答结果推送

问答结果,是以event-stream方式进行推送,如下图

438fcd88c1ccfb4f2fcdcc9a7d37ade9.png f5e71acca157094fc8a302329e64a917.png

为json的方式进行返回

{
  "msg": "process_completed",
  "event_id": "a0ae8b3a9deb4b21a40c4d7c2beba5fe",
  "output": {
    "data": [
      [
        [
          "你好",
          "你好!我很高兴能为您提供帮助。如何可以帮助您?"
        ]
      ],
      null
    ],
    "is_generating": true,
    "duration": 0.031991243362426758,
    "average_duration": 0.05873284415294059
  },
  "success": true
}

text/event-stream是一种MIME类型,用于HTTP服务器推送技术,这项技术通常称为Server-Sent Events(SSE)。它允许一个web服务器实时地向浏览器推送事件或消息。这种通信方式是单向的:从服务器到客户端(浏览器),而不需要客户端周期性地向服务器发起请求来检查更新。

服务器设置:在服务器端,响应的Content-Type设置为text/event-stream,然后通过一个持续开放的HTTP连接发送数据。
Server-Sent Events适用于需要实时数据更新的应用,比如实时新闻报道、社交媒体更新、在线交易信息、或是游戏得分板等。与WebSocket相比,SSE只支持单向通信,但它更简单,且在某些只需要服务器到客户端单向数据流的场景下,SSE是一个更轻量级的选择。

查询接口

查询接口如下图,url地址为

http://127.0.0.1:38504/queue/join?__theme=dark

请求的数据格式

{
  "data": [
    [
      [
        "你好",
        null
      ]
    ],
    null
  ],
  "event_data": null,
  "fn_index": 40,
  "trigger_id": 45,
  "session_hash": "w0s2r1jsq5g"
}
cd38ed0377058e95fa40a433a136ba46.png 55208cddfa16991a5bd23eec4e737697.png

代码解读

由于gradio框架不太熟悉,所以只能一边看一边理解。可能理解不太到位。

监听端口

监听的端口号每次都不一样,都是随机生成的,代码如下,从1024-49000范围随机产生。

def _get_free_port(self):
        # Create a socket object
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # Set a short timeout for the connection attempt
        sock.settimeout(1)
        port = None
        while port is None:
            port = random.randint(1024, 49000)
            try:
                # Attempt to bind to the port
                sock.bind(("127.0.0.1", port))
            except OSError as e:
                port = None
                if e.errno != 98:  # errno 98: Address already in use
                    print('OS error', e)
                    break 
        sock.close()
        return port

安全校验

在启动之后,会生成一个cookie

def _open_app(self, port):
        def launch_thread(cookie):
            launch_url = f'http://127.0.0.1:{port}?cookie={cookie}&__theme=dark'
            print(f'Open {launch_url} in browser to start Chat with RTX')
            webbrowser.open(launch_url)
            return None
        
        self._secure_cookie = str(uuid.uuid4())
        threading.Thread(target=launch_thread, args=(self._secure_cookie,)).start()
        return None

安全校验如下,我相信把这一段注释掉 应该就没有安全校验了

def _validate_request(self, request: gr.Request):
        headers = request.headers
        session_key = None
        if 'cookie' in headers:
            cookies = headers['cookie']
            if '_s_chat_=' in cookies:
                cookies = cookies.split('; ')
                for i, cookie in enumerate(cookies):
                    key, value = cookie.split('=')
                    if key == '_s_chat_':
                        session_key = value
        
        if session_key == None or session_key != self._secure_cookie:
            raise 'session validation failed'
        
        return True

发送命令的时候 添加了一个_s_chat_ 的字段

e319fb3fe86d9a55f8b91c115bb5e11c.png

问答交互

问题主要有两个控件构成,一个是Chat with RTX 一个是SEND。

afb37f959a5521944fd13e6a9410fc1d.png

我们在_render_chatbot函数中可以找到。

def _render_chatbot(self, show_chatbot):
        chatbot_window = gr.Chatbot(
            show_label=False,
            elem_classes="chat-window",
            visible=show_chatbot,
            elem_id="main-chatbot-window",
            sanitize_html=False
        )
        with gr.Group() as query_group:
            with gr.Row():
                query_input = gr.Textbox(placeholder="Chat with RTX...", scale=9, container=False)
                submit_button = gr.Button("SEND", variant="primary", scale=1)

在def _handle_chatbot_events(self):函数中实现处理发送事件函数。

gr.on(
            [self._chat_query_input_textbox.submit, self._chat_submit_button.click],
            self._validate_session,
            None,
            self._get_validate_session_output()
        ).then(
            self._validate_session_and_raise,
            None,
            None
        ).success(
            self._show_hide_sample_questions,
            self._get_show_hide_sample_questions_inputs(),
            self._get_show_hide_sample_questions_outputs()
        ).then(
            process_input,
            [self._chat_query_input_textbox, self._chat_bot_window], 
            [self._chat_query_input_textbox, self._chat_bot_window]
        ).then(
            process_output,
            [self._chat_bot_window, self._state],
            [self._chat_bot_window, self._state]
        )

重点的问题消息处理的函数在

then(
            process_input,
            [self._chat_query_input_textbox, self._chat_bot_window], 
            [self._chat_query_input_textbox, self._chat_bot_window]
        )

这里有个语法问题,我看了好久。第一个是处理函数,第二个是输入参数,第三个数输出参数。
第一个 [self._chat_query_input_textbox, self._chat_bot_window] 指定了处理函数的输入来源。这意味着:当用户触发某个事件(比如提交文本或点击按钮)时,process_input 函数将会接收来自 self._chat_query_input_textbox(用户输入的文本框)和 self._chat_bot_window(聊天窗口,可能用于显示之前的交互历史)的数据作为输入。
第二个 [self._chat_query_input_textbox, self._chat_bot_window] 指明了处理函数的输出目标。这表示:process_input 函数处理完输入数据后,将会更新 self._chat_query_input_textbox 和 self._chat_bot_window 的内容。具体来说,这可能涉及到清空用户的输入框以准备下一次输入,以及在聊天窗口中显示处理结果或者更新交互历史。

然后数据处理函数找到了,在这个函数处理_query_handler

3fb34cd6eb98377aaae1cc0642fc669d.png

最后发现是在初始化的时候 外部传入进来的

def __init__(self, chatbot=None, streaming = False) -> None:
        self._interface = None
        self._query_handler = chatbot

最后在app.py 中找到了其实现的地方

def stream_chatbot(query, chat_history, session_id):
a80b80769fb4f862760747185a0322d6.png

之后就是处理问答的逻辑了。这个下一次来研究。

总结

本文主要研究了chatwithrtx的用户接口,本来想有暴露合适的api,进行直接调用,但是通过研发发现,这个框架并不是一个前后端分离的框架,界面的渲染和函数调用混合在一起。所以接下来,需要研究如何在不使用这个界面的前提下,进行问答的调用。

我的知识星球

请关注公众号g0415shenw 加入知识星球。
星球地址 https://t.zsxq.com/15EvfoA7n
星球有本人经验心得全部总结 涵盖音视频,gb28181、虚幻引擎、其他编程工具等等。另外还可以在星球提问,我会尽力答复,等于给您多了一个引路人。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/426453.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

第十六天-爬虫selenium库

目录 1.介绍 2.使用 selenium 1.安装 2.使用 1.测试打开网页,抓取雷速体育日职乙信息 2.通过xpath查找 3.输入文本框内容 send_keys 4.点击事件 click 5.获取网页源码: 6.获取cookies 7.seleniumt提供元素定位方式:8种 8.控制浏览…

算法刷题day20:二分

目录 引言概念一、借教室二、分巧克力三、管道四、技能升级五、冶炼金属六、数的范围七、最佳牛围栏 引言 这几天一直在做二分的题,都是上了难度的题目,本来以为自己的二分水平已经非常熟悉了,没想到还是糊涂了一两天才重新想清楚&#xff0…

Linux红帽rhce认证多少钱?考个RHCE难不难?

Linux作为开源操作系统的佼佼者,已经广泛应用于各个领域。红帽认证工程师(Red Hat Certified Engineer,简称RHCE)作为Linux领域权威的认证之一,自然成为了众多IT从业者追求的目标。那么,RHCE认证的培训费用是多少?考取这一认证又…

【C语言】linux内核packet_setsockopt

一、中文注释 // 发送数据包函数。它尝试通过特定的网络设备队列直接传输一个skb(socket缓冲区)。 static int packet_direct_xmit(struct sk_buff *skb) {return dev_direct_xmit(skb, packet_pick_tx_queue(skb)); // 调用dev_direct_xmit函数&#x…

写代码实现基金回测(一)

参考博客:应用实战:我的第一个开源项目-基金定投回测工具 这个博主的代码的目录结构还是很赞的 看一下他是如何计算收益率的 第一步:获取所有公募基金的基础信息 共计一万个基金 第二步:获取所有基金的费率信息 这里有一点需要…

Java基于springboot的个人理财系统

基于springboot的个人理财系统 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了个人理财系统的开发全过程。通过分析个人理财系统管理的不足,创建了一个计算机管理个人理财系统的方案。文章介绍了个…

bxCAN总线的工作模式和测试模式(STM32F4xx)

概述 本文主要介绍STM32F4XX的bxCAN知识,包括bxCAN的概念,各种工作模式下特性,如何配置各类工作模式等内容,还介绍了bxCAN的测试模式,bxCAN测试模式有3种工作类型,每种类型有什么特性,以及如何配…

【大厂AI课学习笔记NO.66】TensorFlow

TensorFlow 这个框架,实在是太有名了,最近周红衣都在大力的宣传和讲解。 他说的是对的,人工智能,就是大力出奇迹,就是大量的算力,大量的数据,加上模型的加持,实现的智能感觉。 Goog…

【字符串】马拉车(Manacher)算法

本篇文章参考:比较易懂的 Manacher(马拉车)算法配图详解 马拉车算法可以求出一个字符串中的最长回文子串,时间复杂度 O ( n ) O(n) O(n) 因为字符串长度的奇偶性,回文子串的中心可能是一个字符,也可能是…

webpack源码分析——tapable中before和stage如何改变执行顺序

一、Before用法 Before 用法 before 属性的值可以传入一个数组或者字符串,值为注册事件对象时的名称,它可以修改当前事件函数在传入的事件名称对应的函数之前进行执行。 示例 let hook new SyncWaterfallHook([arg1]);hook.tap(tap1, (arg)> {console.log(tap1…

安装 node 错误的配置环境变量之后使用 npm 报错

安装 node 错误的配置环境变量之后使用 npm 报错 node:internal/modules/cjs/loader:1147 throw err; ^ Error: Cannot find module ‘F:\ACodeTools\Node\node_modules\npm\bin\node_modules\npm\bin\npm-cli.js’ at Module._resolveFilename (node:internal/modules/cjs/loa…

Git推送本地仓库至阿里云仓库

Git推送本地仓库至阿里云仓库 1.安装Git 参考Git安装详解 2.生成 SSH 密钥 基于RSA算法SSH 密钥 1.管理员权限运行Git Bash 2.输入生成密钥指令点击回车,选择 SSH 密钥生成路径。 $ ssh-keygen -t rsa -C "2267521563qq.com"3.以 RSA算法为例&…

TMGM官网平台联合英超豪门切尔西

TMGM官网平台联合英超豪门切尔西 TMGM澳洲总部客户经理 🌏:TMGM818 TMGM中国官网【TMGM558】TMGM联合英超豪门切尔西俱乐部深度合作,去年全球客户成交额突破4650亿美元,在泰国曼谷周杰伦演唱会唯一平台品牌赞助商,作为…

IOC中Bean的生命周期

生命周期的各个阶段: 可以分为三个阶段:产生-使用-销毁 又可以分四个阶段:四个阶段 实例化 ->属性注入->初始化 ->销毁 实例化后到使用的初始化过程: 属性赋值 ->处理各种Aware接口->实现BeanPostProcessor的b…

数据结构/C++:二叉搜索树

数据结构/C:二叉搜索树 概念模拟实现结构分析插入中序遍历查找删除析构函数拷贝构造赋值重载递归查找递归插入递归删除 总代码展示 概念 二叉搜索树(BST - Binary Search Tree)是一种特殊的二叉树,每个顶点最多可以有两个子节点。…

逆向案例四:360k静态和精灵数据动态AES解密,用js的方法

一、360K 网页链接:https://www.36kr.com/p/2672600261670407 页面中有静态的需要解密的内容,确定html包,确定方法 1.1方法步骤 在下方的搜索中输入decrypt(或者关键字window.initialState ,进入js文件 在AES.decrypt处打上断点&#xff0…

【Java项目介绍和界面搭建】拼图小游戏——键盘、鼠标事件

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收藏 …

15-Linux部署HBase集群

Linux部署HBase集群 简介 HBase 是一种分布式、可扩展、支持海量数据存储的 NoSQL 数据库。 和Redis一样,HBase是一款KeyValue型存储的数据库。 不过和Redis设计方向不同 Redis设计为少量数据,超快检索HBase设计为海量数据,快速检索 HB…

运行Python文件时出现‘utf-8’code can‘t decode byte 如何解决?(如图)

如图 亦或者出现“SyntaxError: Non-UTF-8 code starting with \xbb ” 出现这种问题往往是编码格式导致的,我们可以在py文件中的第一行加入以下代码: # codingutf-8或者 # codinggdk优先使用gbk编码 解释一下常用的两种编码格式: utf-…

供应链管理(SCM):界面设计全面扫盲,得供应链者得天下

大家伙,我是大千UI工场,专注UI分享和项目接单,本期带来供应链系统的设计分享,欢迎大家关注、互动交流。 一、什么是SCM SCM系统是供应链管理(Supply Chain Management)系统的缩写。供应链管理是指协调和管…