Chainlit集成Langchain并使用通义千问实现和数据库交互的网页对话应用增强扩展(text2sql)

news2024/11/15 7:12:27

前言

我在上一篇文章中《Chainlit集成Langchain并使用通义千问实现和数据库交互的网页对话应用(text2sql)》 利用langchaincreate_sql_agent 创建一个数据库代理智能体,但是实测中发现,使用 create_sql_agent 在对话中,响应速度太慢了,数据的表越多,对话响应就越慢,这次本篇文章langchain中和数据库对话交互的另两种方式,SQLDatabaseChaincreate_sql_query_chain

SQLDatabaseChain

使用LangChain中的SQLDatabaseChain需要安装langchain_experimental,安装依赖命令如下:

pip install langchain
pip install langchain_experimental

SQLDatabaseChain和数据库的交互响应速度 处于 create_sql_agent create_sql_query_chain中间,其中create_sql_agent 智能体在交互过程中和AI做了多次交互,大致流程如下:先用AI判断问题和数据中表的相关性,查看相关表的设计表结构,利用AI生成sql查询语句,利用AI对生成的sql查询语句进行检查,利用AI对sql命令查询出来结构做最终回复。过程比较多,导致响应很慢,但是相对于其他两种方式来说,更智能,更严谨。SQLDatabaseChain既保持了一定智能性又提升了回复的速度。下面我用chainilt作为一个网页对话的UI界面,利用SQLDatabaseChain实现一个和数据库对话的网页应用示例如下:

本次使用postgres数据库进行对话

在项目根目录下,创建一个app.py文件,代码如下:

import os
import time
from io import BytesIO

import chainlit as cl
import dashscope
from langchain_community.llms import Tongyi
from langchain_community.utilities import SQLDatabase
from langchain_experimental.sql import SQLDatabaseChain


@cl.on_chat_start
async def on_chat_start():
    db = SQLDatabase.from_uri("postgresql+psycopg2://username:password@ip:port/dbname")
    llm = Tongyi(model='qwen-plus', verbose=True)
    db_chain = SQLDatabaseChain.from_llm(llm, db)
    cl.user_session.set("db_chain", db_chain)


@cl.on_message
async def on_message(message: cl.Message):
    start_time = time.time()
    db_chain = cl.user_session.get("db_chain")
    result = db_chain.invoke({"query": message.content})
    print(f"代码执行时间: {time.time() - start_time} 秒")
    await cl.Message(content=result['result']).send()
  • 修改代码中的数据库连接信息为你自己的
  • env文件中配置dashscopekey ,不知道的话,看我之前的文章
  • 实测中把qwen-plus改为qwen-max 或者其他更智能的AI,回答数据的准确度更高

create_sql_query_chain

create_sql_query_chainlangchain中和数据库查询最快的方式,他只是负责根据用户问题,生成查询sql查询语句一个功能。不太智能,但是足够灵活,用户可以自定义其他判断和最终回复的逻辑。下面我用create_sql_query_chain结合AI回复实现了一个简单数据库对话网页应用,速度是目前方式中最快的。

在项目根目录下创建app.py文件,代码如下:

import os
import time
from io import BytesIO

import chainlit as cl
import dashscope
from langchain.chains.sql_database.query import create_sql_query_chain
from langchain_community.llms import Tongyi
from langchain_community.utilities import SQLDatabase
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import PromptTemplate

db = SQLDatabase.from_uri("postgresql+psycopg2://username:password@ip:port/dbname")
llm = Tongyi(model='qwen-plus', verbose=True)


@cl.cache
def extract_sql_query(text):
    # 查找 'SQLQuery:' 的位置
    start_index = text.find('SQLQuery:')
    # 如果找到了 'SQLQuery:',则从其后的位置开始截取字符串
    if start_index != -1:
        # 'SQLQuery:' 后面的第一个字符的位置
        start_of_query = start_index + len('SQLQuery:') + 1
        # 返回 'SQLQuery:' 后面的字符串
        return text[start_of_query:].strip()
    else:
        # 如果没有找到 'SQLQuery:',则返回空字符串
        return text


