用於處理時間序列和大數據框的人工智慧代理

完全使用 Python 和 Ollama 從零開始建置(無需 GPU,無需 API 金鑰)

ㄧㄧㄧ

智能體是由大型語言模型 (LLM) 驅動的人工智慧系統,能夠推理自身目標並採取行動以實現最終目標。它們的設計目的不僅在於回應查詢,還在於組織一系列操作,包括資料處理(例如資料框和時間序列)。這種能力使得資料分析的存取更加普及,從而在現實世界中廣泛應用,例如自動產生報告、執行無程式碼查詢以及支援資料清洗和處理。

代理可以透過兩種不同的方式與資料框進行互動:

  • عنطريق 自然語言 大型語言模型(LLM)將表格讀取為文字字串,並嘗試根據其知識庫來理解它。
  • عنطريق 建立和執行程式碼 代理啟動工具,將資料集作為物件進行處理。

透過將自然語言處理 (NLP) 的強大功能與程式碼執行的精確性相結合,人工智慧代理使更廣泛的用戶能夠與複雜的資料集進行互動並提取有價值的見解。

在本教程中,我將解釋如何 使用人工智慧 (AI) 代理程式處理資料框和時間序列我將提供一些有用的 Python 程式碼,可以輕鬆應用於其他類似情況(只需複製、貼上和運行),並且我會用註釋解釋每一行程式碼,以便您可以重現此範例(文章末尾有完整程式碼的連結)。

 

準備

