当前位置: 首页 > news >正文

AI大模型探索之路-实战篇12: 构建互动式Agent智能数据分析平台:实现多轮对话控制

系列篇章💥

AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研
AI大模型探索之路-实战篇5:探索Open Interpreter开放代码解释器调研
AI大模型探索之路-实战篇6:掌握Function Calling的详细流程
AI大模型探索之路-实战篇7:Function Calling技术实战自动生成函数
AI大模型探索之路-实战篇8:多轮对话与Function Calling技术应用
AI大模型探索之路-实战篇9:探究Agent智能数据分析平台的架构与功能
AI大模型探索之路-实战篇10:数据预处理的艺术:构建Agent智能数据分析平台的基础
AI大模型探索之路-实战篇11: Function Calling技术整合:强化Agent智能数据分析平台功能


目录

  • 系列篇章💥
  • 一、前言
  • 二、引入背景知识库
    • 1、定义OpenAI客户端
    • 2、定义工具函数生成器
    • 3、两次大模型API调用封装
    • 4、user_demographics数据查询服务封装
    • 5、user_demographics函数信息生成测试
    • 6、第一次数据查询对话测试
    • 7、读取数据字典
    • 8、第二次数据查询对话测试
    • 9、数据库基本信息查询测试
    • 10、数据分析调用测试
  • 三、实现交互确认
    • 1、定义数据库基本信息获取函数
    • 2、函数信息生成测试检查:
    • 3、数据分析测试
    • 4、定义SQL提取函数
    • 5、两次次大模型API两次调用封装改造
    • 6、定义消息列表
    • 7、数据查询分析测试1
    • 8、数据查询分析测试2
    • 9、数据查询分析测试3
  • 四、实现完整的多轮对话效果
  • 五、结语


一、前言

在Agent智能数据分析平台的实战开发中,继我们之前关于Function Calling技术整合的讨论之后,本文将专注于实现一个核心功能——多轮对话控制系统。这一机制能够让用户通过自然语言与系统进行连续的交流,从而更准确、更高效地完成数据分析任务。

二、引入背景知识库

引入数据字典知识,作为大模型对话的背景知识库。

1、定义OpenAI客户端

定义大模型客户端,用于与大模型交互对话

import openai
import os
import numpy as np
import pandas as pd
import json
import io
from openai import OpenAI
import inspect
import pymysqlopenai.api_key = os.getenv("OPENAI_API_KEY")client = OpenAI(api_key=openai.api_key)

2、定义工具函数生成器

定义一个函数,用于自动生成function calling功能需要的,工具函数信息体

def auto_functions(functions_list):"""Chat模型的functions参数编写函数:param functions_list: 包含一个或者多个函数对象的列表;:return:满足Chat模型functions参数要求的functions对象"""def functions_generate(functions_list):# 创建空列表,用于保存每个函数的描述字典functions = []# 对每个外部函数进行循环for function in functions_list:# 读取函数对象的函数说明function_description = inspect.getdoc(function)# 读取函数的函数名字符串function_name = function.__name__system_prompt = '以下是某的函数说明:%s' % function_descriptionuser_prompt = '根据这个函数的函数说明,请帮我创建一个JSON格式的字典,这个字典有如下5点要求:\1.字典总共有三个键值对;\2.第一个键值对的Key是字符串name,value是该函数的名字:%s,也是字符串;\3.第二个键值对的Key是字符串description,value是该函数的函数的功能说明,也是字符串;\4.第三个键值对的Key是字符串parameters,value是一个JSON Schema对象,用于说明该函数的参数输入规范。\5.输出结果必须是一个JSON格式的字典,只输出这个字典即可,前后不需要任何前后修饰或说明的语句' % function_nameresponse = client.chat.completions.create(model="gpt-3.5-turbo",messages=[{"role": "system", "content": system_prompt},{"role": "user", "content": user_prompt}])json_function_description=json.loads(response.choices[0].message.content.replace("```","").replace("json",""))json_str={"type": "function","function":json_function_description}functions.append(json_str)return functionsmax_attempts = 4attempts = 0while attempts < max_attempts:try:functions = functions_generate(functions_list)break  # 如果代码成功执行,跳出循环except Exception as e:attempts += 1  # 增加尝试次数print("发生错误:", e)if attempts == max_attempts:print("已达到最大尝试次数,程序终止。")raise  # 重新引发最后一个异常else:print("正在重新运行...")return functions

3、两次大模型API调用封装

封装funcation calling中两次大模型API得调用

def run_conversation(messages, functions_list=None, model="gpt-3.5-turbo"):"""能够自动执行外部函数调用的对话模型:param messages: 必要参数,字典类型,输入到Chat模型的messages参数对象:param functions_list: 可选参数,默认为None,可以设置为包含全部外部函数的列表对象:param model: Chat模型,可选参数,默认模型为gpt-3.5-turbo:return:Chat模型输出结果"""# 如果没有外部函数库,则执行普通的对话任务if functions_list == None:response = client.chat.completions.create(model=model,messages=messages,)response_message = response.choices[0].messagefinal_response = response_message.content# 若存在外部函数库,则需要灵活选取外部函数并进行回答else:# 创建functions对象tools = auto_functions(functions_list)# 创建外部函数库字典available_functions = {func.__name__: func for func in functions_list}# 第一次调用大模型response = client.chat.completions.create(model=model,messages=messages,tools=tools,tool_choice="auto", )response_message = response.choices[0].messagetool_calls = response_message.tool_callsif tool_calls:messages.append(response_message) for tool_call in tool_calls:function_name = tool_call.function.namefunction_to_call = available_functions[function_name]function_args = json.loads(tool_call.function.arguments)function_response = function_to_call(**function_args)messages.append({"tool_call_id": tool_call.id,"role": "tool","name": function_name,"content": function_response,}) ## 第二次调用模型second_response = client.chat.completions.create(model=model,messages=messages,) # 获取最终结果final_response = second_response.choices[0].message.contentelse:final_response = response_message.contentreturn final_response

