fastapi 调用ollama之下的sqlcoder模式进行对话操作数据库

from fastapi import FastAPI, HTTPException, Request
from pydantic import BaseModel
import ollama
import mysql.connector
from mysql.connector.cursor import MySQLCursor
import jsonapp = FastAPI()# 数据库连接配置
DB_CONFIG = {"database": "web",        # 您的数据库名,用于存储业务数据"user": "root",          # 数据库用户名,需要有读写权限"password": "XXXXXX",    # 数据库密码,建议使用强密码"host": "127.0.0.1",    # 数据库主机地址,本地开发环境使用localhost"port": "3306"          # MySQL 默认端口,可根据实际配置修改
}# 数据库连接函数
def get_db_connection():try:conn = mysql.connector.connect(**DB_CONFIG)return connexcept Exception as e:raise HTTPException(status_code=500, detail=f"数据库连接失败: {str(e)}")class SQLRequest(BaseModel):question: strdef get_table_relationships():"""动态获取表之间的关联关系"""conn = get_db_connection()cur = conn.cursor()try:# 获取当前数据库名cur.execute("SELECT DATABASE()")db_name = cur.fetchone()[0]# 获取外键关系cur.execute("""SELECT TABLE_NAME,COLUMN_NAME,REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAMEFROM INFORMATION_SCHEMA.KEY_COLUMN_USAGEWHERE TABLE_SCHEMA = %sAND REFERENCED_TABLE_NAME IS NOT NULLORDER BY TABLE_NAME, COLUMN_NAME""", (db_name,))relationships = []for row in rows:table_name, column_name, ref_table, ref_column = rowrelationships.append(f"-- {table_name}.{column_name} can be joined with {ref_table}.{ref_column}")return "\n".join(relationships) if relationships else "-- No foreign key relationships found"finally:cur.close()conn.close()def get_database_schema():"""获取MySQL数据库表结构,以CREATE TABLE格式返回"""conn = get_db_connection()cur = conn.cursor()try:# 获取当前数据库名cur.execute("SELECT DATABASE()")db_name = cur.fetchone()[0]# 获取所有表的结构信息cur.execute("""SELECT t.TABLE_NAME,c.COLUMN_NAME,c.COLUMN_TYPE,c.IS_NULLABLE,c.COLUMN_KEY,c.COLUMN_COMMENTFROM INFORMATION_SCHEMA.TABLES tJOIN INFORMATION_SCHEMA.COLUMNS c ON t.TABLE_NAME = c.TABLE_NAMEWHERE t.TABLE_SCHEMA = %sAND t.TABLE_TYPE = 'BASE TABLE'ORDER BY t.TABLE_NAME, c.ORDINAL_POSITION""", (db_name,))rows = cur.fetchall()schema = []current_table = Nonetable_columns = []for row in rows:table_name, column_name, column_type, nullable, key, comment = rowif current_table != table_name:if current_table is not None:schema.append(f"CREATE TABLE {current_table} (\n" + ",\n".join(table_columns) + "\n);\n")current_table = table_nametable_columns = []# 构建列定义column_def = f"  {column_name} {column_type.upper()}"if key == "PRI":column_def += " PRIMARY KEY"elif nullable == "NO":column_def += " NOT NULL"if comment:column_def += f" -- {comment}"table_columns.append(column_def)# 添加最后一个表if current_table is not None:schema.append(f"CREATE TABLE {current_table} (\n" + ",\n".join(table_columns) + "\n);\n")return "\n".join(schema)finally:cur.close()conn.close()def get_chinese_table_mapping():"""动态生成表名的中文映射"""conn = get_db_connection()cur = conn.cursor()try:# 获取所有表的注释信息cur.execute("""SELECT t.TABLE_NAME,t.TABLE_COMMENTFROM information_schema.TABLES tWHERE t.TABLE_SCHEMA = DATABASE()ORDER BY t.TABLE_NAME""")mappings = []for table_name, table_comment in cur.fetchall():# 生成表的中文名称chinese_name = table_nameif table_name.startswith('web_'):chinese_name = table_name.replace('web_', '').replace('_', '')if table_comment:chinese_name = table_comment.split('--')[0].strip()# 如果中文名称以"表"结尾,则去掉"表"if chinese_name.endswith('表'):chinese_name = chinese_name[:-1]mappings.append(f'           - "{chinese_name}" -> {table_name} table')return "\n".join(mappings)finally:cur.close()conn.close()@app.post("/query")
async def query_database(request: Request):try:# 获取请求体数据并确保正确处理中文body = await request.body()try:request_data = json.loads(body.decode('utf-8'))except UnicodeDecodeError:request_data = json.loads(body.decode('gbk'))question = request_data.get('question')print(f"收到问题: {question}")  # 调试日志if not question:raise HTTPException(status_code=400, detail="缺少 question 参数")# 获取数据库结构db_schema = get_database_schema()#print(f"数据库结构: {db_schema}")  # 调试日志# 获取中文映射并打印chinese_mapping = get_chinese_table_mapping()#print(f"表映射关系:\n{chinese_mapping}")  # 添加这行来打印映射# 修改 prompt 使用更严格的指导prompt = f"""### Instructions:Convert Chinese question to MySQL query. Follow these rules strictly:1. ONLY return a valid SELECT SQL query2. Use EXACT table names from the mapping below3. DO NOT use any table that's not in the mapping4. For Chinese terms, use these exact mappings:
{chinese_mapping}### Examples:Question: 所有装修记录SQL: SELECT * FROM web_decoration ORDER BY id;Question: 查询装修SQL: SELECT * FROM web_decoration ORDER BY id;### Database Schema:{db_schema}### Question:{question}### SQL Query:"""# 获取 SQL 查询response = ollama.chat(model='sqlcoder:latest', messages=[{'role': 'user', 'content': prompt}])sql_query = response['message']['content'].strip()print(f"生成的SQL: {sql_query}")  # 调试日志# 验证 SQL 查询if "装修" in question and "web_decoration" not in sql_query:sql_query = "SELECT * FROM web_decoration ORDER BY id"if not sql_query.upper().startswith('SELECT'):raise HTTPException(status_code=400, detail="无效的SQL查询格式")conn = get_db_connection()cur = conn.cursor(dictionary=True)try:cur.execute(sql_query)results = cur.fetchall()return {"sql_query": sql_query,"results": results}except mysql.connector.Error as e:raise HTTPException(status_code=400, detail=f"SQL 执行错误: {str(e)}")finally:cur.close()conn.close()except json.JSONDecodeError as e:raise HTTPException(status_code=400, detail=f"JSON 解析错误: {str(e)}")except Exception as e:raise HTTPException(status_code=500, detail=f"处理请求时生错误: {str(e)}")if __name__ == "__main__":import uvicornport = 8666print(f"Starting server on port {port}")uvicorn.run("main:app",host="0.0.0.0", port=port,reload=True)

