Agentes de IA para procesar series temporales y grandes marcos de datos
Construya desde cero usando solo Python y Ollama (sin GPU, sin clave API)
una introducción
Los agentes son sistemas de IA impulsados por grandes modelos de lenguaje (LLM), capaces de razonar sobre sus objetivos y tomar acciones para alcanzar un objetivo final. Está diseñado no sólo para responder consultas, sino para organizar una serie de operaciones, incluido el procesamiento de datos (como marcos de datos y series de tiempo). Esta capacidad permite que muchas aplicaciones del mundo real democraticen el acceso al análisis de datos, como la automatización de informes, consultas sin código y soporte para la limpieza y el procesamiento de datos.

Los agentes pueden interactuar con los marcos de datos de dos maneras diferentes:
- Por lenguaje natural – El modelo de lenguaje grande (LLM) lee la tabla como una cadena de texto e intenta comprenderla basándose en su base de conocimientos.
- Por Crear y ejecutar código – El agente activa herramientas para procesar el conjunto de datos como un objeto.
Al combinar el poder del procesamiento del lenguaje natural (PLN) con la precisión de la ejecución del código, los agentes de IA permiten que una gama más amplia de usuarios interactúen con conjuntos de datos complejos y extraigan información valiosa.
En este tutorial te mostraré cómo Procesamiento de marcos de datos y series temporales mediante agentes de IA. Proporcionaré un código Python útil que se puede aplicar fácilmente en otras situaciones similares (simplemente copie, pegue y ejecute) y explicaré cada línea de código con comentarios para que pueda replicar este ejemplo (enlace al código completo al final del artículo).
preparación
Empecemos a prepararnos Ollama (pip install ollama==0.4.7), una biblioteca que permite a los usuarios ejecutar grandes modelos de lenguaje de código abierto localmente, sin necesidad de servicios en la nube, lo que brinda mayor control sobre la privacidad y el rendimiento de los datos. Dado que se ejecuta localmente, ningún dato de chat sale de tu dispositivo.
Primero, necesitas descargar Ollama Desde el sitio web.
A continuación, en el símbolo del sistema, utilice el comando para descargar el modelo de lenguaje grande (LLM) de su elección. Voy a utilizar Qwen El propio de Alibaba, porque es inteligente y ligero.
Una vez completada la descarga, puedes cambiar a Python y comenzar a escribir código.
import ollama
llm = "qwen2.5"
Probemos el modelo de lenguaje grande:
stream = ollama.generate(model=llm, prompt='''what time is it?''', stream=True)
for chunk in stream:
print(chunk['response'], end='', flush=True)
Series temporales
Una serie temporal es una secuencia de puntos de datos medidos durante un período de tiempo, a menudo utilizada para análisis y pronósticos. Nos permite ver cómo cambian las variables a lo largo del tiempo y se utiliza para identificar tendencias y patrones estacionales. Se considera Series temporales Una poderosa herramienta para el análisis estadístico y la previsión.
Voy a crear un conjunto de datos. serie temporal Falso para uso como ejemplo.
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')
Normalmente, los conjuntos de datos contienen Series temporales En una estructura realmente simple con la variable principal como columna y el tiempo como índice.
Antes de convertirlo en una cadena, quiero asegurarme de que todo esté colocado bajo una columna, para que no perdamos ninguna información.
dtf = ts.reset_index().rename(columns={"index":"date"})
dtf.head()
Luego debes cambiar el tipo de datos. De DataFrame a Diccionario.
data = dtf.to_dict(orient='records')
data[0:5]
finalmente, Del diccionario a la cadena de texto.
str_data = "\n".join([str(row) for row in data])
str_data
Ahora que tenemos una cadena, podemos Incluirlo en un mensaje Cualquier modelo de lenguaje puede procesarlo. Cuando pega un conjunto de datos en un mensaje, se lee: Modelo de lenguaje grande (LLM) Los datos son texto simple, pero aún así se puede comprender la estructura y el significado según los patrones observados durante el entrenamiento.
prompt = f'''
Analyze this dataset, it contains monthly sales data of an online retail product:
{str_data}
'''
Podemos iniciar fácilmente una conversación con Modelo de lenguaje grande (LLM). Tenga en cuenta que, en este momento, este no es un agente porque no tiene ninguna herramienta, solo estamos usando el modelo de lenguaje. Aunque no procesa números como una computadora, lo hace. Modelo de lenguaje grande (LLM) Puede reconocer nombres de columnas, patrones basados en el tiempo, tendencias y valores atípicos, especialmente con conjuntos de datos más pequeños. Puede simular el análisis y explicar los resultados, pero no realizará cálculos precisos de forma independiente, porque no ejecuta código como un agente.
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} )
reconocer Modelo de lenguaje grande (LLM) sobre números y entiende el contexto general, de la misma manera que podría entender una receta o una línea de código.
Como puedes ver, el uso de Modelos de lenguaje grandes (LLM) لتحليل Series temporales Ideal para obtener información y mantener conversaciones rápidas.
Agente
Los modelos de lenguaje grandes (LLM) son excelentes para generar ideas y explorar conceptos iniciales, mientras que un agente puede ejecutar código. Por lo tanto, puede manejar tareas más complejas, como gráficos, pronósticos y detección de anomalías. Entonces, vamos a crear las herramientas.
A veces, lidiar con “La “respuesta final” como herramienta Más eficaz. Por ejemplo, si un agente realiza múltiples acciones para crear resultados intermedios, la respuesta final puede considerarse como la herramienta que integra toda esta información en una respuesta coherente. Al diseñarlo de esta manera, puedes tener más personalización y control sobre los resultados.
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")
Entonces, Herramienta de codificación.
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'))")
Además, añadiré algunos funciones de utilidades Para utilizar la herramienta y ejecutar el agente.
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}
Cuando un agente intenta resolver una tarea, quiero que haga un seguimiento de qué herramientas se utilizaron, qué entradas probó y qué resultados obtuvo. El proceso sólo debe detenerse cuando el modelo esté listo para proporcionar la respuesta final.
Respecto a la herramienta de codificación, noté que los agentes tienden a recrear el marco de datos en cada paso. Así que lo usaré refuerzo de la memoria Para recordarle al modelo que el conjunto de datos ya existe. Es un truco común utilizado para obtener el comportamiento deseado. En última instancia, los refuerzos de memoria ayudan a tener interacciones más significativas y efectivas.
# 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} )
Crear una trama es algo que un modelo de lenguaje grande (LLM) por sí solo no puede hacer. Pero tenga en cuenta que incluso si los agentes pueden generar imágenes, no pueden verlas, porque el motor sigue siendo, en última instancia, un modelo de lenguaje. Por lo tanto, el usuario es el único que visualiza la trama.
El agente utiliza una biblioteca modelos estadisticos Entrenar un modelo y pronosticar series de tiempo.
Cómo manejar grandes marcos de datos
Los modelos de lenguaje grandes (LLM) tienen una memoria limitada, lo que restringe la cantidad de información que pueden procesar al mismo tiempo. Incluso los modelos más sofisticados tienen límites simbólicos (unos pocos cientos de páginas de texto). Además, los modelos de lenguaje grandes (LLM) no retienen la memoria entre sesiones a menos que se incorpore un sistema de recuperación. En la práctica, para trabajar eficazmente con grandes marcos de datos, los desarrolladores a menudo utilizan estrategias como fragmentación, recuperación de generación aumentada (RAG), bases de datos vectoriales y resumen de contenido antes de introducirlo en el modelo.
Vamos a crear un gran conjunto de datos para jugar con él.
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()
Voy a añadir Herramienta de búsqueda web, de modo que la IA de propósito general, con la capacidad de ejecutar código Python y buscar en Internet, obtenga acceso a todo el conocimiento disponible y pueda tomar decisiones basadas en datos.
En Python, la forma más sencilla de crear una herramienta de búsqueda web es utilizando el popular navegador privado. Pato Pato a ganar (pip install duckduckgo-search==6.3.5). Puede utilizar la biblioteca original directamente o importar un shell. LangChain (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")
En total, el agente ahora tiene 3 herramientas.
dic_tools = {'final_answer':final_answer,
'search_web':search_web,
'code_exec':code_exec}
Como no puedo agregar el marco de datos completo en la solicitud, solo alimentaré las primeras 10 filas para que el LLM pueda comprender el contexto general del conjunto de datos. Además, especificaré dónde encontrar el conjunto de datos completo.
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}
'''
Finalmente podemos ejecutar el agente.
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} )
En esta interacción, el agente utilizó correctamente la herramienta de codificación. Ahora quiero hacerle usar la otra herramienta también.
Por último, necesito que el agente reúna toda la información obtenida hasta ahora de este chat.
Conclusión
Este artículo fue concebido como un tutorial para ilustrar Cómo crear agentes desde cero para procesar series temporales y grandes marcos de datos. Hemos cubierto las dos formas en que los modelos pueden interactuar con los datos: a través del lenguaje natural, donde un modelo de lenguaje grande (LLM) interpreta una tabla como una cadena utilizando su base de conocimiento, y generando y ejecutando código, aprovechando herramientas para manipular el conjunto de datos como un objeto.
Código completo de este artículo: GitHub
¡Espero que lo hayas disfrutado! No dudes en contactarme con preguntas y comentarios o para compartir tus proyectos interesantes.
Los comentarios están cerrados.