4、user_demographics数据查询服务封装

定义一个get_user_demographics函数,用于获取user_demographics 表的相关信息

def get_user_demographics(sql_query):"""用户获取user_demographics 表的相关信息:param sql_query: 字符串形式的SQL语句:return SQL查询的user_demographics 表的相关信息"""mysql_pw="iquery_agent"connection = pymysql.connect(host='localhost',  # 数据库地址user='iquery_agent',  # 数据库用户名passwd=mysql_pw,  # 数据库密码db='iquery',  # 数据库名charset='utf8'  # 字符集选择utf8   )try:with connection.cursor() as cursor:sql = sql_querycursor.execute(sql)results = cursor.fetchall()finally:cursor.close()column_names = [desc[0] for desc in cursor.description]# 使用results和column_names创建DataFramedf = pd.DataFrame(results, columns=column_names)return df.to_json(orient = "records")         

5、user_demographics函数信息生成测试

使用工具函数生成器,对测试是否能够正常生成user_demographics相关数据查询的工具函数信息

#定义工具函数列表(当前只有user_demographics信息获取的函数)
functions_list = [get_user_demographics]#user_demographics相关数据查询的工具函数信息,生成测试
tools = auto_functions(functions_list)
tools

生成的函数信息如下:
在这里插入图片描述

注意:结构生成不一定正确,大模型缺少稳定性;可能需要多次调用测试;也可以再生成函数中,加入校验;比如:如果缺失关键key、value,就让大模型重新生成。

6、第一次数据查询对话测试

使用自然语言对话的方式,进行数据查询分析

messages=[{"role": "user", "content": "请问user_demographics表中个人属性为老年男性的数据总共有多少条?"}]response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,tools=tools,tool_choice="auto",  )response.choices[0].message       

输出:

ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_5VK3ywSsn76wNBfAEc17FaWr', function=Function(arguments='{"sql_query":"SELECT COUNT(*) FROM user_demographics WHERE age >= 60 AND gender = \'male\'"}', name='get_user_demographics'), type='function')])

可以从结果中检查大模型是否正常找到自己生成的工具函数,以及生成的相关SQL是否正确;
查询SQL中使用了年龄大于60岁,来查询老年人。

7、读取数据字典

读取本地的数据字典

# 打开并读取Markdown文件
with open('/root/autodl-tmp/iquery项目/data/数据字典/iquery数据字典.md', 'r', encoding='utf-8') as f:md_content = f.read()md_content

输出

