DB_GPT源码梳理

引言

随着数据量的不断增长和数据分析的需求日益增多,将自然语言文本转化为结构化查询语言(SQL)的能力变得越来越重要。Text to SQL方案是一种将自然语言查询转化为SQL查询的技术,它可以帮助用户更轻松、更高效地从文本中提取所需的信息。

博主近期在研究text2sql的项目应用,从大模型和传统的深度学习模型两方面入手,未来会持续发布相关文章,本文将介绍Text to SQL的一种基于大模型的方案:DB-GPT。安装与部署可以参考博主这篇文章:部署DB-GPT

DB-GPT项目简介

DB-GPT项目(项目地址)是在github上发布的,为解决使用大模型和数据库交互的过程中,私密数据以及环境是否能掌握自己的手里,完全自主可控的问题。项目支持为所有以数据库为基础的场景,构建一套完整的私有大模型解决方案。 此方案因为支持本地部署,所以不仅仅可以应用于独立私有环境,而且还可以根据业务模块独立部署隔离,让大模型的能力绝对私有、安全、可控。

概要

对于DBGPT的源码梳理,主要是针对于与数据库对话的部分源码分析

1后端

主要梳理提示词,以及用户的输入和大模型的响应是怎么被处理

1.1整体流程分析

首先我们选择聊天场景
在这里插入图片描述
根据前端抓包,获得的地址中可以看到http://localhost:5670/chat/?scene=chat_with_db_execute&id=8c88bf60-1f17-11ef-80b2-7413eaf68a78,scene=chat_with_db_execute这个参数,我们对应选择的聊天场景应该为ChatWithDbExecute
在这里插入图片描述

在这种聊天模式下,选定提示词模板
self.prompt_template: AppScenePromptTemplateAdapter = (
    CFG.prompt_template_registry.get_prompt_template(
                self.chat_mode.value(),
                language=CFG.LANGUAGE,
                model_name=self.llm_model,
                proxyllm_backend=CFG.PROXYLLM_BACKEND,
            )
)
英文
_DEFAULT_TEMPLATE_EN = """
Please answer the user's question based on the database selected by the user and some of the available table structure definitions of the database.
Database name:
     {db_name}
Table structure definition:
     {table_info}

Constraint:
    1.Please understand the user's intention based on the user's question, and use the given table structure definition to create a grammatically correct {dialect} sql. If sql is not required, answer the user's question directly.. 
    2.Always limit the query to a maximum of {top_k} results unless the user specifies in the question the specific number of rows of data he wishes to obtain.
    3.You can only use the tables provided in the table structure information to generate sql. If you cannot generate sql based on the provided table structure, please say: "The table structure information provided is not enough to generate sql queries." It is prohibited to fabricate information at will.
    4.Please be careful not to mistake the relationship between tables and columns when generating SQL.
    5.Please check the correctness of the SQL and ensure that the query performance is optimized under correct conditions.
    6.put the type name into the name parameter value that returns the required format. If you cannot find the most suitable one, use 'Table' as the display method. , the available data display methods are as follows: {display_type}
    
User Question:
    {user_input}
Please think step by step and respond according to the following JSON format:
    {response}
Ensure the response is correct json and can be parsed by Python json.loads.
"""

中文
_DEFAULT_TEMPLATE_ZH = """
请根据用户选择的数据库和该库的部分可用表结构定义来回答用户问题.
数据库名:
    {db_name}
表结构定义:
    {table_info}

约束:
    1. 请根据用户问题理解用户意图,使用给出表结构定义创建一个语法正确的 {dialect} sql,如果不需要sql,则直接回答用户问题。
    2. 除非用户在问题中指定了他希望获得的具体数据行数,否则始终将查询限制为最多 {top_k} 个结果。
    3. 只能使用表结构信息中提供的表来生成 sql,如果无法根据提供的表结构中生成 sql ,请说:“提供的表结构信息不足以生成 sql 查询。” 禁止随意捏造信息。
    4. 请注意生成SQL时不要弄错表和列的关系
    5. 请检查SQL的正确性,并保证正确的情况下优化查询性能
    6.类型名称放入返回要求格式的name参数值中,如果找不到最合适的则使用'Table'作为展示方式,可用数据展示方式如下: {display_type}
用户问题:
    {user_input}
请一步步思考并按照以下JSON格式回复:
      {response}
确保返回正确的json并且可以被Python json.loads方法解析.

"""

效果最好的是英文提问加英文模板----》中文提问中文模板-----》中英混杂

需要传入的参数

在这里插入图片描述

经过处理之后的参数

在这里插入图片描述

部分参数解释

对于模板中的{response}参数采用默认的回复格式

RESPONSE_FORMAT_SIMPLE = {
    "thoughts": "和用户解释我们应该如何解决这个问题",
    "sql": "要运行的sql语句查询",
    "display_type": "数据展示方式",
}

