시계열 및 빅데이터 프레임을 처리하기 위한 AI 에이전트

GPU나 API 키 없이 Python과 Ollama만 사용하여 처음부터 빌드하세요.

소개

에이전트는 목표에 대해 추론하고 최종 목표를 달성하기 위한 조치를 취할 수 있는 대규모 언어 모델(LLM)로 구동되는 AI 시스템입니다. 에이전트는 쿼리에 응답할 뿐만 아니라 데이터 프레임 및 시계열과 같은 데이터 처리를 포함한 일련의 작업을 조율하도록 설계되었습니다. 이러한 기능을 통해 보고서 자동화, 코드 없는 쿼리, 데이터 정리 및 처리 지원 등 다양한 실제 애플리케이션에서 데이터 분석에 대한 접근성을 높일 수 있습니다.

에이전트는 두 가지 다른 방법으로 데이터 프레임과 상호 작용할 수 있습니다.

  • 으로 자연어 – 대규모 언어 모델(LLM)은 테이블을 텍스트 문자열로 읽고 지식 기반을 기반으로 이해하려고 시도합니다.
  • 으로 코드 생성 및 실행 – 에이전트는 데이터 세트를 객체로 처리하기 위한 도구를 활성화합니다.

AI 에이전트는 자연어 처리(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에서 Dictionary로.

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 코드를 실행하고 인터넷을 검색할 수 있는 기능을 갖춘 범용 AI가 사용 가능한 모든 지식에 접근하여 데이터 기반의 의사 결정을 내릴 수 있게 됩니다.

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}

프롬프트에 전체 데이터프레임을 추가할 수 없으므로, LLM이 데이터세트의 전반적인 맥락을 이해할 수 있도록 처음 10개 행만 입력하겠습니다. 또한, 전체 데이터세트를 찾을 수 있는 위치도 명시하겠습니다.

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의

재밌게 읽으셨기를 바랍니다! 질문이나 의견이 있으시거나, 흥미로운 프로젝트를 공유하고 싶으시면 언제든지 연락 주세요.

 

댓글이 닫혔습니다.