AI大模型探索之路-實戰篇15: Agent智能數據分析平臺之整合封裝Tools和Memory功能代碼

系列篇章💥

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智能數據分析平臺功能
AI大模型探索之路-實戰篇12: 構建互動式Agent智能數據分析平臺:實現多輪對話控制
AI大模型探索之路-實戰篇13: 從對話到報告:打造能記錄和分析的Agent智能數據分析平臺
AI大模型探索之路-實戰篇14: 集成本地Python代碼解釋器:強化Agent智能數據分析平臺


目錄

  • 系列篇章💥
  • 一、前言
  • 二、Memory功能實現之在線云盤類封裝
    • 1、創建OpenAi客戶端
    • 2、定義本地云盤文件目錄創建方法
    • 3、定義doc文檔創建方法
    • 4、定義文件內容追加方法
    • 5、定義獲取文件內容的方法
    • 6、定義清理文件內容的方法
    • 7、定義獲取文件列表的方法
    • 8、定義文件重命名的方法
    • 9、定義刪除文件的方法
    • 10、定義追加圖片的方法
    • 11、定義一個云盤文件操作類
  • 三、Memory功能實現之消息工具類封裝
    • 1、定義消息管理類
    • 2、測試-查看消息管理器
    • 3、測試-追加消息
    • 4、測試-刪除消息
    • 5、添加背景知識
  • 四、Tools功能之函數封裝
    • 1、獲取表結構基本信息(工具函數)
    • 2、提取SQL數據到python變量(輔助函數)
    • 3、python代碼解釋器(工具函數)
    • 4、function函數信息生成器(輔助函數)
    • 5、function函數調用輔助類
  • 三、結語


一、前言

在前面篇章中我們實現了Agent智能數據分析平臺中的Tools和Memory相關代碼落地實踐,本文中我們將對這兩大塊功能代碼進行整合封裝。

二、Memory功能實現之在線云盤類封裝

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 pymysql
import tiktoken
from docx import Document
import matplotlib.pyplot as plt
import seaborn as sns
import tempfile
import ast
from IPython.display import display, Markdown, Code
import shutil
import copy
from openai import  APIConnectionError,AuthenticationErroropenai.api_key = os.getenv("OPENAI_API_KEY")client = OpenAI(api_key=openai.api_key)

2、定義本地云盤文件目錄創建方法

import osdef create_or_get_folder(folder_name):"""根據項目創建云盤目錄"""base_path = "/root/autodl-tmp/iquery項目/iquery云盤"full_path = os.path.join(base_path, folder_name)# 如果目錄不存在,則創建它if not os.path.exists(full_path):os.makedirs(full_path)print(f"目錄 {folder_name} 創建成功")else:print(f"目錄 {folder_name} 已存在")return full_path
print(create_or_get_folder(folder_name = "測試函數"))

在這里插入圖片描述

3、定義doc文檔創建方法

def create_or_get_doc(folder_name, doc_name):"""創建或獲取文件路徑"""base_path = "/root/autodl-tmp/iquery項目/iquery云盤"full_path_folder=os.path.join(base_path,folder_name)file_path_doc = os.path.join(base_path+"/"+folder_name, f'{doc_name}.doc')# 檢查目錄是否存在,如果不存在則創建if not os.path.exists(full_path_folder):os.makedirs(full_path_folder)# 檢查文件是否存在if os.path.exists(file_path_doc):# 文件存在,打開并追加內容document = Document(file_path_doc)else:# 文件不存在,創建一個新的文檔對象document = Document()# 保存文檔document.save(file_path_doc)return file_path_doc
create_or_get_doc(folder_name="測試函數",doc_name="數據分析")

在這里插入圖片描述

4、定義文件內容追加方法

def append_content_in_doc(folder_name, doc_name, qa_string):""""往文件里追加內容@param folder_name=目錄名,doc_name=文件名,qa_string=追加的內容"""base_path = "/root/autodl-tmp/iquery項目/iquery云盤"## 目錄地址full_path_folder=base_path+"/"+folder_name## 文件地址full_path_doc = os.path.join(full_path_folder, doc_name)+".doc"  # 檢查目錄是否存在,如果不存在則創建if not os.path.exists(full_path_folder):os.makedirs(full_path_folder)# 檢查文件是否存在if os.path.exists(full_path_doc):# 文件存在,打開并追加內容document = Document(full_path_doc)else:# 文件不存在,創建一個新的文檔對象document = Document()# 追加內容document.add_paragraph(qa_string)# 保存文檔document.save(full_path_doc)print(f"內容已追加到 {doc_name}")

測試

my_dict = "天青色等煙雨,而我在等你"
append_content_in_doc(folder_name="測試函數",doc_name="數據分析",qa_string=my_dict)