我来为您解释这段代码的主要功能和结构:

主要功能

这是一个使用 FastAPI 框架开发的 API 服务,主要用于将中文问题转换为 SQL 查询语句并执行。

核心组件说明

  1. 数据库配置与连接
DB_CONFIG = {"database": "web","user": "root","password": "XXXXXX","host": "127.0.0.1","port": "3306"
}

提供了 MySQL 数据库的基本连接配置。

  1. 主要工具函数
  • get_table_relationships(): 获取数据库表之间的外键关系
  • get_database_schema(): 获取数据库表结构
  • get_chinese_table_mapping(): 生成表名的中文映射关系
  1. 核心 API 端点
@app.post("/query")

这个端点接收中文问题,主要处理流程:

  • 接收并解析用户的中文问题
  • 获取数据库结构和表映射
  • 使用 ollama 模型将中文转换为 SQL 查询
  • 执行 SQL 查询并返回结果
  1. 智能转换功能
    使用 ollamasqlcoder 模型将中文问题转换为 SQL 查询,包含:
  • 严格的表名映射
  • SQL 查询验证
  • 错误处理机制

特点

  1. 支持中文输入处理
  2. 自动获取数据库结构
  3. 动态生成中文表名映射
  4. 完善的错误处理机制
  5. 支持热重载的开发模式

