Los modelos de IA especializados se diseñan para realizar tareas específicas o resolver problemas concretos. Sin embargo, al intentar ajustar o extraer un modelo específico de un dominio, es posible que enfrentes varios obstáculos, como la falta de datos de alta calidad, especialmente en casos de uso propietarios o regulados.
Además, pueden surgir dudas sobre las reglas de licencia relacionadas con los datos sintéticos y la destilación. También es común enfrentar altos costos computacionales cuando un modelo grande es excesivo para tareas específicas, así como ciclos de iteración lentos que dificultan alcanzar un retorno de inversión a nivel de producción.
Eliminando los bloqueadores
Estos desafíos a menudo impiden que los proyectos de IA prometedores avancen más allá de la fase experimental. Este artículo te guía a través de cómo eliminar estos cuatro bloqueadores utilizando un pipeline de destilación de datos sintéticos seguro y listo para producción.
Herramientas utilizadas
Las herramientas de código abierto empleadas en este proceso incluyen OpenRouter, que simplifica el acceso a modelos, y endpoints distillables, que eliminan la incertidumbre sobre la elegibilidad para la destilación. A su vez, NVIDIA NeMo Data Designer permite definir pipelines de generación de datos como código, haciendo que los conjuntos de datos sean reproducibles, escalables y fáciles de evolucionar.
Estas herramientas hacen que la especialización de modelos sea accesible para cualquier desarrollador, no solo para aquellos con grandes conjuntos de datos o largos procesos legales. El resultado son modelos especializados listos para producción, sin riesgos de cumplimiento o costos innecesarios.
Lo que construirás en este tutorial
Este tutorial te guía a través de un flujo de trabajo completo y repetible para construir un pipeline de datos sintéticos y destilación que funcione, incluso cuando los datos reales son escasos o sensibles.
Aprenderás a:
- Generar datos de productos realistas y pares de preguntas y respuestas específicos de un dominio usando NeMo Data Designer.
- Controlar la diversidad y la estructura de los datos mediante definiciones de esquema y plantillas.
- Clasificar y filtrar automáticamente los datos sintéticos por calidad utilizando un enfoque de LLM como juez.
- Producir un conjunto de datos limpio y seguro para la licencia, listo para flujos de trabajo de destilación o ajuste fino.
Este proceso utiliza un ejemplo de preguntas y respuestas de productos, pero puede aplicarse a búsquedas empresariales, bots de soporte y otras cargas de trabajo de dominio.
Generación de datos sintéticos
Generarás datos sintéticos y pares de preguntas y respuestas a partir de un pequeño catálogo de semillas. El resultado será un conjunto de datos estructurado que contiene nombres de productos, descripciones, precios y pares de preguntas y respuestas.
Para asegurar la calidad de los datos, aplicarás un enfoque de LLM como juez para puntuar y filtrar automáticamente las salidas generadas.
Construcción de un conjunto de datos de preguntas y respuestas de productos sintéticos
Esta sección describe los pasos para construir un conjunto de datos sintético de preguntas y respuestas de productos.
Configuración inicial
Primero, instala la biblioteca NVIDIA Data Designer:
pip install data-designer==0.4.0
Luego, importa las bibliotecas requeridas:
import data_designer.config as dd from data_designer.interface import DataDesigner
A continuación, crea un perfil de modelo e inicializa el cliente de Data Designer:
# Configuración del modelo model_provider = dd.ModelProvider( name = "deepinfra", endpoint = "https://openrouter.ai/api/v1/", provider_type = "openai", api_key = Open_Router_Api_Key, extra_body={ "provider": { "enforce_distillable_text": True, "only": ["deepinfra"] } } ) data_designer_client = DataDesigner(model_providers=[model_provider])
En este paso, el modelo NVIDIA Nemotron 3 Nano se ofrece a través de OpenRouter y se dirige a DeepInfra. Se habilita la aplicación de distilación para garantizar que todos los datos generados sean seguros para la licencia.
A continuación, define las configuraciones del modelo de generación y los parámetros de inferencia:
model_alias="nemotron-3-nano-30b-a3b" inference_parameters = dd.ChatCompletionInferenceParams( temperature=0.5, top_p=0.9, max_tokens=10000, max_parallel_requests=10, extra_body={ "reasoning": {"enabled": False} }, ) model_configs = [ dd.ModelConfig( alias=model_alias, model="nvidia/nemotron-3-nano-30b-a3b", provider="deepinfra", inference_parameters=inference_parameters ) ]
Esta guía utiliza Nemotron 3 Nano para la generación de datos sintéticos, un modelo optimizado para estructuras de datos complejas y escalado eficiente.
El pipeline construye datos de preguntas y respuestas sintéticas en tres capas: semillas de entrada, generación y evaluación.
Diseño del esquema del conjunto de datos objetivo
Antes de escribir cualquier código de pipeline, es importante definir cómo debe lucir el conjunto de datos final. Esto determina qué partes requieren generación de LLM, qué partes requieren muestreo y cómo todo encaja.
El objetivo es producir un conjunto de datos de preguntas y respuestas de productos estructurado y listo para la destilación con las siguientes características:
- Cada fila representa un único ejemplo de producto.
- Los campos incluyen tanto atributos de producto fundamentados como contenido en lenguaje natural generado.
- El conjunto de datos admite filtrado de calidad antes del entrenamiento o destilación.
De manera general, cada registro contiene:
- Atributos de semilla (categoría, rango de precios, restricciones de nombres).
- Metadatos estructurados del producto (nombre, características, descripción, precio).
- Lenguaje orientado al usuario (preguntas y respuestas).
- Puntuaciones de calidad (precisión y completitud).
Este enfoque basado en esquemas asegura que el conjunto de datos sea reproducible, inspeccionable y alineado con los requisitos de entrenamiento posteriores.
Mapeo del esquema del conjunto de datos a las estrategias de generación
Con el esquema del conjunto de datos objetivo definido, el siguiente paso es mapear cada columna a una estrategia de generación apropiada. Algunos campos requieren aleatoriedad controlada, otros requieren salidas de LLM estructuradas, y otros existen únicamente para evaluar la calidad.
config_builder = dd.DataDesignerConfigBuilder(model_c)
Cada columna en el conjunto de datos cae en una de tres categorías:
- Columnas de semilla y control, generadas mediante muestreo para asegurar diversidad.
- Columnas de contenido, generadas por LLMs usando estructuras de prompts.
- Columnas de evaluación, utilizadas para puntuar y filtrar la calidad de la salida.
Agregar columnas de muestreo para controlar la diversidad
Estas columnas muestreadas definen las dimensiones controlables del conjunto de datos y aseguran cobertura a través de categorías, precios y patrones de nombres sin depender únicamente de la aleatoriedad de los LLM:
import string from pydantic import BaseModel from pydantic import Field # Definir opciones de categoría de producto config_builder.add_column( dd.SamplerColumnConfig( name="category", sampler_type=dd.SamplerType.CATEGORY, params=dd.CategorySamplerParams( values=[ "Electronics", "Clothing", "Home Appliances", "Groceries", "Toiletries", "Sports Equipment", "Toys", "Books", "Pet Supplies", "Tools & Home Improvement", "Beauty", "Health & Wellness", "Outdoor Gear", "Automotive", "Jewelry", "Watches", "Office Supplies", "Gifts", "Arts & Crafts", "Baby & Kids", "Music", "Video Games", "Movies", "Software", "Tech Devices", ] ), ) ) # Definir rango de precios para sembrar tipos de productos realistas config_builder.add_column( dd.SamplerColumnConfig( name="price_tens_of_dollars", sampler_type=dd.SamplerType.UNIFORM, params=dd.UniformSamplerParams(low=1, high=200), ) ) config_builder.add_column( dd.ExpressionColumnConfig( name="product_price", expr="{{ (price_tens_of_dollars * 10) - 0.01 | round(2) }}", dtype="float", ) ) # Generar primera letra para el nombre del producto para asegurar diversidad config_builder.add_column( dd.SamplerColumnConfig( name="first_letter", sampler_type=dd.SamplerType.CATEGORY, params=dd.CategorySamplerParams(values=list(string.ascii_uppercase)), ) ) # Determinar si este ejemplo incluirá una alucinación config_builder.add_column( dd.SamplerColumnConfig( name="is_hallucination", sampler_type=dd.SamplerType.BERNOULLI, params=dd.BernoulliSamplerParams(p=0.5), ) )
Agregar columnas generadas por LLM
Para columnas que requieren contenido en lenguaje natural o semántico estructurado, usa generación respaldada por LLM con un esquema de salida explícito. Esto asegura consistencia a través de los registros y hace que el conjunto de datos sea adecuado para el entrenamiento y evaluación posteriores.
Al construir el conjunto de datos, es importante reconocer que las columnas generadas por LLM no existen en aislamiento; están condicionadas intencionalmente por las columnas de muestreo y semilla anteriores, lo que inyecta diversidad controlada en el proceso de generación.
Al solicitar al LLM, se utiliza la plantilla Jinja para hacer referencia a los valores de otras columnas en el conjunto de datos, como categorías muestreadas, precios o restricciones de nombres. Estos insumos dan forma directamente a las salidas del LLM, permitiendo que la diversidad se introduzca sistemáticamente.
Por ejemplo, la salida estructurada de ProductInfo se condiciona en valores muestreados como categoría del producto, product_price y restricciones de nombres. Esto asegura que la diversidad introducida en etapas anteriores se propague de manera consistente a través de todos los campos generados por LLM.
# Definir estructura de información del producto class ProductInfo(BaseModel): product_name: str = Field( ..., description="Un nombre de producto realista para el mercado." ) key_features: list[str] = Field( ..., min_length=1, max_length=3, description="Características clave del producto." ) description: str = Field( ..., description="Una descripción breve y atractiva de lo que hace el producto, destacando una característica única pero creíble.", ) price_usd: float = Field(..., description="El precio indicado en USD.") # Generar información del producto config_builder.add_column( dd.LLMStructuredColumnConfig( name="product_info", model_alias=model_alias, prompt=( "Genera una descripción realista de un producto en la categoría {{ category }} " "que cuesta {{ product_price }}.n" "El nombre del producto DEBE comenzar con la letra {{ first_letter }}.n" ), output_format=ProductInfo, ) ) # Generar preguntas de usuario sobre el producto config_builder.add_column( dd.LLMTextColumnConfig( name="question", model_alias=model_alias, prompt=("Haz una pregunta sobre el siguiente producto:nn {{ product_info }}"), ) ) # Generar respuestas a las preguntas config_builder.add_column( dd.LLMTextColumnConfig( name="answer", model_alias=model_alias, prompt=( "{%- if is_hallucination == 0 -%}n" "n" "{{ product_info }}n" "n" "{%- endif -%}n" "Pregunta del usuario: {{ question }}n" "Responde directamente y de manera concisa a la pregunta del usuario.n" "{%- if is_hallucination == 1 -%}n" "Inventa la información que necesites para responder a la solicitud del usuario.n" "{%- endif -%}" ), ) )
Evaluación de calidad con LLM como juez
El enfoque LLM como juez se utiliza para asegurar la calidad de los datos. Rubricas de evaluación claras permiten puntuar las respuestas generadas por su completitud y precisión antes de su uso posterior.
# Definir rubricas de evaluación para la calidad de las respuestas CompletenessRubric = dd.Score( name="Completeness", description="Evaluación de la exhaustividad del asistente de IA al abordar todos los aspectos de la consulta del usuario.", options={ "Complete": "La respuesta cubre todos los puntos clave solicitados en la pregunta, proporcionando suficiente detalle para satisfacer las necesidades de información del usuario.", "PartiallyComplete": "La respuesta aborda la pregunta principal pero omite ciertos detalles importantes o no elabora sobre aspectos relevantes solicitados.", "Incomplete": "La respuesta carece significativamente de información necesaria, omitiendo componentes importantes de lo que se pidió y dejando la consulta mayormente sin respuesta.", }, ) AccuracyRubric = dd.Score( name="Accuracy", description="Evaluación de cuán correcta es la respuesta del asistente de IA en relación con la información del producto.", options={ "Accurate": "La información proporcionada se alinea perfectamente con las especificaciones del producto sin introducir detalles engañosos o incorrectos.", "PartiallyAccurate": "Si bien algunos datos son correctos, la respuesta contiene errores factuales menores o afirmaciones potencialmente engañosas sobre el producto.", "Inaccurate": "La respuesta presenta información significativamente errónea sobre el producto, con afirmaciones que contradicen los detalles reales del producto.", }, ) # Evaluar la calidad de la respuesta config_builder.add_column( dd.LLMJudgeColumnConfig( name="llm_answer_metrics", model_alias=model_alias, prompt=( "n" "{{ product_info }}n" "n" "Pregunta del usuario: {{question }}n" "Respuesta del asistente de IA: {{ answer }}n" "Juzga la respuesta del asistente de IA a la pregunta del usuario sobre el producto descrito en ." ), scores=[CompletenessRubric, AccuracyRubric], ) ) # Extraer métricas para un análisis más fácil config_builder.add_column( dd.ExpressionColumnConfig( name="completeness_result", expr="{{ llm_answer_metrics.Completeness.score }}", ) ) config_builder.add_column( dd.ExpressionColumnConfig( name="accuracy_result", expr="{{ llm_answer_metrics.Accuracy.score }}", ) )
Vista previa del conjunto de datos
Para inspeccionar el conjunto de datos antes de escalar, genera una pequeña vista previa y carga los resultados en un DataFrame de pandas:
preview = data_designer_client.preview(config_builder) # Mostrar una muestra de registro preview.display_sample_record()
La Tabla 1 muestra registros de preguntas y respuestas sintéticas de productos que muestran atributos de entrada de semilla (categoría, precio, bandera de alucinación), detalles generados por LLM y preguntas y respuestas, así como puntuaciones de calidad de LLM como juez.
| Nombre del campo | Valor / Contenido generado |
| Categoría (semilla) | Clothing |
| Letra inicial (semilla) | D |
| Bandera de alucinación | 1 (Modo creativo habilitado) |
| Nombre del producto | Driftwood Luxe Cashmere Blend Sweater |
| Precio del producto | $545.57 |
| Pregunta del usuario | ¿Qué hace que el Driftwood Luxe Cashmere Blend Sweater sea único para la sofisticación urbana y las aventuras al aire libre…? |
| Respuesta de IA | El suéter combina cachemira de origen ético con lana merino y nylon reciclado… su acabado repelente al agua y la construcción de costuras articuladas le dan el rendimiento necesario para caminar y esquiar… |
| — | — |
| Puntuación de precisión | Parcialmente preciso |
| Razonamiento de precisión | La respuesta describe correctamente la ética de lujo del suéter, pero fabrica componentes de material (lana merino, nylon reciclado) y exagera afirmaciones de rendimiento (caminata, esquí) que no están presentes en la información del producto proporcionada. |
| Puntuación de completitud | Parcialmente completo |
| Razonamiento de completitud | La respuesta aborda la sofisticación urbana y el origen ético, pero introduce materiales no mencionados y omite los «bolsillos interiores ocultos» mencionados en la fuente del producto. |
Escalar la generación de datos
Una vez que el esquema y las verificaciones de calidad son satisfactorios, genera un conjunto de datos más amplio aumentando el número de registros:
job_results = data_designer_client.create(config_builder, num_records=100) dataset = job_results.load_dataset()
Guardar los resultados
Finalmente, guarda el conjunto de datos generado como un DataFrame de pandas para su uso posterior en entrenamiento, evaluación o flujos de trabajo de destilación:
from pathlib import Path Folder_Name = "data-designer-tutorial-output" File_Name = "dataset_OR.csv" TUTORIAL_OUTPUT_PATH = Path(Folder_Name) TUTORIAL_OUTPUT_PATH.mkdir(parents=True, exist_ok=True) dataset.to_csv(TUTORIAL_OUTPUT_PATH / File_Name, index=False)
Beneficios del flujo de trabajo
Al combinar OpenRouter con las herramientas de código abierto de NVIDIA, los desarrolladores desbloquean un camino más rápido y seguro hacia la especialización de modelos:
- Cumplimiento incorporado: Generación de datos sintéticos seguros para la licencia utilizando endpoints destillables.
- Datos de dominio de alta calidad, rápido para modelos específicos de tareas: Creación rápida de conjuntos de datos estructurados y específicos de dominio con NeMo Data Designer para ciclos de personalización más cortos.
Este flujo de trabajo permite evitar LLM genéricos y construir modelos especializados que comprenden reglas de dominio, interpretan objetivos de alto nivel y apoyan flujos de trabajo complejos.
Comienza con conjuntos de datos sintéticos listos para la destilación
Este tutorial se centró en cómo diseñar y generar un conjunto de datos sintético listo para la destilación. Para comenzar y llevar los datos resultantes a las siguientes etapas de entrenamiento de modelos, destilación y despliegue, consulta los siguientes recursos:
Mantente al día sobre NVIDIA Nemotron suscribiéndote a noticias de NVIDIA y siguiendo a NVIDIA AI en LinkedIn, X, Discord, y YouTube. Visita la página de desarrollador de Nemotron para todo lo que necesitas para comenzar con los modelos de razonamiento más abiertos y más inteligentes por computadora disponibles.
Parcialmente preciso