在這里插入圖片描述

5、定義獲取文件內容的方法

## 實現根據項目和文件獲取文件內容的方法from docx import Document
import osdef get_file_content(folder_name, doc_name):"""實現根據項目名和文件名獲取文件內容的方法@param project_name:項目名,file_name:文件名@return 文件內容"""# 構建文件的完整路徑base_path = "/root/autodl-tmp/iquery項目/iquery云盤"file_path = os.path.join(folder_name, doc_name)full_path = os.path.join(base_path, file_path)+".doc"# 確保文件存在if not os.path.exists(full_path):return "文件不存在"try:# 加載文檔doc = Document(full_path)content = []# 遍歷文檔中的每個段落,并收集文本for para in doc.paragraphs:content.append(para.text)# 將所有段落文本合并成一個字符串返回return '\n'.join(content)except Exception as e:return f"讀取文件時發生錯誤: {e}"

測試

get_file_content(folder_name="測試函數",doc_name="數據分析")

6、定義清理文件內容的方法

from docx import Documentdef clear_content_in_doc(folder_name, doc_name):# 打開文檔base_path = "/root/autodl-tmp/iquery項目/iquery云盤"file_path = os.path.join(base_path+"/"+folder_name, f'{doc_name}.doc')doc = Document(file_path)# 遍歷每一個段落,設置其文本為空字符串for p in doc.paragraphs:for run in p.runs:run.text = ''# 保存修改后的文檔doc.save(file_path)print("文檔內容清除完畢")

測試

clear_content_in_doc(folder_name="測試函數",doc_name="數據分析")

7、定義獲取文件列表的方法

def list_files_in_folder(folder_name):"""列舉當前文件夾的全部文件"""base_path = "/root/autodl-tmp/iquery項目/iquery云盤"full_path = os.path.join(base_path,folder_name )file_names = [f for f in os.listdir(full_path) if os.path.isfile(os.path.join(full_path, f))]return file_names

測試

list_files_in_folder(folder_name="測試函數")

8、定義文件重命名的方法

def rename_doc(folder_name, doc_name, new_name):"""修改指定的文檔名稱"""base_path = "/root/autodl-tmp/iquery項目/iquery云盤"file_path = os.path.join(base_path+"/"+folder_name, f'{doc_name}.doc')new_file_path = os.path.join(base_path+"/"+folder_name, f'{new_name}.doc')# 重命名文件os.rename(file_path, new_file_path)return new_name

測試

rename_doc(folder_name="測試函數",doc_name="數據分析",new_name="數據可視化分析報告")

9、定義刪除文件的方法

def delete_all_files_in_folder(folder_name):"""刪除某文件夾內全部文件"""# 定義要刪除的目錄路徑base_path = "/root/autodl-tmp/iquery項目/iquery云盤"full_path = os.path.join(base_path,folder_name)# 遍歷整個目錄for filename in os.listdir(full_path):# 構造文件或者文件夾的絕對路徑file_path = os.path.join(full_path, filename)try:# 如果是文件,則刪除文件if os.path.isfile(file_path) or os.path.islink(file_path):os.unlink(file_path)# 如果是文件夾,則刪除文件夾elif os.path.isdir(file_path):shutil.rmtree(file_path)print("文件已清除完畢")except Exception as e:print('Failed to delete %s. Reason: %s' % (file_path, e))

測試

delete_all_files_in_folder(folder_name = "測試函數")

10、定義追加圖片的方法

	from docx import Document
import matplotlib.pyplot as plt
import os
import tempfiledef append_img_in_doc(folder_name, doc_name, img):""""往文件里追加圖片@param folder_name=目錄名,doc_name=文件名,img=圖片對象,數據類型為matplotlib.figure.Figure對象"""base_path = "/root/autodl-tmp/iquery項目/iquery云盤"## 目錄地址full_path_folder=base_path+"/"+folder_name## 文件地址full_path_doc = os.path.join(full_path_folder, doc_name)+".doc"# 檢查目錄是否存在,如果不存在則創建if not os.path.exists(full_path_folder):os.makedirs(full_path_folder)# 檢查文件是否存在if os.path.exists(full_path_doc):print(full_path_doc)# 文件存在,打開并追加內容document = Document(full_path_doc)else:# 文件不存在,創建一個新的文檔對象document = Document()# 追加圖片# 將matplotlib的Figure對象保存為臨時圖片文件with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as tmpfile:img.savefig(tmpfile.name, format='png')# 將圖片插入到.docx文檔中document.add_picture(tmpfile.name)# 保存文檔document.save(full_path_doc)print(f"圖片已追加到 {doc_name}")
import matplotlib.pyplot as plt# 創建一個圖形
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4, 5])