讓我們開始準備。 奧拉馬 (pip install ollama==0.4.7該庫允許用戶在本地運行大型開源語言模型,無需雲端服務,從而更好地控制資料隱私和效能。由於它在本地運行,因此不會有任何對話資料離開您的裝置。

首先,你需要下載 奧拉馬 來自網站。

接下來,在裝置的命令提示字元中,使用命令下載您選擇的大型語言模型 (LLM)。我將使用 奎文 阿里巴巴自家的產品,因為它既聰明又輕巧。

下載完成後,您就可以切換到 Python 並開始編寫程式碼了。

import ollama
llm = "qwen2.5"

讓我們來試試大語言模型:

stream = ollama.generate(model=llm, prompt='''what time is it?''', stream=True)
for chunk in stream:
    print(chunk['response'], end='', flush=True)

時間序列

時間序列是指在一段時間內測量的一系列數據點,常用於分析和預測。它使我們能夠了解變數隨時間的變化情況,並用於識別趨勢和季節性模式。 時間序列 一款功能強大的統計分析與預測工具。

我將建立一個資料集 時間序列 僅用作範例的偽造文件。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

## create data
np.random.seed(1) #<--for reproducibility
length = 30
ts = pd.DataFrame(data=np.random.randint(low=0, high=15, size=length),
                  columns=['y'],
                  index=pd.date_range(start='2023-01-01', freq='MS', periods=length).strftime('%Y-%m'))

## plot
ts.plot(kind="bar", figsize=(10,3), legend=False, color="black").grid(axis='y')

通常,資料集包含 時間序列 結構非常簡單,主變數作為列,時間作為索引。

在將其轉換為文字字串之前,我想確保所有內容都放在一列下,這樣我們就不會丟失任何資訊。

dtf = ts.reset_index().rename(columns={"index":"date"})
dtf.head()

然後,必須更改資料類型。 從 DataFrame 到字典.

data = dtf.to_dict(orient='records')
data[0:5]

最後, 從字典到字串.

str_data = "\n".join([str(row) for row in data])
str_data

現在我們有了文字字串,我們可以 將其納入指南中 任何語言模型都能處理它。當你將資料集貼到提示符號中時,它會讀取: 大型語言模型(LLM) 資料以純文字形式處理,但仍可以根據訓練過程中觀察到的模式來理解其結構和意義。

prompt = f'''
Analyze this dataset, it contains monthly sales data of an online retail product:
{str_data}
'''

我們可以輕鬆地與…展開對話 大型語言模型(LLM)請注意,目前這還不是一個智能體,因為它沒有任何工具;我們只使用了語言模型。雖然它不像計算機那樣處理數字, 大型語言模型(LLM) 它可以識別列名、基於時間的模式、趨勢和異常值,尤其適用於較小的資料集。它可以模擬分析並解釋結果,但由於它不像代理那樣執行程式碼,因此無法獨立進行精確計算。

messages = [{"role":"system", "content":prompt}]

while True:
    ## User
    q = input('🙂 >')
    if q == "quit":
        break
    messages.append( {"role":"user", "content":q} )
   
    ## Model
    agent_res = ollama.chat(model=llm, messages=messages, tools=[])
    res = agent_res["message"]["content"]
   
    ## Response
    print("👽 >", f"\x1b[1;30m{res}\x1b[0m")
    messages.append( {"role":"assistant", "content":res} )

認出 大型語言模型(LLM) 他理解這些數字和整體背景,就像他理解一個食譜或一行程式碼一樣。

如您所見,使用 大型語言模型(LLM) 分析 時間序列 它非常適合快速獲取資訊和展開對話。

代理人

大型語言模型(LLM)擅長產生想法和探索初始概念,而智能體則可以執行程式碼。因此,它們可以處理更複雜的任務,例如繪圖、預測和異常檢測。那麼,就讓我們來創建工具吧。

有時,處理“最終答案作為工具 效率更高。例如,如果一個智能體執行多個操作來產生中間結果,那麼最終響應可以被視為將所有這些資訊整合為一個連貫答案的工具。透過這種設計方式,您可以實現對結果的更高程度的自訂和控制。

def final_answer(text:str) -> str:
    return text

tool_final_answer = {'type':'function', 'function':{
  'name': 'final_answer',
  'description': 'Returns a natural language response to the user',
  'parameters': {'type': 'object',
                'required': ['text'],
                'properties': {'text': {'type':'str', 'description':'natural language response'}}
}}}

final_answer(text="hi")

然後, 編碼工具.

import io
import contextlib

def code_exec(code:str) -> str:
    output = io.StringIO()
    with contextlib.redirect_stdout(output):
        try:
            exec(code)
        except Exception as e:
            print(f"Error: {e}")
    return output.getvalue()

tool_code_exec = {'type':'function', 'function':{
  'name': 'code_exec',
  'description': 'Execute python code. Use always the function print() to get the output.',
  'parameters': {'type': 'object',
                'required': ['code'],
                'properties': {
                    'code': {'type':'str', 'description':'code to execute'},
}}}}

code_exec("from datetime import datetime; print(datetime.now().strftime('%H:%M'))")

此外,我還會補充一些 實用功能 使用該工具並運行代理程式。

dic_tools = {"final_answer":final_answer, "code_exec":code_exec}

# Utils
def use_tool(agent_res:dict, dic_tools:dict) -> dict:
    ## use tool
    if "tool_calls" in agent_res["message"].keys():
        for tool in agent_res["message"]["tool_calls"]:
            t_name, t_inputs = tool["function"]["name"], tool["function"]["arguments"]
            if f := dic_tools.get(t_name):
                ### calling tool
                print('🔧 >', f"\x1b[1;31m{t_name} -> Inputs: {t_inputs}\x1b[0m")
                ### tool output
                t_output = f(**tool["function"]["arguments"])
                print(t_output)
                ### final res
                res = t_output
            else:
                print('🤬 >', f"\x1b[1;31m{t_name} -> NotFound\x1b[0m")
    ## don't use tool
    if agent_res['message']['content'] != '':
        res = agent_res["message"]["content"]
        t_name, t_inputs = '', ''
    return {'res':res, 'tool_used':t_name, 'inputs_used':t_inputs}

當智能體嘗試解決任務時,我希望它能夠記錄使用的工具、嘗試的輸入以及獲得的結果。只有當模型準備好給出最終答案時,這個過程才應該停止。

關於編碼工具,我注意到代理傾向於在每一步重新建立資料框。因此,我將使用 記憶強化 提醒模型資料集確實存在。這是引發預期行為的常用策略。最終,記憶強化技術有助於實現更有意義、更有效的互動。

# Start a chat
messages = [{"role":"system", "content":prompt}]
memory = '''
The dataset already exists and it's called 'dtf', don't create a new one.
'''
while True:
    ## User
    q = input('🙂 >')
    if q == "quit":
        break
    messages.append( {"role":"user", "content":q} )

    ## Memory
    messages.append( {"role":"user", "content":memory} )     
   
    ## Model
    available_tools = {"final_answer":tool_final_answer, "code_exec":tool_code_exec}
    res = run_agent(llm, messages, available_tools)
   
    ## Response
    print("👽 >", f"\x1b[1;30m{res}\x1b[0m")
    messages.append( {"role":"assistant", "content":res} )

僅靠大型語言模型(LLM)無法建立圖表。然而,需要注意的是,即使智能體能夠創建圖像,它們也無法看到這些圖像,因為引擎本質上仍然是一個語言模型。因此,只有使用者才能可視化圖表。

該代理使用一個庫 統計模型 訓練模型並預測時間序列資料。

處理大型資料框

大型語言模型(LLM)的記憶體有限,這限制了它們一次能夠處理的資訊量。即使是最先進的模型也有詞元數量限制(幾百頁文本)。此外,除非實作了檢索系統,否則LLM無法跨會話保留記憶體。在實踐中,為了有效地處理大型資料框,開發人員通常會採用一些策略,例如分塊、生成增強檢索(RAG)、向量資料庫以及在將內容輸入模型之前對其進行摘要。

我們來創建一個大型資料集來進行實驗。

import random
import string

length = 1000

dtf = pd.DataFrame(data={
    'Id': [''.join(random.choices(string.ascii_letters, k=5)) for _ in range(length)],
    'Age': np.random.randint(low=18, high=80, size=length),
    'Score': np.random.uniform(low=50, high=100, size=length).round(1),
    'Status': np.random.choice(['Active','Inactive','Pending'], size=length)
})

dtf.tail()

我將補充 網路搜尋工具如此一來,具備執行 Python 程式碼和搜尋網路能力的通用人工智慧就能獲得所有可用的知識,並做出資料驅動的決策。

在 Python 中,建立網路搜尋工具最簡單的方法是使用流行的網頁瀏覽器。 DuckDuckGo (pip install duckduckgo-search==6.3.5您可以直接使用原版庫,也可以匯入封面。 浪鏈 (pip install langchain-community==0.3.17).

from langchain_community.tools import DuckDuckGoSearchResults

def search_web(query:str) -> str:
  return DuckDuckGoSearchResults(backend="news").run(query)

tool_search_web = {'type':'function', 'function':{
  'name': 'search_web',
  'description': 'Search the web',
  'parameters': {'type': 'object',
                'required': ['query'],
                'properties': {
                    'query': {'type':'str', 'description':'the topic or subject to search on the web'},
}}}}

search_web(query="nvidia")

目前,該代理商總共擁有 3 種工具。

dic_tools = {'final_answer':final_answer,
             'search_web':search_web,
             'code_exec':code_exec}

由於提示資訊中無法添加完整的數據框,我將僅提供前 10 行數據,以便大型語言模型 (LLM) 能夠理解數據集的整體上下文。此外,我也會指定完整資料集的取得位置。

str_data = "\n".join([str(row) for row in dtf.head(10).to_dict(orient='records')])

prompt = f'''
You are a Data Analyst, you will be given a task to solve as best you can.
You have access to the following tools:
- tool 'final_answer' to return a text response.
- tool 'code_exec' to execute Python code.
- tool 'search_web' to search for information on the internet.

If you use the 'code_exec' tool, remember to always use the function print() to get the output.
The dataset already exists and it's called 'dtf', don't create a new one.

This dataset contains credit score for each customer of the bank. Here's the first rows:
{str_data}
'''

最後,我們可以運行代理了。

messages = [{"role":"system", "content":prompt}]
memory = '''
The dataset already exists and it's called 'dtf', don't create a new one.
'''
while True:
    ## User
    q = input('🙂 >')
    if q == "quit":
        break
    messages.append( {"role":"user", "content":q} )

    ## Memory
    messages.append( {"role":"user", "content":memory} )     
   
    ## Model
    available_tools = {"final_answer":tool_final_answer, "code_exec":tool_code_exec, "search_web":tool_search_web}
    res = run_agent(llm, messages, available_tools)
   
    ## Response
    print("👽 >", f"\x1b[1;30m{res}\x1b[0m")
    messages.append( {"role":"assistant", "content":res} )

在這次互動中,智能體正確使用了編碼工具。現在,我想讓它也使用另一個工具。

最後,我需要代理人整理從這次聊天中獲得的所有資訊。

 

結論

本文旨在作為教育指南,解釋… 如何從零開始建立代理來處理時間序列和大型資料框我們已經介紹了模型與資料互動的兩種方式:一種是透過自然語言,大型語言模型 (LLM) 使用其知識庫將表格解釋為字串;另一種是透過建立和執行程式碼,並使用工具將資料集作為物件進行操作。

本文完整程式碼如下: GitHub上

希望您喜歡!如有任何問題或意見,或想分享您有趣的項目,歡迎隨時與我聯絡。

 

評論被關閉。