项目目标
- 满足自己筛选基金经理;
- 写一个跟AI相关的项目;
- 学习与锻炼Python编程;
- 学习与使用开源框架 Qwen-agent。
项目背景
早在2020年底就尝试过爬取网上的基金数据用来解决自己的问题了,从网上学到一些筛选基金经理的理论,想着去实践,但是专业网站、APP都不能满足。
因此,就想着自己来写一个工具,从数据采集到最后数据分析结果呈现,尽可能地让整个过程自动化。可是,一直未去实践,仅是有想法而已,画画流程图而已。
2020年,随着 GPT-3火爆全球,AI正式进入科技领域的热门。而我是在近一年多才慢慢主动去关注这个领域,去学习一些应用层技术。之后,了解到有chan2SQL,觉得挺有意思的。很快就和自己以前构想的基金经理筛选项目结合到一起了。
好了,大概就这样,接下来就是实现的过程了。整个过程,基本上靠LLM chat工具来写代码,而我主要负责出想法,调试代码。
想法 + 使用AI工具实现过程
工具与技术框架介绍
工具:
- Windows 笔记本
- PyCharm 2025.1
技术框架:
- Qwen-agen 0.0.24;
- Python 3.12;
- flask 3.1.0;
- flask-cors 3.0.10;
- vue.js
Python解释器里关键包:
- mysql 0.0.3
- mysql-connector-python 8.4.0
- mysqlclient 2.2.7
为了方便阅读,此系列文章,每一篇开头都保持上述【项目目标】和【项目背景】,以及【想法 + 使用AI工具实现过程】中的“工具与技术框架介绍”。
基于初版代码优化过程
本次主要优化内容
- 前端无法获取SQL排查与解决;
- 测试过程发现并的问题;
- 查询字段单位对齐问题。
初始代码如下
具体内容就不再一一复制粘贴,有需要整个项目完整代码,可通过右侧链接下载:夸克网盘分享
前端无法获取SQL排查与解决
在未仔细调试代码之前,误以为是 qwen-max 模型无法生成SQL的原因,才导致前端多次运行得到的SQL都是空的,却不知道是因为处理 final_content 不正确。将其打印出来分析,里面的结构中属性“content”,就存在了所需的SQL,也就是模型生成的SQL,而代码还多此一举地通过正则表达式提取,而提取的方法有写得有bug,所以才导致了无法获取到SQL的问题。
最终解决问题的关键代码:(分析了 final_content 的结构之后,获取SQL就不难了)
# 将内容中的 “<HTTPStatus.OK: 200>” 替换为 “200”,是确保 ast.literal_eval 能不报错
content_data = ast.literal_eval(final_content.replace('<HTTPStatus.OK: 200>', '200'))
if 'content' in content_data[0]:
sql_str = content_data[0]['content']
按上述方法处理完之后,再次运行代码,生成SQL就较为稳定了,尤其是单表查询的问题,准确率都接近100%。
测试过程发现并的问题
1. 测试的过程中,发现了执行SQL的方法有一个问题:漏掉了最关键的执行语句代码:cursor.execute(sql_to_run)
该方法完整的代码如下:
@app.route('/api/execute-sql', methods=['POST'])
def execute_sql():
data = request.json
sql_to_run = data.get('sql', '').strip()
if not sql_to_run:
return jsonify({'error': '缺少 SQL 语句'}), 400
conn = get_db_connection()
if not conn or not conn.is_connected():
return jsonify({'error': '数据库连接失败'}), 500
cursor = conn.cursor(dictionary=True)
# 执行 SQL
cursor.execute(sql_to_run)
try:
# 判断是否是 SELECT 查询
if sql_to_run.strip().lower().startswith('select'):
result = cursor.fetchall()
return jsonify({'result': result})
else:
conn.commit() # 提交事务
return jsonify({'message': 'SQL 执行成功', 'rows_affected': cursor.rowcount})
except Error as e:
return jsonify({'error': str(e)}), 400
finally:
cursor.close()
conn.close()
在实际业务中,我们要做这样一个自然语言转SQL的产品,并且是已投入实际生产业务使用的。后端的数据库应该是单独的,最好是单独的,也就是和业务使用的数据库不是同一个,避免生成的查询SQL出现大表无条件的全表查询,影响对实时响应要求较高的在线业务,还有更可怕的修改与删除操作等。
2. 表结构有重复意思的字段,影响SQL生成的准确性
表结构中,重复意思的字段,只是不同数据类型而已。比如:从业时长、从业年份,其实都是想表达基金经理工作时间是多长。
work_duration | '从业时长' ; work_years | '从业年份', 修改为:
work_years (从业年份/从业时长 | decimal)
fund_managing_duration | '管理时长';fund_managing_years | '管理年份',修改为:
fund_managing_years (管理年份/管理时长)
完整的 get_table_schema() 如下:
# 获取表结构信息(供 LLM 使用)
def get_table_schema():
return """
表结构如下:
- 表名: fund_list
字段(字段注释 | 字段类型): fund_id (基金ID | varchar), fund_name (基金名称 | varchar), company_id (基金公司编码 | varchar),
company_name (基金公司名称 | varchar), manager_ids (当前管理人ID | varchar), manager_names (当前管理人名称 | varchar),
fund_type (基金类型 | varchar), fund_size (基金规模(单位:亿元) | decimal), create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
- 表名: fund_manager
字段(字段注释 | 字段类型): manager_id (基金经理ID | varchar), manager_name (基金经理名称 | varchar), company_id (基金公司编码 | varchar),
company_name (基金公司名称 | varchar), work_years (从业年份/从业时长(单位:年) | decimal), manager_link (基金经理详情链接 | varchar),
create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
- 表名: manager_fund_rel
字段(字段注释 | 字段类型): id (主键 | int), manager_id (基金经理ID | varchar), manager_name (基金经理名称 | varchar),
company_id (基金公司编码 | varchar), company_name (基金公司名称 | varchar), fund_id (基金ID | varchar),
fund_type (基金类型 | varchar), fund_size (基金规模(单位:亿元) | decimal), fund_managing_time (基金管理时间 | varchar),
fund_managing_years (管理年份/管理时长(单位:年) | decimal), term_return_rate (任期回报率(小数) | decimal),
year_return_rate (年化收益率(小数) | decimal), create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
"""
按上述修改之后,测试的过程中,发现三个表的查询SQL,LLM都能准确给出来,而这个项目所涉的表,也就是三个表而已,因此在技术实现上就能满足项目目标——“满足自己筛选基金经理”
不过,在测试过程中发现了一个重要的问题,就是需求与表结构中字段的单位对齐问题,比如基金规模,数据表中的字段单位是“亿元”的,当查询条件涉及基金规模时,就需要转换成同一单位来筛选数据。
这也是接下来要说的内容…
查询字段单位对齐问题
首先,是从system prompt 与 get_table_schema(),也就是提供给LLM的表结构优化开始的。
表结构中注明字段单位,system prompt 提示要考虑单位问题,并告知是转成数据表字段单位一致,见下面代码第3点:
system_prompt = f'''
你是一个专业的 MySQL 数据库专家,能按需求写出 SQL。请遵循以下规则:
1. 严格遵循以下表结构:
{get_table_schema()}
2. 生成的 SQL 必须严格符合表结构和字段名。
3. 在生成 SQL 的过程中,需要考虑字段单位问题,要统一单位比较,将问题中涉及到单位的,都转换为与数据表字段的一致。
4. 如果问题涉及未提及的表或字段,请直接告知用户。
5. 只需输出 SQL 语句,不要输出格式化的内容(比如换行符\n等),不要执行它,也不要解释。
'''
这个方法测试之后发现:
- 对于时间的单位年来说,就轻松解决了;
- 对于元转亿元来说,表现也不错;
- 对于万元转亿元来说,准确率都不到50%。
接着,针对万元转亿元准确率不高的问题,尝试了 Few-Shot
system prompt 如下:
system_prompt = f'''
你是一个专业的 MySQL 数据库专家,能按需求写出 SQL。请遵循以下规则:
1. 严格遵循以下表结构:
{get_table_schema()}
2. 生成的 SQL 必须严格符合表结构和字段名。
3. 在生成 SQL 的过程中,需要考虑字段单位问题,要统一单位比较,将问题中涉及到单位的,都转换为与数据表字段的一致。
## 若问题中涉及金额单位,请将其从原始单位转换为亿元,比如:
- 10000000 元 转为 0.1 亿元
- 100000000 元 转为 1 亿元
- 1000 万元 转为 0.1 亿元
- 10000 万元 转为 1 亿元
- 100000 万元 转为 10 亿元
4. 如果问题涉及未提及的表或字段,请直接告知用户。
5. 只需输出 SQL 语句,不要输出格式化的内容(比如换行符\n等),不要执行它,也不要解释。
'''
运行测试发现:问题依旧,万元转亿元的准确率还是上不去。
这时,还怀疑是不是 prompt 写得不够好,于是想着通过 LLM (通义,Qwen3)来优化一下它
prompt
system_prompt = f'''
你是一个专业的 MySQL 数据库专家,能按需求写出 SQL。请遵循以下规则:
1. 严格遵循以下表结构:
{get_table_schema()}
2. 生成的 SQL 必须严格符合表结构和字段名。
3. 在生成 SQL 的过程中,需要考虑字段单位问题,要统一单位比较,将问题中涉及到单位的,都转换为与数据表字段的一致。
- 若问题中涉及金额单位,请将其从原始单位转换为亿元,比如:100000000 元 = 1 亿元
4. 如果问题涉及未提及的表或字段,请直接告知用户。
5. 只需输出 SQL 语句,不要输出格式化的内容(比如换行符\n等),不要执行它,也不要解释。
'''
请帮我优化上述prompt,让 qwen-max 更加能读懂它
新的 system prompt 如下:
system_prompt = f'''
你是一个专业的 MySQL 数据库专家,能够根据自然语言需求精准生成对应的 SQL 查询语句。请严格按照以下要求执行:
【核心规则】
1. 你必须基于以下表结构生成 SQL:
{get_table_schema()}
2. 所有字段名和表名必须与上述结构完全一致,不能擅自更改或猜测。
3. 如果问题中涉及未在表结构中定义的字段或表,请直接返回:「该查询所需字段/表不存在于数据库中」
4. 遇到金额类字段时,需统一转换为“亿元”,再进行比较或计算。
5. 输出内容仅限一条完整 SQL 语句,不包含任何解释、注释、Markdown 格式、换行符等无关内容。
6. 不要添加额外条件或限制(如 LIMIT),除非用户明确要求。
现在,请根据用户的自然语言描述,生成对应 SQL。
'''
运行测试发现:问题依旧如此,万元转亿元的准确率还是上不去。
紧接着,还是通过微调 Few-Shot 来测试,结果都无济于事。
渐进地,我怀疑是 qwen-max 模型对这个“万元”转“亿元”的问题,就是不够准确。
为了验证这个想法,在coze,使用工作流,大模型节点,选择“千问.MAX”,做了验证测试,测试结果如下表:
测试内容 | 总测试次数 | 正确次数 | 错误次数 | 不确定次数 | 正确率 |
1000万元,这是多少亿元,请直接回答 | 10 | 10 | 0 | 0 | 100% |
1000000万元,这是多少亿元,请直接回答 | 10 | 6 | 4 | 0 | 60% |
10000000元,这是多少亿元,请直接回答 | 10 | 9 | 0 | 1 | 90% |
1000000000元,这是多少亿元,请直接回答 | 10 | 10 | 0 | 0 | 100% |
在代码中使用 qwen-max 模型,也做了一个同样的验证,使用的是代码,代码如下:
from dotenv import load_dotenv
from qwen_agent.agents import Assistant
import time
# 加载环境变量
load_dotenv()
# 获取表结构信息(供 LLM 使用)
def get_table_schema():
return """
表结构如下:
- 表名: fund_list
字段(字段注释 | 字段类型): fund_id (基金ID | varchar), fund_name (基金名称 | varchar), company_id (基金公司编码 | varchar),
company_name (基金公司名称 | varchar), manager_ids (当前管理人ID | varchar), manager_names (当前管理人名称 | varchar),
fund_type (基金类型 | varchar), fund_size (基金规模(单位:亿元) | decimal), create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
- 表名: fund_manager
字段(字段注释 | 字段类型): manager_id (基金经理ID | varchar), manager_name (基金经理名称 | varchar), company_id (基金公司编码 | varchar),
company_name (基金公司名称 | varchar), work_years (从业年份/从业时长(单位:年) | decimal), manager_link (基金经理详情链接 | varchar),
create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
- 表名: manager_fund_rel
字段(字段注释 | 字段类型): id (主键 | int), manager_id (基金经理ID | varchar), manager_name (基金经理名称 | varchar),
company_id (基金公司编码 | varchar), company_name (基金公司名称 | varchar), fund_id (基金ID | varchar),
fund_type (基金类型 | varchar), fund_size (基金规模(单位:亿元) | decimal), fund_managing_time (基金管理时间 | varchar),
fund_managing_years (管理年份/管理时长(单位:年) | decimal), term_return_rate (任期回报率(小数) | decimal),
year_return_rate (年化收益率(小数) | decimal), create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
"""
system_prompt = f'''
你是一个专业的 MySQL 数据库专家,能按需求写出 SQL。请遵循以下规则:
1. 严格遵循以下表结构:
{get_table_schema()}
2. 生成的 SQL 必须严格符合表结构和字段名。
3. 在生成 SQL 的过程中,需要考虑字段单位问题,要统一单位比较,将问题中涉及到单位的,都转换为与数据表字段的一致。
## 若问题中涉及金额单位,请将其从原始单位转换为亿元,比如:
- 10000000 元 转为 0.1 亿元
- 100000000 元 转为 1 亿元
- 1000 万元 转为 0.1 亿元
- 10000 万元 转为 1 亿元
- 100000 万元 转为 10 亿元
4. 如果问题涉及未提及的表或字段,请直接告知用户。
5. 只需输出 SQL 语句,不要输出格式化的内容(比如换行符\n等),不要执行它,也不要解释。
'''
# 初始化 Qwen 助手(不注册任何工具)
llm_cfg = {
'model': 'qwen-max', # 'qwen-plus',
'model_server': 'dashscope'
}
bot = Assistant(
llm=llm_cfg,
system_message=system_prompt
)
messages = []
# user_input = '1000万元,这是多少亿元,请直接回答,这是多少亿元,请直接回答'
# user_input = '1000000万元,这是多少亿元,请直接回答,这是多少亿元,请直接回答'
# user_input = '10000000元,这是多少亿元,请直接回答,这是多少亿元,请直接回答'
user_input = '1000000000元,这是多少亿元,请直接回答,这是多少亿元,请直接回答'
for num in range(10):
# 用户输入自然语言,让 AI 生成 SQL
messages.append({'role': 'user', 'content': user_input})
# 获取 AI 最终生成的 SQL
final_content = ''
for r in bot.run(messages=messages):
if isinstance(r, dict):
content = r.get('content', '')
else:
content = str(r)
final_content = content.strip() # 保留最后一次的内容
print('final_content ------------------------------------ ')
print(final_content)
time.sleep(num)
测试结果如下表:
测试内容 | 总测试次数 | 正确次数 | 错误次数 | 不确定次数 | 正确率 |
1000万元,这是多少亿元,请直接回答 | 10 | 10 | 0 | 0 | 100% |
1000000万元,这是多少亿元,请直接回答 | 10 | 3 | 7 | 0 | 30% |
10000000元,这是多少亿元,请直接回答 | 10 | 10 | 0 | 0 | 100% |
1000000000元,这是多少亿元,请直接回答 | 10 | 10 | 0 | 0 | 100% |
这两个测试结果,应该能说明 qwen-max 模型存在“万元”转“亿元”准确率不高的问题,从而也放弃了使用 prompt 优化的方法来解决它。
总想着找一个更好一点的办法来解决—— qwen-max 模型存在“万元”转“亿元”准确率不高的问题,各种查阅资料下来,也没找到较为满意的。
最后是通过代码来解决的,大致的处理逻辑如下流程图:
按此方法修改了代码,涉及“万元”转“亿元”的单位问题,测试结果是 100%解决了的,总共测试了20次。
本次主要优化的三点内容,均只是涉及 app.py 这个代码文件而已,最后粘贴一下这个文件的完整代码,代码如下:
import numbers
from flask import Flask, jsonify, request
from flask_cors import CORS
import mysql.connector
from mysql.connector import Error
import os
from dotenv import load_dotenv
from qwen_agent.agents import Assistant
import ast
# 加载环境变量
load_dotenv()
app = Flask(__name__)
CORS(app) # 启用跨域请求
import sys
print(sys.executable)
# 数据库连接配置(从 .env 文件读取)
def get_db_connection():
try:
connection = mysql.connector.connect(
host=os.getenv('DB_HOST'),
user=os.getenv('DB_USER'),
password=os.getenv('DB_PASSWORD'),
database=os.getenv('DB_NAME')
)
return connection
except Error as e:
print(f"数据库连接失败: {e}")
return None
# 获取表结构信息(供 LLM 使用)
def get_table_schema():
return """
表结构如下:
- 表名: fund_list
字段(字段注释 | 字段类型): fund_id (基金ID | varchar), fund_name (基金名称 | varchar), company_id (基金公司编码 | varchar),
company_name (基金公司名称 | varchar), manager_ids (当前管理人ID | varchar), manager_names (当前管理人名称 | varchar),
fund_type (基金类型 | varchar), fund_size (基金规模(单位:亿元) | decimal), create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
- 表名: fund_manager
字段(字段注释 | 字段类型): manager_id (基金经理ID | varchar), manager_name (基金经理名称 | varchar), company_id (基金公司编码 | varchar),
company_name (基金公司名称 | varchar), work_years (从业年份/从业时长(单位:年) | decimal), manager_link (基金经理详情链接 | varchar),
create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
- 表名: manager_fund_rel
字段(字段注释 | 字段类型): id (主键 | int), manager_id (基金经理ID | varchar), manager_name (基金经理名称 | varchar),
company_id (基金公司编码 | varchar), company_name (基金公司名称 | varchar), fund_id (基金ID | varchar),
fund_type (基金类型 | varchar), fund_size (基金规模(单位:亿元) | decimal), fund_managing_time (基金管理时间 | varchar),
fund_managing_years (管理年份/管理时长(单位:年) | decimal), term_return_rate (任期回报率(小数) | decimal),
year_return_rate (年化收益率(小数) | decimal), create_user (创建人 | varchar), create_time (创建时间 | datetime), update_time (更新时间 | datetime)
"""
import re
# 通过正则表达式匹配和提取出金额数字和单位
def extract_amount_and_unit(text):
text = text.strip()
text = re.sub(r'\s+', ' ', text)
match = re.search(r'(\d+[\d\.\,]*)\s*(亿元|万元|元)', text)
if match:
amount_str = match.group(1)
unit = match.group(2)
# 转换金额(考虑千分位逗号)
amount = float(amount_str.replace(',', ''))
return amount, unit
else:
# 默认无单位时认为是“元”
# 尝试提取纯数字
num_match = re.search(r'(\d+[\d\.\,]*)', text)
amount = float(num_match.group(1).replace(',', '')) if num_match else 1
return amount, '元'
def extract_condition_value(sql, column_name):
# 改进后的正则:将数值部分也作为捕获组
pattern = rf"{column_name}\s*([<>!=]=?|LIKE)\s*(?:'([^']*)'|(\d+\.?\d*))"
match = re.search(pattern, sql, re.IGNORECASE)
if match:
# operator = match.group(1) # 操作符
string_value = match.group(2) # 引号内的值(字符串)
number_value = match.group(3) # 数值型值
value = string_value or number_value
return value
return None
#统一转单位为“亿元”
def convert_to_yiyuan(amount, unit):
if unit == '亿元':
return amount
elif unit == '万元':
return amount / 10_000
elif unit == '元':
return amount / 100_000_000
else:
return amount
# 构建 system_prompt
system_prompt = f'''
你是一个专业的 MySQL 数据库专家,能按需求写出 SQL。请遵循以下规则:
1. 严格遵循以下表结构:
{get_table_schema()}
2. 生成的 SQL 必须严格符合表结构和字段名。
3. 在生成 SQL 的过程中,需要考虑字段单位问题,要统一单位比较:
- 若涉及金额单位,统一转换为“亿元”
- 若涉及时间单位,比如天、周、月、季度、年,统一转换为“年”
- 其他单位,都转换为与数据表字段的一致
4. 如果问题涉及未提及的表或字段,请直接告知用户。
5. 只需输出 SQL 语句,不要输出格式化的内容(比如换行符\n等),不要执行它,也不要解释。
'''
# 初始化 Qwen 助手(不注册任何工具)
llm_cfg = {
'model': 'qwen-max', # 'qwen-plus',
'model_server': 'dashscope'
}
bot = Assistant(
llm=llm_cfg,
system_message=system_prompt
)
messages = []
@app.route('/api/generate-sql', methods=['POST'])
def generate_sql():
global messages
data = request.json
user_input = data.get('query', '')
if not user_input:
return jsonify({'error': '缺少查询内容'}), 400
if user_input.lower() in ['exit', 'quit']:
return jsonify({'sql': ''})
# 用户输入自然语言,让 AI 生成 SQL
messages.append({'role': 'user', 'content': user_input})
# 获取 AI 最终生成的 SQL
final_content = '';
for r in bot.run(messages=messages):
if isinstance(r, dict):
content = r.get('content', '')
else:
content = str(r)
final_content = content.strip() # 保留最后一次的内容
sql_str = ''
# 将内容中的 “<HTTPStatus.OK: 200>” 替换为 “200”,是确保 ast.literal_eval 能不报错
content_data = ast.literal_eval(final_content.replace('<HTTPStatus.OK: 200>', '200'))
if 'content' in content_data[0]:
sql_str = content_data[0]['content']
# 判断问题中是否存在基金规模作为查询条件
assistant_yiyuan_num = extract_condition_value(sql_str, "fund_size")
if assistant_yiyuan_num:
amount, unit = extract_amount_and_unit(user_input)
yiyuan_num = convert_to_yiyuan(amount, unit)
# 判断通过 Python 代码转换的数值与第一次 LLM 生成的是否相等,不相等继续调用 LLM
if str(yiyuan_num) != str(assistant_yiyuan_num):
user_input_new = f'''
根据用户的问题:{user_input},你首次得到的 SQL 如下:
{sql_str}
****
请你检查 SQL 中查询条件:fund_size 的数值单位转换是否正确,正确的数值应是:{yiyuan_num}
## 要求:
SQL语句末尾应包含英文分号(;)
****
请输出最终 SQL
'''
# 用户输入自然语言,让 AI 生成 SQL
messages.append({'role': 'user', 'content': user_input_new})
# 获取 AI 第二次生成的 SQL
for r in bot.run(messages=messages):
if isinstance(r, dict):
content = r.get('content', '')
else:
content = str(r)
final_content = content.strip()
content_data = ast.literal_eval(final_content.replace('<HTTPStatus.OK: 200>', '200'))
if 'content' in content_data[0]:
sql_str = content_data[0]['content']
messages.append({'role': 'assistant', 'content': final_content})
return jsonify({'sql': sql_str, 'final_content' : final_content})
@app.route('/api/execute-sql', methods=['POST'])
def execute_sql():
data = request.json
sql_to_run = data.get('sql', '').strip()
if not sql_to_run:
return jsonify({'error': '缺少 SQL 语句'}), 400
conn = get_db_connection()
if not conn or not conn.is_connected():
return jsonify({'error': '数据库连接失败'}), 500
cursor = conn.cursor(dictionary=True)
# 执行 SQL
cursor.execute(sql_to_run)
try:
# 判断是否是 SELECT 查询
if sql_to_run.strip().lower().startswith('select'):
result = cursor.fetchall()
return jsonify({'result': result})
else:
conn.commit() # 提交事务
return jsonify({'message': 'SQL 执行成功', 'rows_affected': cursor.rowcount})
except Error as e:
return jsonify({'error': str(e)}), 400
finally:
cursor.close()
conn.close()
if __name__ == '__main__':
app.run(debug=True)
未完待续…
回看项目目标,接下来最关键的就是要实现查询结果展示,其他的应该就是一些使用交互问题了。这部分内容,就看啥时候抽空处理了,最近搞这个小项目确实花了不少心思。不过,也能学到不少知识,在实战中学习有一种踏实感。
前三篇文章,看到大家的喜欢,又是点赞收藏,还点关注。于是而言,既是认同,也是鞭策吧…
这里放一下之前文章的链接吧,方便大家阅读。
AI编程实战:Python + Qwen-agent 实现chat2SQL智能助手系统-CSDN博客