在這里插入圖片描述

append_img_in_doc(folder_name="測試函數",doc_name="數據分析",img=fig)

在這里插入圖片描述

11、定義一個云盤文件操作類

class CloudFile():"""用于操作云盤文件"""def __init__(self, project_name, part_name, doc_content = None):# 項目名稱,即項目文件夾名稱self.project_name = project_name# 項目某部分名稱,即項目文件名稱self.part_name = part_name# 項目文件夾ID# 若項目文件夾ID為空,則獲取項目文件夾IDfolder_path=create_or_get_folder(folder_name=project_name)# 創建時獲取當前項目中其他文件名稱列表self.doc_list = list_files_in_folder(folder_name=project_name)file_path = create_or_get_doc(folder_name=project_name, doc_name=part_name)# 項目文件具體內容,相當于多輪對話內容self.doc_content = doc_content# 若初始content不為空,則將其追加入文檔內if doc_content != None:append_content_in_doc(folder_name=project_name, doc_name=part_name, dict_list=doc_content)def get_doc_content(self):"""根據項目某文件的文件ID,獲取對應的文件內容"""     self.doc_content = get_file_content(folder_name=self.project_name, doc_name=self.part_name)return self.doc_contentdef append_doc_content(self, content):"""根據項目某文件的文件ID,追加文件內容"""  append_content_in_doc(folder_name=self.project_name,doc_name=self.part_name, dict_list=content)def clear_content(self):"""清空某文件內的全部內容"""  clear_content_in_doc(folder_name=self.project_name, doc_name=self.part_name)def delete_all_files(self):"""刪除當前項目文件夾內的全部文件"""  delete_all_files_in_folder(folder_name=self.project_name)def update_doc_list(self):"""更新當前項目文件夾內的全部文件名稱"""self.doc_list = list_files_in_folder(folder_name=self.project_name)def rename_doc(self, new_name):"""修改當前文件名稱"""self.part_name = rename_doc_in_drive(folder_name=self.project_name, doc_name=self.part_name, new_name=new_name)

本地存儲測試

c1 = CloudFile(project_name='測試項目', part_name='測試文檔1')

在這里插入圖片描述

三、Memory功能實現之消息工具類封裝

1、定義消息管理類