对于6.类型名称放入返回要求格式的name参数值中,如果找不到最合适的则使用’Table’作为展示方式,可用数据展示方式如下: {display_type}
display_type可选的类型如

response_line_chart:used to display comparative trend analysis data
    
response_pie_chart:suitable for scenarios such as proportion and distribution statistics
    
response_table:suitable for display with many display columns or non-numeric columns
    
response_scatter_plot:Suitable for exploring relationships between variables, detecting outliers, etc.
    
response_bubble_chart:Suitable for relationships between multiple variables, highlighting outliers or special situations, etc.
    
response_donut_chart:Suitable for hierarchical structure representation, category proportion display and highlighting key categories, etc.
    
response_area_chart:Suitable for visualization of time series data, comparison of multiple groups of data, analysis of data change trends, etc.
    
response_heatmap:Suitable for visual analysis of time series data, large-scale data sets, distribution of classified data, etc.

table_info就是对应我们所选择的数据库dbgpt_test下表的结构
在这里插入图片描述
当传入这些参数之后我们可以看到模板发生的变化

role='system' 
content='\n请根据用户选择的数据库和该库的部分可用表结构定义来回答用户问题.

数据库名:    
    dbgpt_test
表结构定义:    [(\'riskcontroller(measure_type,risk_level,harm,owner_id,order_number,safe_measure,id,procedures)\',), (\'security(id,owner_id,execute_content,measure_type,execute_situation,order_number)\',), (\'transaction_order(id,order_no,product_name,product_category,amount,pay_status,user_id,user_name,create_time,update_time)\',), (\'user(id,name,email,mobile,gender,birth,country,city,create_time,update_time)\',)]
约束:
            1. 请根据用户问题理解用户意图,使用给出表结构定义创建一个语法正确的 mysql sql,如果不需要sql,则直接回答用户问题。\n    
            2. 除非用户在问题中指定了他希望获得的具体数据行数,否则始终将查询限制为最多 50 个结果。\n   
            3. 只能使用表结构信息中提供的表来生成 sql,如果无法根据提供的表结构中生成 sql ,请说:“提供的表结构信息不足以生成 sql 查询。” 禁止随意捏造信息。\n    
            4. 请注意生成SQL时不要弄错表和列的关系\n    
            5. 请检查SQL的正确性,并保证正确的情况下优化查询性能\n    
            6.将类型名称放入返回要求格式的name参数值中,如果找不到最合适的则使用\'Table\'作为展示方式,可用数据展示方式如下: 
            response_line_chart:used to display comparative trend analysis data
            response_pie_chart:suitable for scenarios such as proportion and distribution statistics
            response_table:suitable for display with many display columns or non-numeric columns
            response_scatter_plot:Suitable for exploring relationships between variables, detecting outliers, etc.
            response_bubble_chart:Suitable for relationships between multiple variables, highlighting outliers or special situations, etc.
            response_donut_chart:Suitable for hierarchical structure representation, category proportion display and highlighting key categories, etc.
            response_area_chart:Suitable for visualization of time series data, comparison of multiple groups of data, analysis of data change trends, etc.
            response_heatmap:Suitable for visual analysis of time series data, large-scale data sets, distribution of classified data, etc.
用户问题:
            查询每个用户的订单数量,并用饼图来进行表示
请一步步思考并按照以下JSON格式回复:
            "{\\n    \\"thoughts\\": \\"和用户解释我们应该如何解决这个问题\\",\\n    \\"sql\\": \\"要运行的sql语句查询\\",\\n    \\"display_type\\": \\"数据展示方式\\"\\n}"
            
确保返回正确的json并且可以被Python json.loads方法解析.\n\n' round_index=0
传入模型之后,得到模型的原始输出

在这里插入图片描述
得到输出结果如下


'{
    "thoughts": "我们可以通过在transaction_order表中按照user_id进行分组,并计算每个用户的订单数量来解决这个问题。",
    "sql": "SELECT user_id, COUNT(*) AS order_count FROM transaction_order GROUP BY user_id",
    "display_type": "response_pie_chart"
}'

最后转换为一个用户可以理解和使用的格式,通常是前端显示所需的格式

view_message = await blocking_func_to_async(
            self._executor,
            self.prompt_template.output_parser.parse_view_response,
            speak_to_user,
            result,
            prompt_define_response,
)

通过输出,得知结构如下

我们可以通过在transaction_order表中按照user_id进行分组,并计算每个用户的订单数量来解决这个问题。
<chart-view content="{&quot;type&quot;: &quot;response_pie_chart&quot;, &quot;sql&quot;: &quot;SELECT user_id, COUNT(*) AS order_count FROM transaction_order GROUP BY user_id&quot;, &quot;data&quot;: [{&quot;user_id&quot;: 111, &quot;order_count&quot;: 5}, {&quot;user_id&quot;: 112, &quot;order_count&quot;: 13}, {&quot;user_id&quot;: 113, &quot;order_count&quot;: 7}, {&quot;user_id&quot;: 114, &quot;order_count&quot;: 5}, {&quot;user_id&quot;: 121, &quot;order_count&quot;: 9}, {&quot;user_id&quot;: 122, &quot;order_count&quot;: 11}, {&quot;user_id&quot;: 123, &quot;order_count&quot;: 16}, {&quot;user_id&quot;: 124, &quot;order_count&quot;: 10}, {&quot;user_id&quot;: 125, &quot;order_count&quot;: 8}, {&quot;user_id&quot;: 211, &quot;order_count&quot;: 10}, {&quot;user_id&quot;: 212, &quot;order_count&quot;: 7}, {&quot;user_id&quot;: 213, &quot;order_count&quot;: 8}, {&quot;user_id&quot;: 214, &quot;order_count&quot;: 10}, {&quot;user_id&quot;: 221, &quot;order_count&quot;: 6}, {&quot;user_id&quot;: 222, &quot;order_count&quot;: 6}, {&quot;user_id&quot;: 223, &quot;order_count&quot;: 7}, {&quot;user_id&quot;: 311, &quot;order_count&quot;: 5}, {&quot;user_id&quot;: 312, &quot;order_count&quot;: 7}, {&quot;user_id&quot;: 313, &quot;order_count&quot;: 10}, {&quot;user_id&quot;: 314, &quot;order_count&quot;: 3}, {&quot;user_id&quot;: 315, &quot;order_count&quot;: 4}, {&quot;user_id&quot;: 321, &quot;order_count&quot;: 11}, {&quot;user_id&quot;: 322, &quot;order_count&quot;: 8}, {&quot;user_id&quot;: 323, &quot;order_count&quot;: 5}, {&quot;user_id&quot;: 324, &quot;order_count&quot;: 9}]}" />
如果在我们的问题中不指定要用什么形式进行展示就选择默认形式
"{
    "thoughts": "我们可以通过查询'user'表中的记录数量来获取用户数量。",
    "sql": "SELECT COUNT(*) AS user_count FROM user",
    "display_type": "response_table"
}"