@cl.step(type="tool", name="数据库查询")
async def db_query(message: cl.Message):
    db_chain = cl.user_session.get("db_chain")
    result = ""
    async for chunk in db_chain.astream({"question": message.content}):
        result = result.join(chunk)
    print("db_chain:" + result)
    sql = None
    if 'SELECT' in result:
        sql = extract_sql_query(result)
        print("自然语言转SQL:" + sql)
        res = db.run(sql)
        print("查询结果:", res)
        return sql, res
    if not sql:
        await cl.Message(content=result).send()
        return None, None


@cl.on_chat_start
async def on_chat_start():
    answer_prompt = PromptTemplate.from_template(
        """Given the following user question, corresponding SQL query, and SQL result, answer the user question. 
        用中文回答最终答案
        Question: {question}
        SQL Query: {query}
        SQL Result: {result}
        Answer: """
    )
    answer_chain = answer_prompt | llm | StrOutputParser()
    cl.user_session.set("answer_chain", answer_chain)
    db_chain = create_sql_query_chain(llm=llm, db=db)
    cl.user_session.set("db_chain", db_chain)


@cl.on_message
async def on_message(message: cl.Message):
    start_time = time.time()
    runnable = cl.user_session.get("answer_chain")
    msg = cl.Message(content="")
    sql, res = await db_query(message)
    if res:
        async for chunk in runnable.astream({"question": message.content, "query": sql, "result": res}):
            await msg.stream_token(chunk)
        print(f"代码执行时间: {time.time() - start_time} 秒")
        await msg.update()

  • 修改代码中的配置为你自己的数据库连接信息
  • 代码中的AI模型使用的是通义千问的qwen-plus
  • 大致原理使用create_sql_query_chain 根据用户问题生成查询sql,对返回的结构进行提取,获得最终sql,使用db.run方法执行最终sql。将sql执行结果sql查询语句、和用户问题,发给AI做最终回答。
  • 这种方式的弊端,当用户提问的问题和数据库无关时,报错的概率更大,需要进一步处理。对于create_sql_query_chain生成sql命令,没有做进一步校验,默认他是正确的,虽然节省的时间,也提升了报错的概率
  • db = SQLDatabase.from_uri("sqlite:///demo.db") 中的demo.db文件是上面sqlite_data.py文件执行后生成的
  • llm = Tongyi(model='qwen-plus', verbose=True)verbose 意思是是否打印详细输出
  • 在底层,LangChain 使用 SQLAlchemy 连接到 SQL 数据库。因此,SQLDatabaseChain 可以与 SQLAlchemy 支持的任何 SQL 方言一起使用,例如 MS SQL、MySQL、MariaDB、PostgreSQL、Oracle SQL、DatabricksSQLite。有关连接到数据库的要求的更多信息,请参阅 SQLAlchemy 文档。

连接mysql代码示例:

# 连接 MySQL 数据库
db_user = "root"
db_password = "12345678"
db_host = "IP"
db_port = "3306"
db_name = "demo"
db = SQLDatabase.from_uri(f"mysql+pymysql://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}")

运行应用程序

要启动 Chainlit 应用程序,请打开终端并导航到包含的目录app.py。然后运行以下命令:

 chainlit run app.py -w   
  • -w标志告知 Chainlit 启用自动重新加载,因此您无需在每次更改应用程序时重新启动服务器。您的聊天机器人 UI 现在应该可以通过http://localhost:8000访问。
  • 自定义端口可以追加--port 80

启动后界面如下:

在这里插入图片描述
在这里插入图片描述

  • 目前存在问题没办法流式输出,因为流公式返回的结果是ai执行sql的过程,最终返回的结果文本是流式返回的最后一段。
  • 执行时间有点长,提出问题后,一般5秒左右,才返回。
  • 目前支持sql查询相关的操作,不支持数据库新增、修改、删除的操作

相关文章推荐