class MessageManager():"""MessageManager,用于創建Chat模型能夠接收和解讀的messages對象。該對象是原始Chat模型接收的\messages對象的更高級表現形式,MessageManager類對象將字典類型的list作為其屬性之一,同時還能\能區分系統消息和歷史對話消息,并且能夠自行計算當前對話的token量,并執能夠在append的同時刪\減最早對話消息,從而能夠更加順暢的輸入大模型并完成多輪對話需求。"""def __init__(self, system_content_list=[], question='你好。',tokens_thr=None, project=None):self.system_content_list = system_content_list# 系統消息文檔列表,相當于外部輸入文檔列表system_messages = []# 除系統消息外歷史對話消息history_messages = []# 用于保存全部消息的listmessages_all = []# 系統消息字符串system_content = ''# 歷史消息字符串,此時為用戶輸入信息history_content = question# 系統消息+歷史消息字符串content_all = ''# 輸入到messages中系統消息個數,初始情況為0num_of_system_messages = 0# 全部信息的token數量all_tokens_count = 0encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")# 將外部輸入文檔列表依次保存為系統消息if system_content_list != []:      for content in system_content_list:system_messages.append({"role": "system", "content": content})# 同時進行全文檔拼接system_content += content# 計算系統消息tokensystem_tokens_count = len(encoding.encode(system_content))# 拼接系統消息messages_all += system_messages# 計算系統消息個數num_of_system_messages = len(system_content_list)# 若存在最大token數量限制if tokens_thr != None:# 若系統消息超出限制if system_tokens_count >= tokens_thr:print("system_messages的tokens數量超出限制,當前系統消息將不會被輸入模型")            # 刪除系統消息system_messages = []messages_all = []# 系統消息個數清零num_of_system_messages = 0# 系統消息token數清零system_tokens_count = 0all_tokens_count += system_tokens_count# 創建首次對話消息history_messages = [{"role": "user", "content": question}]# 創建全部消息列表messages_all += history_messages# 計算用戶問題tokenuser_tokens_count = len(encoding.encode(question))# 計算總token數all_tokens_count += user_tokens_count# 若存在最大token限制if tokens_thr != None:# 若超出最大token限制if all_tokens_count >= tokens_thr:print("當前用戶問題的tokens數量超出限制,該消息無法被輸入到模型中")  # 同時清空系統消息和用戶消息history_messages = []system_messages = []messages_all = []num_of_system_messages = 0all_tokens_count = 0# 全部messages信息self.messages = messages_all# system_messages信息self.system_messages = system_messages# user_messages信息self.history_messages = history_messages# messages信息中全部content的token數量self.tokens_count = all_tokens_count# 系統信息數量self.num_of_system_messages = num_of_system_messages# 最大token數量閾值self.tokens_thr = tokens_thr# token數計算編碼方式self.encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")# message掛靠的項目self.project = project# 刪除部分對話信息def messages_pop(self, manual=False, index=None):def reduce_tokens(index):drop_message = self.history_messages.pop(index)self.tokens_count -= len(self.encoding.encode(str(drop_message)))if self.tokens_thr is not None:while self.tokens_count >= self.tokens_thr:reduce_tokens(-1)if manual:if index is None:reduce_tokens(-1)elif 0 <= index < len(self.history_messages) or index == -1:reduce_tokens(index)else:raise ValueError("Invalid index value: {}".format(index))# 更新messagesself.messages = self.system_messages + self.history_messages# 增加部分對話信息def messages_append(self, new_messages):# 若是單獨一個字典,或JSON格式字典if type(new_messages) is dict or type(new_messages) is openai.types.chat.chat_completion_message.ChatCompletionMessage:self.messages.append(new_messages)self.tokens_count += len(self.encoding.encode(str(new_messages)))# 若新消息也是MessageManager對象elif isinstance(new_messages, MessageManager):self.messages += new_messages.messagesself.tokens_count += new_messages.tokens_count# 重新更新history_messagesself.history_messages = self.messages[self.num_of_system_messages: ]# 再執行pop,若有需要,則會刪除部分歷史消息self.messages_pop()# 復制信息def copy(self):# 創建一個新的 MessageManager 對象,復制所有重要的屬性system_content_str_list = [message["content"] for message in self.system_messages]new_obj = MessageManager(system_content_list=copy.deepcopy(system_content_str_list),  # 使用深復制來復制系統消息question=self.history_messages[0]["content"] if self.history_messages else '',tokens_thr=self.tokens_thr)# 復制任何其他需要復制的屬性new_obj.history_messages = copy.deepcopy(self.history_messages)  # 使用深復制來復制歷史消息new_obj.messages = copy.deepcopy(self.messages)  # 使用深復制來復制所有消息new_obj.tokens_count = self.tokens_countnew_obj.num_of_system_messages = self.num_of_system_messagesreturn new_obj# 增加系統消息def add_system_messages(self, new_system_content):system_content_list = self.system_content_listsystem_messages = []# 若是字符串,則將其轉化為listif type(new_system_content) == str:new_system_content = [new_system_content]system_content_list.extend(new_system_content)new_system_content_str = ''for content in new_system_content:new_system_content_str += contentnew_token_count = len(self.encoding.encode(str(new_system_content_str)))self.tokens_count += new_token_countself.system_content_list = system_content_listfor message in system_content_list:system_messages.append({"role": "system", "content": message})self.system_messages = system_messagesself.num_of_system_messages = len(system_content_list)self.messages = system_messages + self.history_messages# 再執行pop,若有需要,則會刪除部分歷史消息self.messages_pop()# 刪除系統消息def delete_system_messages(self):system_content_list = self.system_content_listif system_content_list != []:system_content_str = ''for content in system_content_list:system_content_str += contentdelete_token_count = len(self.encoding.encode(str(system_content_str)))self.tokens_count -= delete_token_countself.num_of_system_messages = 0self.system_content_list = []self.system_messages = []self.messages = self.history_messages# 清除對話消息中的function消息def delete_function_messages(self):# 用于刪除外部函數消息history_messages = self.history_messages# 從后向前迭代列表for index in range(len(history_messages) - 1, -1, -1):message = history_messages[index]## 這兒估計有問題if message.get("function_call") or message.get("role") == "function":self.messages_pop(manual=True, index=index)

2、測試-查看消息管理器

msg1 = MessageManager()
msg1.system_messages

在這里插入圖片描述

3、測試-追加消息

msg1.history_messages

在這里插入圖片描述

msg1.messages_append({"role": "user", "content": "你好,有什么可以幫你?"})
msg1.history_messages

在這里插入圖片描述

4、測試-刪除消息

msg1.messages_pop(manual=True, index=-1)
msg1.history_messages

在這里插入圖片描述

5、添加背景知識

# 數據字典文件
with open('/root/autodl-tmp/iquery項目/data/數據字典/iquery數據字典.md', 'r', encoding='utf-8') as f:data_dictionary = f.read()
# 數據分析報告編寫專家文檔
with open('/root/autodl-tmp/iquery項目/data/業務知識/本公司數據分析師業務介紹.md', 'r', encoding='utf-8') as f:da_instruct = f.read()
msg2 = MessageManager(system_content_list=[data_dictionary, da_instruct])
msg2.system_messages