模型输出如下

"我们可以通过查询'user'表中的记录数量来获取用户数量。
<chart-view content="{&quot;type&quot;: &quot;response_table&quot;, &quot;sql&quot;: &quot;SELECT COUNT(*) AS user_count FROM user&quot;, &quot;data&quot;: [{&quot;user_count&quot;: 25}]}" />"

1.2sql执行过程分析

查询模型原始输出

根据追踪代码,可以得知,ModelOutput.text就是模型的原始输出

@dataclass
@PublicAPI(stability="beta")
class ModelOutput:
    """A class to represent the output of a LLM.""" ""

    text: str
    """The generated text."""

在这里插入图片描述

RESPONSE_FORMAT_SIMPLE = {
    "thoughts": "和用户解释我们应该如何解决这个问题",
    "sql": "要运行的sql语句查询",
    "display_type": "数据展示方式",
}

model_output.text = "{
    "thoughts": "我们应该查询'user'表中的用户数量。",
    "sql": "SELECT COUNT(*) AS user_count FROM user",
    "display_type": "response_table"
}"
提取SQL语句

● 从解析出的AI回复中提取SQL语句。
● “sql”: “SELECT COUNT(*) AS user_count FROM user”,
● 在代码中找到执行sql的地方
在这里插入图片描述
路径:D:\Code\Code_pycharm\DB_gpt\DB-GPT\dbgpt\app\scene\base_chat.py 下的380行
调用之后执行D:\Code\Code_pycharm\DB_gpt\DB-GPT\dbgpt\app\scene\chat_db\auto_execute\chat.py下的do_action()方法

执行SQL语句

执行sql的核心代码

核心sql执行代码
    def run_to_df(self, command: str, fetch: str = "all"):
        """Execute sql command and return result as dataframe."""
        import pandas as pd

        # Pandas has too much dependence and the import time is too long
        # TODO: Remove the dependency on pandas
        result_lst = self.run(command, fetch)
        colunms = result_lst[0]
        values = result_lst[1:]
        result_final = pd.DataFrame(values, columns=colunms)
        return result_final

执行完sql语句之后结果封装成DataFrame类型
在这里插入图片描述

