DataChain es una biblioteca moderna de marcos de datos Pythonic diseñada para inteligencia artificial. Está diseñado para organizar sus datos no estructurados en conjuntos de datos y distribuirlos a escala en su máquina local. Datachain no abstrae ni oculta los modelos de IA y las llamadas API, pero ayuda a integrarlos en la pila de datos posmoderna.
El almacenamiento como fuente de verdad.
Procese datos no estructurados sin copias redundantes de S3, GCP, Azure y sistemas de archivos locales.
Soporte de datos multimodal: imágenes, vídeo, texto, PDF, JSON, CSV, parquet.
Une archivos y metadatos en conjuntos de datos en columnas, versionados y persistentes.
Canalizaciones de datos compatibles con Python.
Operar sobre objetos y campos de objetos de Python.
Paralelización integrada y computación sin memoria sin SQL ni Spark.
Enriquecimiento y procesamiento de datos.
Genere metadatos utilizando modelos de IA locales y API de LLM.
Filtre, únase y agrupe por metadatos. Búsqueda por incrustaciones de vectores.
Pase conjuntos de datos a Pytorch y Tensorflow, o expórtelos nuevamente al almacenamiento.
Eficiencia.
Paralelización, cargas de trabajo sin memoria y almacenamiento en caché de datos.
Operaciones vectorizadas en campos de objetos de Python: suma, recuento, promedio, etc.
Búsqueda de vectores optimizada.
$ pip instalar cadena de datos
Un almacenamiento consta de imágenes de perros y gatos (dog.1048.jpg, cat.1009.jpg), anotadas con datos reales e inferencias de modelos en el formato 'json-pairs', donde cada imagen tiene un archivo JSON coincidente, como cat. 1009.json:
{"clase": "gato", "id": "1009", "num_annotators": 8,"inferencia": {"clase": "perro", "confianza": 0,68} }
Ejemplo de descarga únicamente de imágenes inferidas de "gatos de alta confianza" utilizando metadatos JSON:
de la columna de importación de cadena de datos, DataChainmeta = DataChain.from_json("gs://datachain-demo/dogs-and-cats/*json", object_name="meta")images = DataChain.from_storage("gs://datachain-demo /perros-y-gatos/*jpg")images_id = imágenes.map(id=archivo lambda: file.path.split('.')[-2])annotated = images_id.merge(meta, on="id", right_on="meta.id")likely_cats = annotated.filter((Column("meta.inference .confianza") > 0,93) & (Columna("meta.inference.class_") == "gato"))likely_cats.export_files("gatos-de-alta-confianza/", señal="archivo")
Inferencia por lotes con un modelo de sentimiento simple utilizando la biblioteca de transformadores:
transformadores de instalación de tuberías
El siguiente código descarga archivos de la nube y aplica una función definida por el usuario a cada uno de ellos. Todos los archivos con un sentimiento positivo detectado se copian al directorio local.
desde transformadores importar tuberíadesde cadena de datos importar DataChain, Columnclassifier = pipeline("sentiment-analysis", dispositivo="cpu",model="distilbert/distilbert-base-uncased-finetuned-sst-2-english")def is_positive_dialogue_ending(file) - > bool:final_diálogo = file.read()[-512:]clasificador de retorno(final_diálogo)[0]["etiqueta"] == cadena "POSITIVO" = ( DataChain.from_storage("gs://datachain-demo/chatbot-KiT/", nombre_objeto="archivo", tipo="texto") .settings(paralelo=8, caché=Verdadero) .map(is_positive=is_positive_dialogue_ending) .save("archivo_respuesta") )positive_chain = chain.filter(Column("is_positive") == True)positive_chain.export_files("./output")print(f"{positive_chain.count()} archivos fueron exportados")
Se exportaron 13 archivos.
$ ls salida/datachain-demo/chatbot-KiT/ 15.texto 20.texto 24.texto 27.texto 28.texto 29.texto 33.texto 37.texto 38.texto 43.texto ... $ ls salida/datachain-demo/chatbot-KiT/ | baño -l 13
Los LLM pueden funcionar como clasificadores universales. En el siguiente ejemplo, empleamos una API gratuita de Mistral para juzgar los diálogos del chatbot disponibles públicamente. Obtenga una clave API de Mistral gratuita en https://console.mistral.ai
$ pip install mistralai (Requiere versión >=1.0.0) $ exportar MISTRAL_API_KEY=_tu_clave_
DataChain puede paralelizar llamadas API; el nivel gratuito de Mistral admite hasta 4 solicitudes al mismo tiempo.
from mistralai import Mistralfrom datachain import File, DataChain, ColumnPROMPT = "¿Este diálogo fue exitoso? Responda en una sola palabra: Éxito o fracaso". def eval_dialogue(archivo: Archivo) -> bool: cliente = Mistral() respuesta = cliente.chat .complete( model="open-mixtral-8x22b", mensajes=[{"rol": "sistema", "contenido": PROMPT}, {"rol": "usuario", "contenido": archivo.read()}]) resultado = respuesta.opciones[0].message.content return resultado.lower().startswith("éxito")chain = ( DataChain .from_storage("gs://datachain-demo/chatbot-KiT/", object_name="archivo") .settings(paralelo=4, caché=Verdadero) .map(is_success=eval_dialogue) .save("archivos_mistral") )successful_chain = chain.filter(Column("is_success") == True)successful_chain.export_files("./output_mistral")print(f"{successful_chain.count()} archivos fueron exportados")
Con las instrucciones anteriores, el modelo Mistral considera 31/50 archivos para mantener diálogos exitosos:
$ ls salida_mistral/datachain-demo/chatbot-KiT/ 1.texto 15.texto 18.texto 2.texto 22.texto 25.texto 28.texto 33.texto 37.texto 4.texto 41.texto ... $ ls salida_mistral/datachain-demo/chatbot-KiT/ | baño -l 31
Las respuestas de LLM pueden contener información valiosa para el análisis, como la cantidad de tokens utilizados o los parámetros de rendimiento del modelo.
En lugar de extraer esta información de la estructura de datos de respuesta de Mistral (clase ChatCompletionResponse), DataChain puede serializar toda la respuesta LLM a la base de datos interna:
from mistralai import Mistralfrom mistralai.models import ChatCompletionResponsefrom datachain import File, DataChain, ColumnPROMPT = "¿Este diálogo fue exitoso? Responda en una sola palabra: Éxito o fracaso".def eval_dialog(file: File) -> ChatCompletionResponse: client = MistralClient() devolver client.chat( model="open-mixtral-8x22b", mensajes=[{"role": "sistema", "contenido": INDICADOR}, {"rol": "usuario", "contenido": file.read()}])cadena = ( DataChain.from_storage("gs://datachain-demo/chatbot-KiT/", object_name="archivo") .settings(paralelo=4, caché=Verdadero) .map(respuesta=eval_dialog) .map(status=respuesta lambda: respuesta.opciones[0].message.content.lower()[:7]) .save("respuesta") )chain.select("archivo.nombre", "estado", "respuesta.uso").show(5)success_rate = chain.filter(Column("status") == "éxito").count() / cadena .count()print(f"{100*success_rate:.1f}% de los diálogos fueron exitosos")
Producción:
estado del archivo respuesta respuesta respuesta nombre uso uso uso tokens_indicación tokens_total tokens_completación 0 1.txt éxito 547 548 1 1 error de 10.txt 3576 3578 2 2 Fallo 11.txt 626 628 2 3 12.txt falla 1144 1182 38 4 13.txt éxito 1100 1101 1 [Limitado por 5 filas] 64,0% de los diálogos fueron exitosos
En los ejemplos anteriores, los conjuntos de datos se guardaron en la base de datos integrada (SQLite en la carpeta .datachain del directorio de trabajo). Estos conjuntos de datos se versionaron automáticamente y se puede acceder a ellos mediante DataChain.from_dataset("dataset_name").
A continuación se explica cómo recuperar un conjunto de datos guardado e iterar sobre los objetos:
chain = DataChain.from_dataset("response")# Iterando uno por uno: admite flujo de trabajo sin memoria para archivos, respuesta en chain.limit(5).collect("file", "response"):# verificar el objetos Python recopiladosassert isinstance(response, ChatCompletionResponse)status = respuesta.opciones[0].message.content[:7]tokens = Response.usage.total_tokensprint(f"{file.get_uri()}: {status}, tamaño de archivo: {file.size}, tokens: {tokens}")
Producción:
gs://datachain-demo/chatbot-KiT/1.txt: Éxito, tamaño de archivo: 1776, tokens: 548 gs://datachain-demo/chatbot-KiT/10.txt: Error, tamaño de archivo: 11576, tokens: 3578 gs://datachain-demo/chatbot-KiT/11.txt: Error, tamaño de archivo: 2045, tokens: 628 gs://datachain-demo/chatbot-KiT/12.txt: Error, tamaño de archivo: 3833, tokens: 1207 gs://datachain-demo/chatbot-KiT/13.txt: Éxito, tamaño de archivo: 3657, tokens: 1101
Algunas operaciones se pueden ejecutar dentro de la base de datos sin deserialización. Por ejemplo, calculemos el costo total de usar las API de LLM, asumiendo que la llamada a Mixtral cuesta $2 por 1 millón de tokens de entrada y $6 por 1 millón de tokens de salida:
cadena = DataChain.from_dataset("mistral_dataset")costo = chain.sum("response.usage.prompt_tokens")*0.000002 + chain.sum("response.usage.completion_tokens")*0.000006print(f"Gasté ${cost:.2f} en {chain.count()} llamadas")
Producción:
Gasté $0.08 en 50 llamadas
Los resultados de la cadena se pueden exportar o pasar directamente al cargador de datos de PyTorch. Por ejemplo, si estamos interesados en pasar una imagen y una etiqueta según el sufijo del nombre del archivo, el siguiente código lo hará:
desde torch.utils.data importar DataLoaderdesde transformadores importar CLIPProcessordesde cadena de datos importar C, DataChainprocessor = CLIPProcessor.from_pretrained("openai/clip-vit-base-patch32")chain = (DataChain.from_storage("gs://datachain-demo/dogs -y-gatos/", tipo="imagen") .map(label=nombre lambda: nombre.split(".")[0], params=["archivo.nombre"]) .select("archivo", "etiqueta").to_pytorch(transform=processor.image_processor,tokenizer=processor.tokenizer, ) )cargador = DataLoader(cadena, tamaño_lote=1)
Empezando
Multimodal (pruebe en Colab)
Evaluaciones de LLM (pruebe en Colab)
Lectura de metadatos JSON (pruebe en Colab)
Las contribuciones son muy bienvenidas. Para obtener más información, consulte la Guía para colaboradores.
Documentos
Presente un problema si encuentra algún problema
Chat de discordia
Correo electrónico
Gorjeo