'# iquery数据字典:iquery数据库数据字典\n\n本数据字典记录了iquery数据库中各张数据表的基本情况。\n\n## 1.user_demographics数据表\n\n- 基本解释\n\n  \u200b\t\tuser_demographics数据表记录了电信用户的个人基本情况,主要涵盖客户基本生物属性,包括性别、年龄状况、是否结婚以及是否经济独立等。\n\n- 数据来源\n\n  \u200b\tuser_demographics数据集由一线业务人员人工采集记录,并且通过回访确认相关信息,数据集的准确性和可信度都非常高。\n\n- 各字段说明\n\n| Column Name | Description | Value Range | Value Explanation | Type |\n|-------------|-------------|-------------|-------------------|------|\n| customerID | 客户ID,user_demographics数据表主键 |              | 由数字和字母组成的 | VARCHAR(255) |\n| gender | 用户的性别 | Female, Male | Female (女性), Male (男性) | VARCHAR(255) |\n| SeniorCitizen | 是否为老人 | 0, 1 | 0 (不是), 1 (是) | INT |\n| Partner | 用户是否有伴侣 | Yes, No | Yes (有), No (没有) | VARCHAR(255) |\n| Dependents | 用户经济是否独立,往往用于判断用户是否已经成年 | No, Yes | Yes (有), No (没有) | VARCHAR(255) |\n\n## 2.user_services数据表\n\n- 基本解释\n\n  \u200b        user_services数据表记录了每位用户订购电信服务的基本情况,截至目前,电信服务商提供了种类多样的服务,包括电话类服务和网络类服务等,本数据集表记录了每位用户订阅电信服务的基本情况。\n\n- 数据来源\n\n  \u200b\t\tuser_services数据表由后台系统自动创建生成,并未经过人工校验。\n\n- 各字段说明\n\n| Column Name | Description | Value Range | Value Explanation | Type |\n|-------------|-------------|-------------|-------------------|------|\n| customerID | 客户ID,user_services数据表主键 |  | 由数字和字母组成的 | VARCHAR(255) |\n| PhoneService | 用户是否有电话服务 | No, Yes | Yes (有), No (没有) | VARCHAR(255) |\n| MultipleLines | 用户是否开通了多条电话业务 | No phone service, No, Yes | Yes (有多条电话线业务), No (没有多条电话线业务), No phone service (没有电话服务) | VARCHAR(255) |\n| InternetService | 用户的互联网服务类型 | DSL, Fiber optic, No | DSL (DSL), Fiber optic (光纤), No (没有) | VARCHAR(255) |\n| OnlineSecurity | 是否开通网络安全服务 | No, Yes, No internet service | Yes(有)、No(无) or No internetservice(没有网路服务) | VARCHAR(255) |\n| OnlineBackup | 是否开通在线备份服务 | Yes, No, No internet service | Yes(有)、No(无) or No internetservice(没有网路服务) | VARCHAR(255) |\n| DeviceProtection | 是否开通设备保护服务 | No, Yes, No internet service | Yes(有)、No(无) or No internetservice(没有网路服务) | VARCHAR(255) |\n| TechSupport | 是否开通技术支持业务 | No, Yes, No internet service | Yes(有)、No(无) or No internetservice(没有网路服务) | VARCHAR(255) |\n| StreamingTV | 是否开通网络电视 | No, Yes, No internet service | Yes(有)、No(无) or No internetservice(没有网路服务) | VARCHAR(255) |\n| StreamingMovies | 是否开通网络电影 | No, Yes, No internet service | Yes(有)、No(无) or No internetservice(没有网路服务) | VARCHAR(255) |\n\n## 3.user_payments数据表\n\n- 基本解释\n\n  \u200b\t\tuser_payments数据表记录了每一位用户支付状况,既包括用户的支付方式和合同类型,同时也包含用户具体支付金额,包括月付金额和总金额等。\n\n- 数据来源\n\n  \u200b\t\tuser_payments数据表由后台自动记录生成,并未经过校验。\n\n- 各字段说明\n\n| Column Name | Description | Value Range | Value Explanation | Type |\n|-------------|-------------|-------------|-------------------|------|\n| customerID | 客户ID,user_payments数据表主键 |  | 由数字和字母组成的 | VARCHAR(255) |\n| Contract | 合同类型 | Month-to-month, One year, Two year | Month-to-month (月付), One year (一年付), Two year (两年付) | VARCHAR(255) |\n| PaperlessBilling | 是否无纸化账单 | Yes, No | Yes (是), No (否) | VARCHAR(255) |\n| PaymentMethod | 支付方式 | Electronic check, Mailed check, Bank transfer (automatic), Credit card (automatic) | Electronic check (电子检查), Mailed check (邮寄支票), Bank transfer (automatic) (银行转账), Credit card (automatic) (信用卡) | VARCHAR(255) |\n| MonthlyCharges | 月费用 |  | 用户平均每月支付费用 | FLOAT        |\n| TotalCharges | 总费用 |  | 截至目前用户总消费金额 | VARCHAR(255) |\n\n## 4.user_churn\n\n- 基本解释\n\n  \u200b\t\tuser_churn数据表记录了当前用户流失情况。\n\n- 数据来源\n\n  \u200b\t\tuser_churn数据表由后台自动创建并记录,当合同截至后但用户未续费,则判断该用户目前处于流失状态。\n\n- 各字段说明\n\n| Column Name | Description | Value Range | Value Explanation | Type |\n|-------------|-------------|-------------|-------------------|------|\n| customerID | 客户ID,user_churn数据表主键 |             | 由数字和字母组成的 | VARCHAR(255) |\n| Churn | 用户是否流失 | No, Yes | Yes (是), No (否) | VARCHAR(255) |\n\n'

8、第二次数据查询对话测试

将数据字典作为背景知识,再次使用自然语言对话的方式,进行数据查询分析

messages=[{"role": "system", "content": md_content}, {"role": "user", "content": "请问user_demographics表中个人属性为老年男性的数据总共有多少条?"}
]
response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,tools=tools,tool_choice="auto",  )response.choices[0].message

输出:

ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_e4LEDDcytWdGUx0m98plDpUa', function=Function(arguments='{"sql_query":"SELECT * FROM user_demographics WHERE SeniorCitizen = 1 AND gender = \'Male\'"}', name='get_user_demographics'), type='function')])

通过输出结果可以看到,这一次数据查询中使用了SeniorCitizen 字段,因为背景知识中,这个字段是用来标识老人的,不需要通过年龄判断。
在这里插入图片描述

9、数据库基本信息查询测试

调用大模型API查询数据库的基本情况信息

messages=[{"role": "system", "content": md_content}, {"role": "user", "content": "请帮我介绍下iquery这个数据库的基本情况"}
]
response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,)response.choices[0].message.content

输出:

'iquery数据库是一个用于电信用户数据分析的数据库,主要包括了四张数据表:user_demographics、user_services、user_payments和user_churn。这些数据表记录了电信用户的个人基本情况、订购的电信服务情况、支付情况以及流失情况。用户可以通过iquery数据库中的数据来进行用户行为分析、用户流失预测、产品定价优化等工作。每张数据表都有各自的字段说明,方便用户了解和利用数据库中的数据。'

10、数据分析调用测试

让大模型帮忙分析user_demographics数据表和user_services数据表的数据可信度。

messages=[{"role": "system", "content": md_content}, {"role": "user", "content": "user_demographics数据表和user_services数据表哪张表的数据可信度更高呢?"}
]
response = client.chat.completions.create(model="gpt-3.5-turbo",messages=messages,)print(response.choices[0].message.content)

输出:

根据描述,user_demographics数据表由一线业务人员人工采集记录,并通过回访确认相关信息,数据集的准确性和可信度都非常高。而user_services数据表由后台系统自动生成,并未经过人工校验。因此,user_demographics数据表的数据可信度更高。

三、实现交互确认

在数据查询分析前,让大模型输出将要执行的SQL,让用户确认检查;同时咨询是否需要执行

1、定义数据库基本信息获取函数

定义一个获取数据库基本信息的工具函数

def sql_inter(sql_query):"""用于获取iquery数据库中各张表的有关相关信息,\核心功能是将输入的SQL代码传输至iquery数据库所在的MySQL环境中进行运行,\并最终返回SQL代码运行结果。需要注意的是,本函数是借助pymysql来连接MySQL数据库。:param sql_query: 字符串形式的SQL查询语句,用于执行对MySQL中iquery数据库中各张表进行查询,并获得各表中的各类相关信息:return:sql_query在MySQL中的运行结果。"""mysql_pw = "iquery_agent"connection = pymysql.connect(host='localhost',  # 数据库地址user='iquery_agent',  # 数据库用户名passwd=mysql_pw,  # 数据库密码db='iquery',  # 数据库名charset='utf8'  # 字符集选择utf8)try:with connection.cursor() as cursor:# SQL查询语句sql = sql_querycursor.execute(sql)# 获取查询结果results = cursor.fetchall()finally:connection.close()return json.dumps(results)

2、函数信息生成测试检查:

#定义工具函数列表
functions_list = [sql_inter]#工具函数信息生成
tools = auto_functions(functions_list)
tools

输出:
在这里插入图片描述

检查生成的函数信息结构是否正确,是否有缺失的key、value

3、数据分析测试

messages = [{"role": "system", "content": md_content},{"role": "user", "content": "请问user_demographics数据表的主键和user_services数据表的主键是否完全一致?"}
]
run_conversation(messages, functions_list=functions_list, model="gpt-3.5-turbo")

输出:
在这里插入图片描述

4、定义SQL提取函数

def extract_sql(json_str):# 提取并返回'sql_query'的值return json_str.get('sql_query', None)

5、两次次大模型API两次调用封装改造

改造二次大模型API两次调用的封装函数,引入用户确认的逻辑

def check_code_run(messages, functions_list=None, model="gpt-3.5-turbo",auto_run = True):"""能够自动执行外部函数调用的对话模型:param messages: 必要参数,字典类型,输入到Chat模型的messages参数对象:param functions_list: 可选参数,默认为None,可以设置为包含全部外部函数的列表对象:param model: Chat模型,可选参数,默认模型为gpt-3.5-turbo:return:Chat模型输出结果"""# 如果没有外部函数库,则执行普通的对话任务if functions_list == None:response = client.chat.completions.create(model=model,messages=messages,)response_message = response.choices[0].messagefinal_response = response_message.content# 若存在外部函数库,则需要灵活选取外部函数并进行回答else:# 创建functions对象tools = auto_functions(functions_list)# 创建外部函数库字典available_functions = {func.__name__: func for func in functions_list}# 第一次调用大模型response = client.chat.completions.create(model=model,messages=messages,tools=tools,tool_choice="auto", )response_message = response.choices[0].messagetool_calls = response_message.tool_callsif tool_calls:messages.append(response_message) for tool_call in tool_calls:function_name = tool_call.function.namefunction_to_call = available_functions[function_name]function_args = json.loads(tool_call.function.arguments)if auto_run == False:sql_query = extract_sql(function_args)res = input('即将执行以下代码:%s。是否确认并继续执行(1),或者退出本次运行过程(2)' % sql_query)if res == '2':print("终止运行")return Noneelse:print("正在执行代码,请稍后...")function_response = function_to_call(**function_args)messages.append({"tool_call_id": tool_call.id,"role": "tool","name": function_name,"content": function_response,}) ## 第二次调用模型second_response = client.chat.completions.create(model=model,messages=messages,) # 获取最终结果final_response = second_response.choices[0].message.contentelse:final_response = response_message.contentdel messagesreturn final_response

6、定义消息列表

messages = [{"role": "system", "content": md_content},{"role": "user", "content": "请问iquery数据库下user_demographics表的第10条数据内容是?"}
]
#函数列表查看
functions_list

在这里插入图片描述

7、数据查询分析测试1

check_code_run(messages, functions_list=functions_list, model="gpt-3.5-turbo", auto_run = False)

输出:
在这里插入图片描述

8、数据查询分析测试2

messages = [{"role": "system", "content": md_content},{"role": "user", "content": "请问iquery数据库下user_demographics表有多少条数据?"}
]
check_code_run(messages, functions_list=functions_list, model="gpt-3.5-turbo", auto_run = False)

输出:
在这里插入图片描述

9、数据查询分析测试3

messages = [{"role": "system", "content": md_content},{"role": "user", "content": "请问iquery数据库下user_demographics表中,男性和女性的分别有多少人"}
]
check_code_run(messages, functions_list=functions_list, model="gpt-3.5-turbo", auto_run = False)

输出:
在这里插入图片描述

四、实现完整的多轮对话效果

经过上述步骤的不断优化和测试,我们最终实现了一个完整的多轮对话控制系统。该系统不仅能够理解用户的查询意图,还能够在需要时向用户确认信息,从而使得整个数据分析过程更加透明、可控。

import tiktokendef chat_with_inter(functions_list=None, prompt="你好呀", model="gpt-3.5-turbo", system_message=[{"role": "system", "content": "你是一个智能助手。"}], auto_run = True):# 创建函数列表对应的参数解释列表functions = auto_functions(functions_list)# 多轮对话阈值if 'gpt-4' in model:tokens_thr = 6000elif '16k' in model:tokens_thr = 14000else:tokens_thr = 3000messages = system_messagemessages.append({"role": "user", "content": prompt})## 计算token大小embedding_model = "text-embedding-ada-002"# 模型对应的分词器(TOKENIZER)embedding_encoding = "cl100k_base"encoding = tiktoken.get_encoding(embedding_encoding)tokens_count = len(encoding.encode((prompt + system_message[0]["content"])))while True:           answer = check_code_run(messages, functions_list=functions_list, model=model, auto_run = auto_run)print(f"模型回答: {answer}")# 询问用户是否还有其他问题user_input = input("您还有其他问题吗?(输入退出以结束对话): ")if user_input == "退出":del messagesbreak# 记录新一轮问答messages.append({"role": "assistant", "content": answer})messages.append({"role": "user", "content": user_input})# 计算当前总token数tokens_count += len(encoding.encode((answer + user_input)))# 删除超出token阈值的对话内容while tokens_count >= tokens_thr:tokens_count -= len(encoding.encode(messages.pop(1)["content"]))
chat_with_inter(functions_list=functions_list, prompt="我想根据iquery数据库中数据分析用户流失情况,请问需要用到iquery数据库中的哪几张表呢?", model="gpt-3.5-turbo", system_message=[{"role": "system", "content": md_content}], auto_run = False)

对话效果
在这里插入图片描述

五、结语

在本篇章中,我们进一步强化了Agent智能数据分析平台的功能,通过实现可控的多轮对话交互确认逻辑,极大地提升了用户体验和系统的安全性。这一进步将为未来更加复杂、更加智能化的数据分析平台的构建奠定坚实的基础。

在这里插入图片描述

🎯🔖更多专栏系列文章:AIGC-AI大模型探索之路

😎 作者介绍:我是寻道AI小兵,资深程序老猿,从业10年+、互联网系统架构师,目前专注于AIGC的探索。
📖 技术交流:建立有技术交流群,可以扫码👇 加入社群,500本各类编程书籍、AI教程、AI工具等你领取!
如果文章内容对您有所触动,别忘了点赞、⭐关注,收藏!加入我,让我们携手同行AI的探索之旅,一起开启智能时代的大门!

相关文章:

AI大模型探索之路-实战篇12: 构建互动式Agent智能数据分析平台:实现多轮对话控制

系列篇章&#x1f4a5; AI大模型探索之路-实战篇4&#xff1a;深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5&#xff1a;探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6&#xff1a;掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…...

深入理解文件系统和日志分析

文件是存储在硬盘上的&#xff0c;硬盘上的最小存储单位是扇区&#xff0c;每个扇区的大小是512字节。 inode&#xff1a;存储元信息&#xff08;包括文件的属性&#xff0c;权限&#xff0c;创建者&#xff0c;创建日期等等&#xff09; block&#xff1a;块&#xff0c;连续…...

vue+vant移动端显示table表格加横向滚动条

vant移动端显示table效果&#xff0c;增加复选框&#xff0c;可以进行多选和全选。加横向滚动条&#xff0c;可以看全部内容。 <template><div class"app-container"><div class"nav_text" style"position: relative;"><…...

webserver服务器从零搭建到上线(八)|EpollPoller事件分发器类

文章目录 EpollPoller事件分发器类成员变量和成员函数解释私有的成员函数和成员变量成员函数 具体实现常量的作用构造函数和析构函数⭐️poll函数updateChannel函数removeChannel 函数removeChannel 和updateChannel⭐️fillActiveChannels 函数⭐️update 函数 总结 终于要开始…...

SD-WAN:企业网络转型的必然趋势

随着SD-WAN技术的不断进步和完善&#xff0c;越来越多的企业选择利用SD-WAN进行网络转型。根据IDC的研究&#xff0c;47%的企业已经成功迁移到SD-WAN&#xff0c;另有48%的公司计划在未来两个月内部署这一技术。 据Channel Futures报道&#xff0c;一位合作伙伴透露&#xff0c…...

构建高效稳定的短视频直播系统架构

随着短视频直播的迅猛发展&#xff0c;构建一个高效稳定的短视频直播系统架构成为了互联网企业的重要挑战。本文将探讨如何构建高效稳定的短视频直播系统架构&#xff0c;以提供优质的用户体验和满足日益增长的用户需求。 ### 1. 短视频直播系统的背景 短视频直播近年来蓬勃发…...

python分别保存聚类分析结果+KeyError: ‘CustomerID‘报错

如何在完成聚类分析后按聚类编号保存数据并且带上原数据所属ID # 将每个聚类的数据保存到不同的文件中 for cluster_id in range(6): # 假设共有6个聚类cluster_data data[data[cluster] cluster_id]cluster_data_with_customer_id cluster_data.copy()cluster_data_with_…...

Sui与Atoma合作为开发者提供AI支持

AI初创公司Atoma宣布其即将推出的推理网络将与Sui集成&#xff0c;该网络将使开发者能够在他们的应用程序中使用AI工具。Atoma选择Sui作为其第一个区块链集成对象是由于Sui的可扩展性和性能。 尽管生成式AI在过去几年中引起了轰动&#xff0c;但它尚未进入许多消费者应用程序。…...

go-gin中session实现redis前缀和db库选择+单点登录

分别实现了redigo中自动加前缀和session中自动加前缀 等有空了整理一个demo放到github上&#xff0c;到时候求个小星星 在gin-contrib/sessions/redis库中redis的前缀是被封装起来了&#xff0c;所以自定义前缀没有内部方法在这里我们自己实现一下NewStoreWithDBPrefix方法配…...

python-双胞胎字符串

[问题描述]&#xff1a;给定两个字符串s和t&#xff0c;每次可以任意交换s的奇数位和偶数位的字符&#xff0c;即奇数位的字符可以与任意其它奇数位的字符交换&#xff0c;偶数位的字符同样也可以与任意偶数位的字符的字符交换&#xff0c;问能否在有限的次数的交换下使s变为t?…...

万字长文,小白新手怎么开始做YOLO实验,从零开始教!整体思路在这里,科研指南针!

最近专栏来了很多的新手小白&#xff0c;对科研实验的过程感到困惑和无从下手&#xff0c;这篇文章就来讲解一下整体的科研流程&#xff0c;从选择数据集到发表论文的各个步骤&#xff0c;并针对大家在实验中常犯的错误进行解答。并且为大家提供通向我其他相关博客的指引&#…...

MDR-1A用什么前端:深度解析与实用指南

MDR-1A用什么前端&#xff1a;深度解析与实用指南 索尼MDR-1A作为一款备受瞩目的音乐耳机&#xff0c;其音质表现与前端设备的搭配息息相关。那么&#xff0c;MDR-1A用什么前端才能达到最佳的音效体验呢&#xff1f;本文将从四个方面、五个方面、六个方面和七个方面进行深入探…...

01Linux以及操作系统概述

课程目标 1.了解现代操作系统的整体构成及发展历史 2.了解Linux操作系统及其分支版本 3.直观上理解服务器端与桌面端版本的区别 课程实验 1.通过对CentOS和Ubuntu的演示&#xff0c;直观理解Linux与Windows的异同 课堂引入 本章内容主要为大家详细讲解Linux操作系统(以下简…...

华为OD刷题C卷 - 每日刷题 1

1、&#xff08;两数之和&#xff09;&#xff1a; 这段代码是针对力扣&#xff08;LeetCode&#xff09;上的“两数之和”问题。它提供了一个Java类Solution&#xff0c;其中包含一个方法twoSum&#xff0c;该方法接收一个整数数组nums和一个整数目标值target。目的是找出数组…...

基于ELK的日志管理【开发实践】

文章目录 一、ELK简介1.1 ELK的作用与应用1.2 ELK的组成1.3 Elasticsearch1.4 Logstash1.5 Kibana1.6 ELK架构简述1.7 基础知识1.7.1 数据格式1.7.2 正排索引和倒排索引1.7.3 全文搜索 二、ES入门---基于HTTP的使用方式&#xff08;了解&#xff09;2.1 索引操作2.1.1 创建索引…...

音视频开发—音频相关概念:数模转换、PCM数据与WAV文件详解

文章目录 前言1.模拟数字转换&#xff08;ADC&#xff09;1.1ADC的关键步骤&#xff1a; 2.数字模拟转换&#xff08;DAC&#xff09;2.1DAC 的基本流程包括&#xff1a; 3.PCM数据3.1PCM 数据的关键要素包括&#xff1a; 4.WAV文件4.1 WAV的构成4.2WAV文件的标准块结构4.3WAV的…...

Elasticsearch 8.1官网文档梳理 - 十三、Search your data(数据搜索)

Search your data 这里有两个比较有用的参数需要注意一下 Search timeout&#xff1a;设置每个分片的搜索超时时间。从集群级别可以通过 search.default_search_timeout 来设置超时时间。如果在 search.default_search_timeout 设置的时间段内未完成搜索请求&#xff0c;就会…...

笔墨挥毫如游龙 最是经典铁线篆——记著名书法家王子彬

真正的书法大家,必是经历了日积月累的求索磨炼,毕竟书法从来都不是一蹴而就的艺术,因此但凡是急功近利者,其人也是远远无法达到书入臻境的创作高度。而纵观当代书坛界内,其中王子彬先生的艺术声誉可谓是广为人知,作为一名深具传统功底的实力派书法大家,王子彬先生的取法历途无疑…...

智慧校园有哪些特征

随着科技的飞速进步&#xff0c;教育领域正经历着一场深刻的变革。智慧校园&#xff0c;作为这场变革的前沿代表&#xff0c;正在逐步重塑我们的教育理念和实践方式。它不仅仅是一个概念&#xff0c;而是一个集成了物联网、大数据、人工智能等先进技术的综合生态系统&#xff0…...

day25回溯算法part02| 216.组合总和III 17.电话号码的字母组合

216.组合总和III 题目链接/文章讲解 | 视频讲解 class Solution { public:vector<vector<int>> result;vector<int> path;int sum;void backtracking(int n, int k, int startindex) {// int sum accumulate(path.begin(), path.end(), 0);if (sum n &am…...

AWS联网和内容分发服务

概况 VPC Amazon Virtual Private Cloud (Amazon VPC) 让您能够全面地控制自己的虚拟网络环境&#xff0c;包括资源放置、连接性和安全性。首先在 AWS 服务控制台中设置 VPC。然后&#xff0c;向其中添加资源&#xff0c;例如 Amazon Elastic Compute Cloud (EC2) 和 Amazon …...

vscode设置编辑器文件自动保存

步骤 1.打开vscode的设置 2.在搜索栏输入关键字“保存”&#xff1b; 在 Files: Auto Save 设置项&#xff0c;选择自动保存的模式...

SJ705C安全帽高温预处理箱

一、仪器用途 安全帽高温预处理箱是我公司根据安全帽新国家标准检测试验要求而自主设计研发制造。是安全帽检测前做高温预处理的专用设备。 二、仪器特征 1、有PID自整定温度控制仪&#xff0c;控制准确。 2、数显计时、计温器。 3、石英灯管加热系统;。 …...

AI盒子在智慧加油站的应用

方案背景 为规范加油站作业&#xff0c;保障人民生命财产安全&#xff0c;《加油站作业安全规范》&#xff08;AQ 3010-2007&#xff09;中第五条规定&#xff1a;卸油作业基本要求&#xff0c;明确防静电、防雷电、防火、人员值守、禁止其他车辆及非工作人员进入卸油区。 痛点…...

IC开发——VCS基本用法

1. 简介 VCS是编译型verilog仿真器&#xff0c;处理verilog的源码过程如下&#xff1a; VCS先将verilog/systemverilog文件转化为C文件&#xff0c;在linux下编译链接生成可执行文件&#xff0c;在linux下运行simv即可得到仿真结果。 VCS使用步骤&#xff0c;先编译verilog源…...

MongoDB~存储引擎了解

存储引擎 存储引擎是一个数据库的核心&#xff0c;主要负责内存、磁盘里数据的管理和维护。 MongoBD的优势&#xff0c;在于其数据模型定义的灵活性、以及可拓展性。但不要忽略&#xff0c;其存储引擎也是插件式的存在&#xff0c;支持不同类型的存储引擎&#xff0c;使用不同…...

JavaScript实现粒子数字倒计时效果附完整注释

<!DOCTYPE html> <html lang="en"><head><meta charset...

Dubbo SPI(Service Provider Interface)机制深度解析

Dubbo SPI&#xff08;Service Provider Interface&#xff09;机制是Apache Dubbo框架中一项核心的技术组件&#xff0c;它超越了传统Java SPI的范畴&#xff0c;为Dubbo带来了高度的可扩展性和灵活性。在分布式服务架构日益复杂多变的今天&#xff0c;Dubbo SPI机制通过巧妙的…...

常用中间件各版本下载

常用中间件下载地址 前言分布式中间件负载均衡中间件缓存中间件数据库中间件其他中间件1、Maven下载地址2、Git下载地址2、JDK下载地址3、MySQL下载地址4、Redis下载地址5、Nacos下载地址6、Tomcat下载地址7、Nginx下载地址8、RocketMQ下载地址8、RabbitMQ下载地址8、Erlang下载…...

VsCode SSH远程设置不用重复输入密码

winR输入cmd&#xff0c;回车&#xff0c;输入 C:\Users\Administrator> ssh-keygen -t rsa -b 4096 Generating public/private rsa key pair. Enter file in which to save the key (C:\Users\Administrator/.ssh/id_rsa): Enter passphrase (empty for no passphrase): …...

【Linux】:进程切换

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux进程切换的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精…...

MongoDB CRUD操作:删除文档

MongoDB CRUD操作&#xff1a;删除文档 文章目录 MongoDB CRUD操作&#xff1a;删除文档删除集合的所有文档删除符合条件的所有文件删除第一个符合条件的文档## 在MongoDB Atlas中删除文档删除行为索引 原子性写确认 可以使用下面的方式删除MongoDB集合的文档&#xff1a; 使用…...

SpringBoot集成腾讯COS流程

1.pom.xml中添加cos配置 <!--腾讯cos --> <dependency><groupId>com.qcloud</groupId><artifactId>cos_api</artifactId><version>5.6.28</version> </dependency> 2.application.yaml中添加cos配置 # 腾讯云存储cos…...

中高级前端开发岗

定位&#xff1a; 日常迭代任务的核心研发&#xff0c;具备高质、高效完成迭代任务的能力。 素质要求&#xff1a; 业务专家或擅长某一方向技术&#xff1b;有较丰富的开发经验&#xff1b;需要具备良好的沟通和协作能力&#xff0c;能够与其他部门和团队进行有效的沟通和协…...

idea常用配置

文章目录 I 常见问题1.1 取消maven忽略文件清单1.2 源根之外的java文件1.3 idea取消所有断点1.4 idea使用非模式提交界面1.5 用Service窗口展示所有服务及端口1.6 idea编码问题(加载配置文件失败)II idea 换行后自动缩进4个空格,怎么取消?I 常见问题 1.1 取消maven忽略文件…...

Spring AOP 切面按照一定规则切片并行查询Mapper并返回

需求&#xff1a; 有时候我们在查询mapper层时&#xff0c;有时候可能由于入参数据过大或者查询的范围较大&#xff0c;导致查询性能较慢&#xff0c;此时 我们需要将原本的查询按照一定规则将查询范围进行切面&#xff0c;然后分片查询&#xff0c;最后将查询结果进行组装合并…...

【vue3|第4期】Vue3的选项式与组合式

日期&#xff1a;2024年5月30日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…...

算法训练营第四十五天 | LeetCode 1049 最后一块石头的重量II、LeetCode 494 目标和、LeetCode 474 一和零

LeetCode 1049 最后一块石头的重量 继续昨天没有详细说的01背包问题往下继续说。01背包问题是将dp从一维问题升维到二维之后会遇到的一类典型问题。dp数组自然而然地是一个横坐标表示物品序号-1&#xff0c;纵坐标表示背包重量的二维数组。01背包由一个背包是否放该物品并比照后…...

【数据结构与算法(C 语言)】栈的基本操作函数(动图演示) 及 栈的实际应用之一:进制转换

目录 1. 前言2. 结构及基本操作函数&#xff1a;2.1 栈的结构类型 Stack2.2 初始化栈 InitStack2.3 销毁栈 DestroyStack2.4 清空栈 ClearStack2.5 判断栈是否为空 StackEmpty2.6 获取stack的长度 StackLength2.7 获取栈顶元素 GetTop2.8 入栈 Push2.9 出栈 Pop2.10 访问元素2.…...

[原创]C++ 11的thread_local线程局部变量与Lambda表达式配合使用, 却引发致命的, 难以发现的冲突.

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…...

C语言-单精度和双精度浮点型

文章目录 一、遇到的问题二、解决方案三、问题根因float和double的区别&#xff1a; 总结-浮点数 一、遇到的问题 将NXP项目的代码移植到RH850F1K的项目上时&#xff0c;程序运行异常&#xff1a; u16Volt (uint16)((double)u16ADVal * (double)6.3) 执行到这一行程序就跑飞了…...

STM32学习问题总结(2)—CubeMX生成项目后串口没效果和Microlib

检查完所有的硬件和软件部分&#xff0c;最后发现&#xff0c;又是Keil的设置问题&#xff0c;啊啊啊啊 打开Keil的魔术棒&#xff0c;勾选Target的Use Microlib选项即可&#xff0c;但这并不是最佳方案 最终解决方案&#xff1a; 参考&#xff1a;http://t.csdnimg.cn/2Tjfc…...

【数据结构与算法 | 二叉树篇】二叉树的前中后序遍历(递归版本)

1. 二叉树的概念 (1). 二叉树的结构 借用了一下力扣的模板 public class TreeNode {int val;TreeNode left;TreeNode right;TreeNode() {}TreeNode(int val) { this.val val; }TreeNode(int val, TreeNode left, TreeNode right) {this.val val;this.left left;this.righ…...

Python exp用法:深入探索指数函数的奥秘

Python exp用法&#xff1a;深入探索指数函数的奥秘 在Python中&#xff0c;exp是一个非常重要的数学函数&#xff0c;它属于math模块的一部分&#xff0c;用于计算自然数e的指数。自然数e是一个无理数&#xff0c;约等于2.71828&#xff0c;它在数学、物理和工程等领域有着广…...

[有监督学习] 8.详细图解神经网络

神经网络 一直以来&#xff0c;人们都认为神经网络&#xff08;Neural Network&#xff0c;NN&#xff09;是模仿生物体的神经网络设计而成的。神经网络既可以用于回归&#xff0c;也可以用于分类&#xff0c;但在实际应用中常用于分类。基于神经网络的深 度学习因在图像识别和…...

我给线程池管理框架hippo4j找bug

1 虚拟机参数不生效 hippo4j的docker启动脚本位于 docker/docker-startup.sh 。从下图可以看到 JAVA_OPT放在了jar包名 hippo4j-server.jar之后&#xff0c;而只有项目参数才放在jar包名之后。 实际上这里JAVA_OPT中包含虚拟机参数&#xff0c;而虚拟机参数要放在jar包名之前…...

win10键盘按乱了,如何恢复?

今天键盘被宝宝给按乱了&#xff0c;好不容易给重新调整回来&#xff0c;记录备忘&#xff1a; 1、win10的asdw和方向键互换了&#xff1a; 使用Fnw键来回切换&#xff0c;OK&#xff01; 2、键盘的win键失效&#xff0c;例如&#xff1a;按winD无法显示桌面。此时&#xf…...

5.29工效学-人因工程人机交互

对于工效学这门课&#xff0c;一直都感觉很有意思&#xff0c;是一个值得再认真一点的课。可惜上课的时候效率不高&#xff0c;有感兴趣的东西课后也没有自行去拓展开来&#xff0c;前面的课我感觉还讲了比较重要的东西&#xff0c;但是&#xff0c;全忘了呢&#xff08;真的对…...

头歌数据结构与算法课程设计中-硬币找零

给定n种不同面值的硬币k_i和每种硬币的数量x_i以及一个总金额k,请编写一个程序计算最少需要几枚硬币凑出这个金额k,凑出的方案是什么? 如果凑不出则输出“凑不出” 输入描述: 第一行两个正整数,n和k 然后n行每行两个数k_i和x_i 表示k_i面值的硬币有x_i个,中间以空格分隔 输…...

Golang的内存关系

1.Page Golang的Page,在操作系统对虚拟内存管理的MMU定义的物理页有相似的定义,默认的Page为8KB 2.mSpan 多个连续的Page称之为是一个Span&#xff0c;其定义含义有操作系统的管理的页表相似 3.Size Class Size Class: 相当于 一个等级和刻度, 比如 第二等级 就代表 一个Pag…...