《Chainlit快速实现AI对话应用的界面定制化教程》
《Chainlit接入FastGpt接口快速实现自定义用户聊天界面》
《使用 Xinference 部署本地模型》
《Fastgpt接入Whisper本地模型实现语音输入》
《Fastgpt部署和接入使用重排模型bge-reranker》
《Fastgpt部署接入 M3E和chatglm2-m3e文本向量模型》
《Fastgpt 无法启动或启动后无法正常使用的讨论(启动失败、用户未注册等问题这里)》
《vllm推理服务兼容openai服务API》
《vLLM模型推理引擎参数大全》
《解决vllm推理框架内在开启多显卡时报错问题》
《Ollama 在本地快速部署大型语言模型,可进行定制并创建属于您自己的模型》

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

yolo学习 (一) 安装yolov8及训练

随便搞个python环境,直接装或者anaconda都行,python版本最低3.8以上 一、安装yolov8 (cpu版本) pip install ultralytics yolov8安装版本比较省事,不过这里默认装的是CPU版本 import torch print(torch.__version_…

基于stm32单片机使用 RT-Thread 系统的 ADC 外设

一、ADC 介绍 来源:RT-Thread 文档中心   ADC(Analog-to-Digital Converter) 指模数转换器。是指将连续变化的模拟信号转换为离散的数字信号的器件。真实世界的模拟信号,例如温度、压力、声音或者图像等,需要转换成更容易储存、处理和发射…

手机玩机常识-------谷歌系列机型解锁bl详细步骤 其他机型可以借鉴参考

谷歌公司自从在2005年收购了Android公司之后一直在开发一款手机操作系统,谷歌的这一举动正是为了推出自己的手机而作准备.目前。谷歌Pixel 系列为很多玩家所持有。其独特的安装原生系统为很多粉丝所青睐。今天我们来看看谷歌Pixel 系列机型解锁bl的相关常识 谷歌Pi…

CTF(misc)

1、隐写3 题目链接 观察这个图片感觉图片高度有问题,010editor打开,查看CRC python脚本求宽高 import os import binascii import struct crcbp open("dabai.png","rb").read() for i in range(1024):for j in range(1024):data …

操作系统 ---- 调度器、闲逛进程

一、调度器/调度程序(scheduler) 2、③由调度程序引起,调度程序决定: 让谁运行?――调度算法运行多长时间?―一时间片大小 调度时机――什么事件会触发“调度程序”? 创建新进程进程退出运行进程阻塞I/O中断发生(可能唤醒某…

大受欢迎的游戏却又意外被作者下架的《Flappy Bird》将重返iPhone

据"Flappy Bird 基金会"官网称,标志性的侧卷轴滚动游戏《Flappy Bird》将很快回归 iPhone。《Flappy Bird》于 2013 年发布,很快就获得了数千万次下载。然而,这款游戏在2014 年突然从 App Store 下架,原因是其越南开发者…

SD卡挂载FatFs文件系统

一、简介 实验目的:SD卡挂载FATFS文件系统,并生成.txt文件 MCU:ST32F103ZET6 SD卡:16G;SPI读写模式; 引脚定义:VCC:5V GND:GND MISO:PA6 …

常用环境部署(十八)——CentOS7搭建DNS服务器

一、安装Bind服务器软件并启动 1、安装Bind服务 yum -y install bind bind* 2、 启动服务 systemctl start named 3、开机自启动 systemctl enable named 二、查看named进程是否正常启动 1、检查进程 ps -eaf|grep named 2、检查监听端口 ss -nult|grep :53 三、关闭…

EmguCV学习笔记 C# 11.6 图像分割

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。 教程VB.net版本请访问…

宠物毛发对人体有什么危害?宠物空气净化器小米、希喂、352对比实测

作为一个呼吸科医生,我自己也养猫。软软糯糯的小猫咪谁不爱啊,在养猫的过程中除了欢乐外,也面临着一系列的麻烦,比如要忍耐猫猫拉粑粑臭、掉毛、容易带来细菌等等的问题。然而我发现,现在许多年轻人光顾着养猫快乐了&a…

Vue生命周期钩子在UniApp中的应用

1、Vue 3 生命周期钩子介绍 onMounted()//注册一个回调函数,在组件挂载完成后执行。onUpdated()//注册一个回调函数,在组件因为响应式状态变更而更新其 DOM 树之后调用。onUnmounted()//注册一个回调函数,在组件实例被卸载之后调用。onBefor…

西部数据发布的一款西数硬盘检测修复工具-支持WD-L/WD-ROYL板,能进行硬盘软复位,可识别硬盘查看或清除-供大家学习参考

使用方法: 1、运行WDR5.3正式版.exe 2、导入WDR5.3.key 3、PORTTALK.SYS放入系统目录 第一步:注册完打开软件 第二步:设置维修盘端口:点击设置--》端口--》会出现主要端口 ,次要端口 ,定制端口 USB。一般如果不是USB移动硬盘都选择“定制端口”

WebGL入门(019):WebGLSync 简介、使用方法、示例代码

还是大剑师兰特:曾是美国某知名大学计算机专业研究生,现为航空航海领域高级前端工程师;CSDN知名博主,GIS领域优质创作者,深耕openlayers、leaflet、mapbox、cesium,canvas,webgl,ech…

轨迹预测(2)CVPR-24:基于社交互动角度表示的行人轨迹预测(代码已开源)

一.写在前面 今天要分享的是CVPR 2024上的一篇精彩的行人轨迹预测论文。这篇文章的灵感来源于海洋动物,它们通过回声定位来感知水下同伴的位置。研究者们构建了一种名为 SocialCircle 的全新基于角度的社交互动表示模型,用于动态反映行人相对…

MATLAB | R2024b更新了哪些好玩的东西?

Hey, 又到了一年两度的MATLAB更新时刻,MATLAB R2024b正式版发布啦!,直接来看看有哪些我认为比较有意思的更新吧! 1 小提琴图 天塌了,我这两天才写了个半小提琴图咋画,MATLAB 官方就出了小提琴图绘制方法。 小提琴图…

从边缘到云端,合宙DTURTU打造无缝物联网解决方案

随着物联网(IoT)技术的飞速发展,万物互联的时代已经到来, 如何高效、稳定地连接边缘设备与云端平台,实现数据的实时采集、传输与处理,成为了推动物联网应用落地的关键。 DTU(数据传输单元&…

Python面试宝典第48题:找丑数

题目 我们把只包含质因子2、3和5的数称作丑数(Ugly Number)。比如:6、8都是丑数,但14不是,因为它包含质因子7。习惯上,我们把1当做是第一个丑数。求按从小到大的顺序的第n个丑数。 示例 1: 输入…

单链表的查找与长度计算

注&#xff1a;本文只探讨"带头结点"的情况(查找思路类似循环找到第i-1 个结点的代码) 一.按位查找&#xff1a; 1.代码演示&#xff1a; 版本一&#xff1a; #include<stdio.h> #include<stdlib.h> ​ ​ //定义单链表结点类型 typedef struct LNo…

C语言 | Leetcode C语言题解之第401题二进制手表

题目&#xff1a; 题解&#xff1a; char** readBinaryWatch(int turnedOn, int* returnSize) {char** ans malloc(sizeof(char*) * 12 * 60);*returnSize 0;for (int i 0; i < 1024; i) {int h i >> 6, m i & 63; // 用位运算取出高 4 位和低 6 位if (h &…

针对网上nbcio-boot代码审计的actuator方法的未授权访问漏洞和ScriptEngine的注入漏洞的补救

针对网上下面文章的漏洞补救 奇安信攻防社区-代码审计之nbcio-boot从信息泄露到Getshell 一、未授权分析 在ShiroConfig中放开了actuator方法的未授权访问 org/jeecg/config/shiro/ShiroConfig.java:156 上面问题,先注释掉上面的未授权访问,实际就是代码注释掉 二、、RCE…