使用示例

可以通过 POST 请求访问 /query 端点:

{"question": "查询所有装修记录"
}

服务会返回:

{"sql_query": "SELECT * FROM web_decoration ORDER BY id","results": [...]
}

安全特性

  1. 数据库连接错误处理
  2. SQL 注入防护
  3. 请求体编码自适应(支持 UTF-8 和 GBK)
  4. 查询结果的安全封装

查看效果:
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动化报表怎么写

自动化报表设计 标题 日期 筛选器 具体字段自由字段 迷你图 同环比 条件格式 步骤 填充数值 1、先筛选战区日期sumifs(纯数值-注册人数,纯数值-战区列,周报-战区单元格,纯数值-日期,周报-日期单元格) 需要注意⚠️纯数值里的单元格…

学习笔记022——Ubuntu 安装 MySQL8.0版本踩坑记录

目录 1、查看可安装 MySQL 版本 2、Ubuntu安装 MySQL8.0 3、MySQL8.0 区分大小写问题 4、MySQL8.0 设置sql_mode 5、MySQL8.0 改端口33060(个人遇到问题) 1、查看可安装 MySQL 版本 ## 列出可用的MySQL版本(列出所有可用的MySQL版本以…

优化装配,提升品质:虚拟装配在汽车制造中的关键作用

汽车是各种零部件的有机结合体,因此汽车的装配工艺水平和装配质量直接影响着汽车的质量与性能。在汽车装配过程中,经常会发生零部件间干涉或装配顺序不合理等现象,且许多零部件制造阶段产生的质量隐患要等到实际装配阶段才能显现出来&#xf…

Office-Tab-for-Mac Office 窗口标签化,Office 多文件标签化管理

Office Tab:让操作更高效,给微软 Office 添加多标签页功能 Office 可以说是大家装机必备的软件,无论学习还是工作都少不了。其中最强大、用的最多的,还是微软的 Microsoft Office。 遗憾的是,微软的 Office 不支持多…

【网络】Socket编程TCP/UDP序列化和反序列化理解应用层(C++实现)Json::Value

主页:醋溜马桶圈-CSDN博客 专栏:计算机网络原理_醋溜马桶圈的博客-CSDN博客 gitee:mnxcc (mnxcc) - Gitee.com 目录 1.基于Socket的UDP和TCP编程介绍 1.1 基本TCP客户—服务器程序设计基本框架 ​编辑1.2 基本UDP客户—服务器程序设计基本框…

架构师:使用 Atomix 实现分布式协调服务的技术指南

1、简述 Atomix 是一个强大的分布式协调框架,提供了分布式数据结构、协调工具和一致性协议,帮助开发者实现高可用、强一致性的分布式系统。它构建于 Raft 和 Paxos 等一致性协议之上,支持创建分布式锁、Leader 选举、分布式 Map、消息发布-订阅等功能,常用于微服务架构和分…

linux之调度管理(9)-SMP cpu hotplug

一、cpu热插拔介绍 在单核时代,操作系统只需要管理一个cpu,当系统有任务要执行时,所有任务在该cpu的就绪队列上排队,调度器根据调度算法选择一个最佳任务执行。当就绪队列上的所有任务都执行完成后,cpu就执行idle进程而…

[JavaWeb]微头条项目

完整笔记和项目代码: https://pan.baidu.com/s/1PZBO0mfpwDPic4Ezsk8orA?pwdwwp5 提取码: wwp5 JavaWeb-微头条项目开发 1 项目简介 1.1 业务介绍 微头条新闻发布和浏览平台,主要包含业务如下 用户功能 注册功能登录功能 头条新闻 新闻的分页浏览通过标题关键字搜…

hhdb数据库介绍(9-24)

计算节点参数说明 failoverAutoresetslave 参数说明&#xff1a; PropertyValue参数值failoverAutoresetslave是否可见是参数说明故障切换时&#xff0c;是否自动重置主从复制关系默认值falseReload是否生效否 参数设置&#xff1a; <property name"failoverAutor…