解析视图响应
# 定义 parse_view_response 方法,用于解析视图响应
    def parse_view_response(self, speak, data, prompt_response) -> str:
        # 初始化一个空字典 param 和一个 XML 元素 api_call_element,类型为 "chart-view"# 
        param = {}
        api_call_element = ET.Element("chart-view")
        err_msg = None
        success = False
        try:
            if not prompt_response.sql or len(prompt_response.sql) <= 0:
                raise AppActionException("Can not find sql in response", speak)
			#调用 data 函数执行 SQL 语句,获取结果数据框 df
            # ['user_count']  [0          25]
            df = data(prompt_response.sql)
            param["type"] = prompt_response.display
            param["sql"] = prompt_response.sql
            param["data"] = json.loads(
                df.to_json(orient="records", date_format="iso", date_unit="s")
            )
            #param 字典转换为 JSON 字符串
            view_json_str = json.dumps(param, default=serialize, ensure_ascii=False)
            success = True
        except Exception as e:
            logger.error("parse_view_response error!" + str(e))
            err_param = {
                "sql": f"{prompt_response.sql}",
                "type": "response_table",
                "data": [],
            }
            # err_param["err_msg"] = str(e)
            err_msg = str(e)
            view_json_str = json.dumps(err_param, default=serialize, ensure_ascii=False)

        # 这里将 JSON 字符串设置为 XML 元素的内容
        api_call_element.set("content", view_json_str)
        # 将XML 元素对象按照utf-8的编码方式,转化为字符串
        result = ET.tostring(api_call_element, encoding="utf-8")
        if not success:
            view_content = (
                f'{speak} \\n <span style="color:red">ERROR!</span>'
                f"{err_msg} \n {result.decode('utf-8')}"
            )
            raise AppActionException("Generate view content failed", view_content)
        else:
            return speak + "\n" + result.decode("utf-8")

然后就能看到之前呈现的效果

就是这个效果
     <chart-view content="{&quot;type&quot;: &quot;response_table&quot;, &quot;sql&quot;: &quot;SELECT COUNT(*) AS user_count FROM user&quot;, &quot;data&quot;: [{&quot;user_count&quot;: 25}]}" />'

2前端

前端主要梳理请求参数的构造和响应的处理,尤其是图表展示(折线图,饼图,柱状图等等如何展示)(如果有需要的话,评论区留言)

  • 30
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在transformers模块中,没有名为modeling_gpt2的属性。 我们知道,transformers库是一个用于自然语言处理(NLP)任务的常用工具包,它包含了各种预训练模型和训练模型的工具函数。 在这个错误中,出现了"module transformers has no attribute modeling_gpt2"的错误提示。这意味着我们在transformers模块中尝试访问modeling_gpt2属性,但是并没有找到这个属性。 可能的原因是我们导入了transformers模块,但是没有正确引入所需的模型或模型类。 对于GPT-2模型,我们应该使用"from transformers import GPT2Model"来导入GPT-2模型类,而不是modeling_gpt2属性。 请确保您在代码中正确导入了所需的模型类或属性,并使用适当的名称进行访问。如果您正在尝试访问的模型或属性不存在,您需要检查transformers库的版本和更新情况,或者查看文档以了解如何正确使用该库。 ### 回答2: 在transformers模块中没有名为modeling_gpt2的属性。这是因为最新版本的transformers库已经重新组织了其内部结构和命名规则。以前版本的transformers库中,GPT-2模型相关的代码被命名为modeling_gpt2,但在最新版本中已经进行了重构和重命名。 现在,GPT-2模型相关的代码在transformers模块中被命名为GPT2Model。如果您想使用GPT-2模型,可以通过以下代码来实例化一个GPT2Model对象: ```python from transformers import GPT2Model model = GPT2Model.from_pretrained('gpt2') ``` 注意,为了使用GPT-2模型,您需要先安装transformers库,并且通过`pip install transformers`命令来安装它的相应版本。 总结一下,"module transformers has no attribute modeling_gpt2"的错误信息是因为您正在引用一个过时的命名。在最新版本的transformers库中,GPT-2模型的代码被命名为GPT2Model,而不再是modeling_gpt2。 ### 回答3: 在transformers模块中找不到属性modeling_gpt2的原因可能有以下几种情况: 1. 版本不匹配:可能您使用的transformers版本过低,缺少了modeling_gpt2这个属性。建议您升级transformers到最新版本,并且检查是否安装了正确的版本。 2. 模型名称错误:modeling_gpt2是指GPT2模型的具体实现,因此如果您在代码中使用模型时,错误地使用了别的模型名称,就会报错找不到modeling_gpt2属性。请确保在代码中正确地引用了GPT2模型。 3. 错误导入:可能您导入transformers模块时出现错误,导致没有正确地加载modeling_gpt2属性。请检查您导入transformers的代码,确保正确地导入了模块。 如果以上三种情况都检查过了,仍然找不到modeling_gpt2属性,建议查阅transformers库的官方文档,了解该属性是否在您使用的版本中可用。另外,您还可以尝试搜索相关的解决方案或者咨询transformers社区来获取更多帮助。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值