Skip to main content
Los modelos de lenguaje son buenos resumiendo texto y malos recordando hechos. Este tutorial saca los hechos de la memoria del modelo y los coloca en el prompt, de modo que cada frase de la salida pueda rastrearse hasta una página que acabas de recuperar. Construiremos una herramienta de línea de comandos que responde a una pregunta con un informe corto y citado:
Por el camino haremos lo siguiente:
  1. Buscar en la web en vivo con /augment/search
  2. Decidir cuáles de esos resultados vale la pena leer
  3. Convertir las páginas seleccionadas a Markdown con /augment/scrape
  4. Pedir a un modelo de chat que escriba el informe, citando las fuentes por número
  5. Conectar las cuatro etapas en un único script
Hacer la recuperación por nuestra cuenta, en lugar de dejar que la haga el modelo, es lo que hace que el resultado sea auditable. Conservamos la lista exacta de páginas que entraron en el prompt y podemos mostrar al lector de dónde vino cada afirmación. Si prefieres que Venice se encargue de la recuperación dentro de una única solicitud, establece venice_parameters.enable_web_search en una completion de chat. La guía Búsqueda y extracción web compara ambos enfoques.

Configuración

Necesitas Python 3.9 o posterior, el paquete requests y una clave de API de Venice. Consulta Generación de una clave de API si aún no tienes una.
Crea research.py y comienza con las importaciones y un bloque de encabezados compartido que reutilizará cada llamada:

1. Busca en la web

/augment/search toma una consulta y devuelve hasta 20 resultados clasificados. Brave es el proveedor predeterminado y aplica Zero Data Retention. Google también está disponible y se envía mediante proxy a través de Venice, de modo que la consulta nunca se vincula contigo.
Cada resultado es un objeto con cuatro campos:
Vale la pena conocer dos detalles de esa respuesta antes de construir sobre ella. El campo content llega con HTML dentro, porque el proveedor envuelve los términos coincidentes en etiquetas <strong>. La sustitución HTML_TAG de arriba las elimina para que el fragmento llegue al modelo como texto sin formato. El campo date suele ser una cadena vacía. Muchas páginas no publican una fecha legible por máquina, así que trata date como una pista que puedes usar cuando esté presente, más que como un campo por el que puedas ordenar o filtrar.
limit debe estar entre 1 y 20, y query debe tener entre 1 y 400 caracteres. Los valores fuera de esos rangos devuelven HTTP 400 con un cuerpo de validación. No se ajustan automáticamente por ti.

2. Elige qué fuentes leer

Extraer los diez resultados sería lento, costoso y en gran medida redundante. Los motores de búsqueda devuelven varias páginas del mismo sitio, y los sitios de documentación en particular devuelven la misma página en varios idiomas, así que el mismo contenido puede aparecer tres o cuatro veces bajo URL distintas. Conservar solo el resultado mejor clasificado por dominio elimina la mayor parte de esa duplicación en unas pocas líneas:
Al ejecutarlo sobre los diez resultados anteriores se reducen a cuatro sitios distintos:
Este es el lugar natural para añadir tu propio criterio. Puedes crear una lista de dominios de confianza, descartar resultados cuyo fragmento nunca mencione los términos clave o preferir resultados con un date reciente. Cada filtro que apliques aquí es una decisión que el modelo ya no tendrá oportunidad de equivocar.

3. Extrae las páginas seleccionadas

/augment/scrape obtiene una URL pública y la devuelve como Markdown. Primero solicita al sitio una representación Markdown nativa y recurre a la extracción basada en navegador cuando no la hay. Algunas páginas fallarán, y una herramienta de investigación debería tratar eso como algo rutinario en lugar de fatal:
Ambas comprobaciones se ganan su lugar. La verificación de estado detecta sitios que rechazan el acceso automatizado, y la de longitud detecta páginas que devuelven 200 pero entregan un banner de cookies o una envoltura vacía en lugar de un artículo.
Los fallos de extracción devuelven un cuerpo simple {"error": "..."} con un mensaje legible, por ejemplo X (formerly Twitter) blocks automated access to their content. X y Reddit están bloqueados por completo. Para incluir publicaciones de X en una respuesta, utiliza en su lugar venice_parameters.enable_x_search en una completion de chat.
Las solicitudes no dependen entre sí, así que ejecútalas en paralelo. Ya que estamos, limitemos también cuánto conservamos de cada página:
La tercera página volvió con exactamente 12000 caracteres, lo que significa que era más larga que el presupuesto y quedó truncada.
char_budget no es un lujo. Los resultados de búsqueda incluyen con frecuencia páginas agregadas como mapas del sitio, changelogs y archivos llms-full.txt, y una sola de esas puede devolver cerca de un millón de caracteres. Sin un tope, un resultado desafortunado decide cuánto cuesta toda la solicitud.

4. Escribe el informe

Ahora entregamos al modelo las páginas que recopilamos, numeradas, y le pedimos citas que se refieran a esos números. La numeración en el prompt es lo que nos permite convertir después un [2] de la salida en una URL.
Una temperature baja mantiene la redacción cerca del texto de las fuentes. Establecer enable_web_search en off coincide con el valor predeterminado, pero decirlo explícitamente garantiza que el modelo no pueda introducir en silencio una fuente que no aparece en nuestra lista de referencias.

5. Únelo todo

La última pieza ejecuta las etapas en orden y añade la lista de referencias que resuelve los números de las citas:
Los mensajes de progreso se envían a stderr, de modo que puedes redirigir solo el informe a un archivo:
Aquí está el inicio del informe que produjo, abreviado:
Nota que la fuente 3 nunca se cita en este extracto. Ese es el comportamiento que queremos. El modelo usó las fuentes que eran relevantes y dejó las demás en paz, y como las citas están numeradas, puedes verlo de un vistazo.

Ajuste del pipeline

La mayor parte del tiempo de reloj se va a la completion de chat final, ya que cuatro páginas extraídas suman decenas de miles de tokens. Estas son las palancas por las que conviene empezar:

Próximos pasos

El pipeline que ya tienes es una base más que un producto terminado. Algunas direcciones que vale la pena explorar:
  • Almacena en caché el Markdown extraído por URL para que las preguntas repetidas no vuelvan a descargar las mismas páginas.
  • Guarda el Markdown como vectores con Embeddings y recupera pasajes en lugar de páginas enteras.
  • Deja que el modelo planifique varias consultas antes de buscar, como hace la demo Agente de investigación privado.
  • Lee el informe en voz alta canalizándolo a Narración de artículos con texto a voz.

Búsqueda y extracción web

Referencia de los endpoints Search y Scrape.

Narración de artículos con texto a voz

Convierte el texto que acabas de generar en audio.

Embeddings

Indexa el Markdown extraído en lugar de volver a descargarlo.

Agente de investigación privado

Un agente más grande que planifica sus propias búsquedas.