软件设计师 - 第3章 数据结构

概述 按照存储结构来分&#xff0c;数据结构可以分成如下四种&#xff1a; 线性结构&#xff1a;数据元素间呈现线性关系&#xff0c;有单一的前驱和后继表&#xff1a;可以看做是线性结构的推广&#xff0c;是多个线性结构的集合树&#xff1a;不同于线性结构&#xff0c;其元…

完整http服务器

目录 背景目标描述技术特点开发环境WWW客户端浏览发展史服务端http发展史http分层概览 背景 http协议被广泛使用&#xff0c;从移动端&#xff0c;pc浏览器&#xff0c;http无疑是打开互联网应用窗口的重要协议&#xff0c;http在网络应用层中的地位不可撼动&#xff0c;是能…

详细描述一下Elasticsearch搜索的过程?

大家好&#xff0c;我是锋哥。今天分享关于【详细描述一下Elasticsearch搜索的过程&#xff1f;】面试题。希望对大家有帮助&#xff1b; 详细描述一下Elasticsearch搜索的过程&#xff1f; Elasticsearch 的搜索过程是其核心功能之一&#xff0c;允许用户对存储在 Elasticsea…

springBoot插件打包部署

打包插件spring-boot-maven-plugin 不使用插件&#xff0c;运行时&#xff0c;异常信息为“没有主清单属性” 本地部署 杀进程

[ 网络安全介绍 1 ] 什么是网络安全?

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

无插件H5播放器EasyPlayer.js视频流媒体播放器如何开启electron硬解码Hevc(H265)

在数字化时代&#xff0c;流媒体播放器技术正经历着前所未有的变革。随着人工智能、大数据、云计算等技术的融合&#xff0c;流媒体播放器的核心技术不断演进&#xff0c;为用户提供了更加丰富和个性化的观看体验。 EasyPlayer.js H5播放器&#xff0c;是一款能够同时支持HTTP、…

阿里数字人工作 Emote Portrait Alive (EMO):基于 Diffusion 直接生成视频的数字人方案

TL;DR 2024 年 ECCV 阿里智能计算研究所的数字人工作&#xff0c;基于 diffusion 方法来直接的从音频到视频合成数字人&#xff0c;避免了中间的三维模型或面部 landmark 的需求&#xff0c;效果很好。 Paper name EMO: Emote Portrait Alive - Generating Expressive Portra…

Unity脚本基础规则

Unity脚本基础规则 如何在Unity中创建一个脚本文件&#xff1f; 在Project窗口中的Assets目录下&#xff0c;选择合适的文件夹&#xff0c;右键&#xff0c;选择第一个Create&#xff0c;在新出现的一栏中选择C# Script&#xff0c;此时文件夹内会出现C#脚本图标&#xff0c;…

基于YOLOv8深度学习的无人机航拍小目标检测系统(PyQt5界面+数据集+训练代码)

本研究提出并实现了一种基于YOLOv8深度学习模型的无人机航拍小目标检测系统&#xff0c;旨在解决高空环境下汽车目标检测的技术难题。随着无人机技术的发展&#xff0c;航拍图像已广泛应用于交通监控、城市管理、灾害应急等多个领域。然而&#xff0c;由于无人机通常在较高的飞…

Excel如何把两列数据合并成一列,4种方法

Excel如何把两列数据合并成一列,4种方法 参考链接:https://baijiahao.baidu.com/s?id=1786337572531105925&wfr=spider&for=pc 在Excel中,有时候需要把两列或者多列数据合并到一列中,下面介绍4种常见方法,并且提示一些使用注意事项,总有一种方法符合你的要求:…

VSCode自定义插件创建教程

文章目录 一、前言二、插件维护三、调试插件四、使用 vsce 生成 vsix 插件五、问题&#xff1a;打开调试窗口后&#xff0c;输入helloworld并没有指令提示六、插件创建实战七、拓展阅读 一、前言 对于前端程序猿来讲&#xff0c;最常用的开发利器中VSCode首当其冲&#xff0c;…