輸出
在這里插入圖片描述

四、Tools功能之函數封裝

1、獲取表結構基本信息(工具函數)

定義一個SQL工具函數,用于獲取表結構信息,作為大模型生成SQL的背景知識

## mysql hive sparksql
def sql_inter(sql_query, g='globals()'):"""用于獲取iquery數據庫中各張表的有關相關信息,\核心功能是將輸入的SQL代碼傳輸至iquery數據庫所在的MySQL環境中進行運行,\并最終返回SQL代碼運行結果。需要注意的是,本函數是借助pymysql來連接MySQL數據庫。:param sql_query: 字符串形式的SQL查詢語句,用于執行對MySQL中iquery數據庫中各張表進行查詢,并獲得各表中的各類相關信息:param g: g,字符串形式變量,表示環境變量,無需設置,保持默認參數即可: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)
sql_inter(sql_query='SELECT COUNT(*) FROM user_demographics;', g=globals())

2、提取SQL數據到python變量(輔助函數)

定義一個輔助函數,用于將查詢到的記錄提取保存到本地python變量中

def extract_data(sql_query,df_name,g='globals()'):"""用于借助pymysql,將MySQL中的iquery數據庫中的表讀取并保存到本地Python環境中。:param sql_query: 字符串形式的SQL查詢語句,用于提取MySQL中iquery數據庫中的某張表。:param df_name: 將MySQL數據庫中提取的表格進行本地保存時的變量名,以字符串形式表示。:param g: g,字符串形式變量,表示環境變量,無需設置,保持默認參數即可:return:表格讀取和保存結果"""mysql_pw = "iquery_agent"connection = pymysql.connect(host='localhost',  # 數據庫地址user='iquery_agent',  # 數據庫用戶名passwd=mysql_pw,  # 數據庫密碼db='iquery',  # 數據庫名charset='utf8'  # 字符集選擇utf8)globals()[df_name] = pd.read_sql(sql_query, connection)return "已成功完成%s變量創建" % df_name
extract_data(sql_query = 'SELECT * FROM user_demographics;', df_name = 'user_demographics_df', g = globals())

在這里插入圖片描述

從python變量中取出數據查看

user_demographics_df.head()

在這里插入圖片描述

3、python代碼解釋器(工具函數)

def python_inter(py_code,g='globals()'):"""用于對iquery數據庫中各張數據表進行查詢和處理,并獲取最終查詢或處理結果。:param py_code: 字符串形式的Python代碼,用于執行對iquery數據庫中各張數據表進行操作:param g: g,字符串形式變量,表示環境變量,無需設置,保持默認參數即可:return:代碼運行的最終結果"""    # 添加圖片對象,如果存在繪圖代碼,則創建fig對象py_code = insert_fig_object(py_code)global_vars_before = set(globals().keys())try:exec(py_code, globals())except Exception as e:return str(e)global_vars_after = set(globals().keys())new_vars = global_vars_after - global_vars_beforeif new_vars:result = {var: globals()[var] for var in new_vars}return str(result)else:try:return str(eval(py_code, globals()))except Exception as e:return "已經順利執行代碼"

檢查圖形對象,賦值給fig(方便通過全局變量fig進行統一的繪圖對象操作)

def insert_fig_object(code_str,g='globals()'):"""為圖片創建fig對象:param g: g,字符串形式變量,表示環境變量,無需設置,保持默認參數即可"""#print("開始畫圖了")global fig# 檢查是否已存在 fig 對象的創建if 'fig = plt.figure' in code_str or 'fig, ax = plt.subplots()' in code_str:return code_str  # 如果存在,則返回原始代碼字符串# 定義可能的庫別名和全名plot_aliases = ['plt.', 'matplotlib.pyplot.','plot']sns_aliases = ['sns.', 'seaborn.']# 尋找第一次出現繪圖相關代碼的位置first_plot_occurrence = min((code_str.find(alias) for alias in plot_aliases + sns_aliases if code_str.find(alias) >= 0), default=-1)# 如果找到繪圖代碼,則在該位置之前插入 fig 對象的創建if first_plot_occurrence != -1:plt_figure_index = code_str.find('plt.figure')if plt_figure_index != -1:# 尋找 plt.figure 后的括號位置,以確定是否有參數closing_bracket_index = code_str.find(')', plt_figure_index)# 如果找到了 plt.figure(),則替換為 fig = plt.figure()modified_str = code_str[:plt_figure_index] + 'fig = ' + code_str[plt_figure_index:closing_bracket_index + 1] + code_str[closing_bracket_index + 1:]else:modified_str = code_str[:first_plot_occurrence] + 'fig = plt.figure()\n' + code_str[first_plot_occurrence:]return modified_strelse:return code_str  # 如果沒有找到繪圖代碼,則返回原始代碼字符串

圖形繪制代碼測試

import matplotlib.pyplot as plt
# 數據
categories = ['Category 1', 'Category 2', 'Category 3', 'Category 4']
values = [4, 7, 1, 8]# 創建 Figure 對象
fig, ax = plt.subplots()# 在 Axes 對象 ax 上創建條形圖
ax.bar(categories, values)# 添加標題和標簽
ax.set_title('Bar Chart Example')
ax.set_xlabel('Categories')
ax.set_ylabel('Values')# 顯示圖表
plt.show()

在這里插入圖片描述

insert_fig_object方法測試

code_string = """
import matplotlib.pyplot as plt
# 數據
categories = ['Category 1', 'Category 2', 'Category 3', 'Category 4']
values = [4, 7, 1, 8]# 創建 Figure 對象
fig, ax = plt.subplots()# 在 Axes 對象 ax 上創建條形圖
ax.bar(categories, values)# 添加標題和標簽
ax.set_title('Bar Chart Example')
ax.set_xlabel('Categories')
ax.set_ylabel('Values')# 顯示圖表
plt.show()
"""
print(insert_fig_object(code_str = code_string, g=globals()))

在這里插入圖片描述

python_inter(py_code = code_string, g=globals())

在這里插入圖片描述

查看fig對象

在這里插入圖片描述

4、function函數信息生成器(輔助函數)

定義一個用于生成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

5、function函數調用輔助類

負責承接外部函數調用時相關功能支持。
類屬性包括外部函數列表、外部函數參數說明列表、以及調用方式說明三項。

class AvailableFunctions():"""外部函數類,主要負責承接外部函數調用時相關功能支持。類屬性包括外部函數列表、外部函數參數說明列表、以及調用方式說明三項。"""def __init__(self, functions_list=[], functions=[], function_call="auto"):self.functions_list = functions_listself.functions = functionsself.functions_dic = Noneself.function_call = None# 當外部函數列表不為空、且外部函數參數解釋為空時,調用auto_functions創建外部函數解釋列表if functions_list != []:self.functions_dic = {func.__name__: func for func in functions_list}self.function_call = function_callif functions == []:self.functions = auto_functions(functions_list)# 增加外部函數方法,并且同時可以更換外部函數調用規則def add_function(self, new_function, function_description=None, function_call_update=None):self.functions_list.append(new_function)self.functions_dic[new_function.__name__] = new_functionif function_description == None:new_function_description = auto_functions([new_function])self.functions.append(new_function_description)else:self.functions.append(function_description)if function_call_update != None:self.function_call = function_call_update
af = AvailableFunctions(functions_list=[sql_inter, extract_data, python_inter])
af.functions_list

在這里插入圖片描述

af.functions_dic

在這里插入圖片描述

af.function_call

在這里插入圖片描述

af.functions

輸出:

[{'type': 'function','function': {'name': 'sql_inter','description': '用于獲取iquery數據庫中各張表的有關相關信息,核心功能是將輸入的SQL代碼傳輸至iquery數據庫所在的MySQL環境中進行運行,并最終返回SQL代碼運行結果。','parameters': {'type': 'object','properties': {'sql_query': {'type': 'string','description': '字符串形式的SQL查詢語句,用于執行對MySQL中iquery數據庫中各張表進行查詢,并獲得各表中的各類相關信息。'},'g': {'type': 'string','description': 'g,字符串形式變量,表示環境變量,無需設置,保持默認參數即可。'}},'required': ['sql_query', 'g']}}},{'type': 'function','function': {'name': 'extract_data','description': '用于借助pymysql,將MySQL中的iquery數據庫中的表讀取并保存到本地Python環境中。','parameters': {'type': 'object','properties': {'sql_query': {'type': 'string','description': '字符串形式的SQL查詢語句,用于提取MySQL中iquery數據庫中的某張表。'},'df_name': {'type': 'string','description': '將MySQL數據庫中提取的表格進行本地保存時的變量名,以字符串形式表示。'},'g': {'type': 'string', 'description': 'g,字符串形式變量,表示環境變量,無需設置,保持默認參數即可'}},'required': ['sql_query', 'df_name']}}},{'type': 'function','function': {'name': 'python_inter','description': '用于對iquery數據庫中各張數據表進行查詢和處理,并獲取最終查詢或處理結果。','parameters': {'$schema': 'http://-schema.org/draft-07/schema#','type': 'object','properties': {'py_code': {'type': 'string','description': '字符串形式的Python代碼,用于執行對iquery數據庫中各張數據表進行操作'},'g': {'type': 'string', 'description': 'g,字符串形式變量,表示環境變量,無需設置,保持默認參數即可'}},'required': ['py_code', 'g']}}}]

三、結語

本文中我們封裝落地了Agent智能數據分析平臺中的Tools和Memory相關代碼,下一篇章中我將落地實踐Agent智能數據分析平臺的核心模塊Plan,探索發掘人類意圖,優化整個決策流程。

在這里插入圖片描述

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

😎 作者介紹:我是尋道AI小兵,資深程序老猿,從業10年+、互聯網系統架構師,目前專注于AIGC的探索。
📖 技術交流:建立有技術交流群,可以掃碼👇 加入社群,500本各類編程書籍、AI教程、AI工具等你領取!
如果文章內容對您有所觸動,別忘了點贊、?關注,收藏!加入我,讓我們攜手同行AI的探索之旅,一起開啟智能時代的大門!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/22048.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/22048.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/22048.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

模式識別判斷題

貝葉斯估計的方法類似于貝葉斯決策&#xff0c;也需要定義損失函數。&#xff08;正確&#xff09; 解釋&#xff1a;貝葉斯估計是一種基于貝葉斯定理的參數估計方法&#xff0c;它在估計參數時考慮了參數的先驗分布。與貝葉斯決策類似&#xff0c;貝葉斯估計也需要定義損失函數…

46.ThreadPoolExcutor接口

線程池狀態 ThreadPoolExcutor使用int高3位來表示線程池狀態&#xff0c;低29位表示線程數量 狀態高三位接收新任務處理阻塞隊列任務說明RUNNING111YYSHUTDOWN000NY不會接收新任務&#xff0c;但會處理阻塞隊列剩余任務&#xff0c;比較溫和&#xff0c;已經提交的任務都會執…

15.1 測試-重要性與testing包

1. 測試的重要性 1.1 單元測試 單元測試是針對一小部分代碼進行獨立地測試。 單元測試的對象通常是單個函數或方法&#xff0c;而要測試的是它在接受給定的輸入后&#xff0c;能否產生符合預期的輸出。 單元測試的作用主要表現在以下兩個方面&#xff1a; 驗證程序的最小…

C++ STL-迭代器函數對象適配器

目錄 一.迭代器 二. 函數對象 三. 適配器 一.迭代器 是一種通用的指針類型&#xff0c;可以用來遍歷 STL 容器中的元素。 具有以下作用和意義&#xff1a; 提供一種通用的方式來訪問容器中的元素。允許對不同類型的容器進行統一的操作。增強了代碼的靈活性和可擴展性。 一…

The Best Toolkit 最好用的工具集

The Best Toolkit 工欲善其事&#xff0c;必先利其器&#xff0c;整理過往工作與生活中遇到的最好的工具軟件 PDF合并等 PDF24 Tools PDF查看器 SumatraPDF 可以使用黑色來查看&#xff0c;相對不傷眼睛&#xff0c;也有電子書相關的閱讀器 Kindle pdf裁邊工具 briss 軟件卸載…

【C++題解】1085 - 尋找雷劈數

問題&#xff1a;1085 - 尋找雷劈數 類型&#xff1a;for循環 題目描述&#xff1a; 把整數 3025 從中剪開分為 30 和 25 兩個數&#xff0c;此時再將這兩數之和平方&#xff0c;計算結果又等于原數。 (3025)(3025)55553025 &#xff0c;這樣的數叫“雷劈數”。 求所有符合這…

Photoshop版本選擇及系統要求

1、ps2018cc/2020cc版本 適合新手&#xff0c;增加了很多智能化操作&#xff0c;非常方便好上手。 2020&#xff1a; 2、ps2015版本 cc2015版本不論是功能還是硬件上&#xff0c;都是不二選擇&#xff0c;適合于配置較低的電腦&#xff0c;該有的基本功能它都有。 3、2021/2…

std::numeric_limits::max和宏定義重復報錯問題

問題描述 今天在編譯Beckhoff ADS開源組件的時候發現編譯報錯&#xff0c;報錯代碼如下 long AdsDevice::ReadReqEx2(uint32_t group, uint32_t offset, size_t length, void* buffer, uint32_t* bytesRead) const {if (length > std::numeric_limits<uint32_t>::ma…

Algorand 的復興之路:改變游戲規則,打造 RWA 第一公鏈

TLDR 發布 AlgoKit 2.0&#xff0c;支持 Python 原生語言&#xff0c;打造開發者友好的開發環境&#xff0c;Algorand 的開發者社區規模迅速擴大。 升級共識激勵機制&#xff0c;用 ALGO 獎勵共識節點參與共識的執行&#xff0c;增加 ALGO 的應用場景&#xff0c;同時進一步確…

GB28181的主動、被動的含義

GB28181有點象視頻會議&#xff1a; 終端通過SIP登錄服務器。管理員點擊某個終端&#xff0c;進行視頻。 就是這個主動、被動沒有聽說。于是問了同事&#xff0c;他說&#xff1a; 主動被動是從服務器角度來看的。所謂被動&#xff0c;就是服務器開一個端口&#xff0c;被動接…

鋼結構乙級資質延期,企業如何降低經營風險

當企業面臨鋼結構乙級資質延期時&#xff0c;為了降低經營風險&#xff0c;可以采取以下措施&#xff1a; 1. 提前規劃與準備 資質延續規劃&#xff1a;在資質到期前&#xff0c;提前規劃資質延續的相關工作&#xff0c;包括準備所需材料、明確流程和時間節點等。 項目評估&…

js去重的幾種方式

在JavaScript中&#xff0c;有多種方式可以實現數組去重。以下是幾種常見的方式&#xff1a; 使用Set數據結構&#xff1a;使用Set可以快速實現數組去重&#xff0c;Set會自動排除重復的元素。例如&#xff1a; const arr [1, 2, 3, 3, 4, 4, 5]; const uniqueArr [...new S…

如何從官網下載 mysql 二進制安裝包

一.下載二進行包 1. 官網網址: https://www.mysql.com/ 如圖所示進入官網 2. 點擊 DOWNLOADS ,進入如下圖 在該頁面找到 MySQL Community (GPL) Downloads 點進去 如上圖頁面&#xff0c;找到 MySQL Community Server 在點進去 下載 linux 通用版 點擊最下面 Compressed …

(十四)統計學基礎練習題八(選擇題T351-400)

本文整理了統計學基礎知識相關的練習題&#xff0c;共50道&#xff0c;適用于想鞏固統計學基礎或備考的同學。來源&#xff1a;如荷學數據科學題庫&#xff08;技術專項-統計學三&#xff09;。序號之前的題請看往期文章。 351&#xff09; 352&#xff09; 353&#xff09; 3…

C++vector部分實現及感悟

myvector.h #pragma once #include<assert.h> #include<iostream> #include<vector> using namespace std; namespace bit {template<class T>//必須使用typename場景\template<typename T>與template<class T>一般情況下這兩個通用&#…

Jmeter實戰教程入門講解

前言 通過前面對Jmeter元件的講解&#xff0c;大家應該都知道常用元件的作用和使用了。編寫Jmeter腳本前我們需要知道Jmeter元件的執行順序&#xff0c;可以看看我這篇性能測試學習之路&#xff08;三&#xff09;—初識Jmeter來了解下。下面我將以工作中的一個簡單的實例帶大…

Flutter 中的 TableCell 小部件:全面指南

Flutter 中的 TableCell 小部件&#xff1a;全面指南 Flutter 是一個功能強大的 UI 框架&#xff0c;由 Google 開發&#xff0c;允許開發者使用 Dart 語言構建跨平臺的移動、Web 和桌面應用。在 Flutter 的豐富組件庫中&#xff0c;TableCell 是一個用于創建表格單元格的組件…

企業打款驗證API在Java、Python、PHP中的使用教程

隨著企業銀行賬號數量的增加和銀行間的連接方式不斷豐富&#xff0c;企業在進行資金交易時需要確保所填寫的收款方賬戶信息的準確性和合法性&#xff0c;以避免資金損失和風險。然而&#xff0c;由于銀行數量眾多、地域分布廣泛&#xff0c;不同銀行間的賬戶驗證機制和信息交互…

vue前端實現頁面禁止縮放 前端適配問題處理 前端項目多端適配解決方案

在前端項目中,如果一個系統頁面可以縮放可能會導致多種異常情況,這些異常情況涉及到頁面布局、元素尺寸、事件觸發、響應式設計和用戶體驗等方面。 1.布局錯亂:頁面元素在縮放后可能會出現錯位、重疊或部分隱藏的情況,導致頁面布局混亂,影響用戶對頁面內容的理解和操作。這…

【云原生】kubernetes中secret原理詳解與應用實戰

?? 歡迎大家來到景天科技苑?? &#x1f388;&#x1f388; 養成好習慣&#xff0c;先贊后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者簡介&#xff1a;景天科技苑 &#x1f3c6;《頭銜》&#xff1a;大廠架構師&#xff0c;華為云開發者社區專家博主&#xff0c;…