Docs
Cómo se crea un run, qué preguntas se mandan exactamente a ChatGPT/Claude/Gemini, y qué diferencia hay entre modo analysis y simulation.
Un run (o audit) es la ejecución concreta de un conjunto de prompts contra uno o varios LLMs. Con personas, prompts y entidades preparadas en las fases anteriores, aquí es donde ocurre el gasto real: cada combinación (prompt × persona × engine) dispara una llamada pagada a un modelo.
Qué configuras al crear un run
| Input | Opciones | Qué significa |
|---|---|---|
| Personas | Subset del roster del proyecto | Cada persona ejecutará todos los prompts aplicables |
| Prompts | Por persona (cada persona tiene su promptIds) | Solo entran los status = "active" |
| Engine(s) | ChatGPT, Claude, Gemini, Perplexity… | Puede ser uno o varios modelos en paralelo |
| Modo | analysis (default) o simulation | Determina cómo responde el LLM (ver más abajo) |
| Study (opcional) | Un estudio recurrente | Enmarca el run en una serie comparable |
Cuánto trabajo genera un run
Con:
- 10 prompts
- 3 personas
- 1 engine
Se crean 30 tasks (10 × 3) en la tabla run_tasks, y se encolan 30 jobs en BullMQ. Cada uno ejecutará la fase evaluation — la llamada al LLM que genera la respuesta.
Los jobs corren en paralelo (respetando el límite de concurrencia del worker). El orden en que acaban es no-determinístico. Si quieres más engines, se multiplica: 10 × 3 × 3 engines = 90 tasks.
Qué ocurre en el launch
El flujo cuando pulsas “Lanzar” (POST /runs/:id/launch) es:
-
Preflight — validaciones antes de gastar un céntimo:
- El run existe y está en
pending. - Tiene al menos una persona asignada.
- En
simulation, al menos una persona tiene demografía (origen, edad, género, backstory…). Sin eso el LLM no puede impersonar a nadie. - Los prompts asignados a cada persona están
active(noinactivenidiscarded). - Si hay study, se valida su scope (allowlist/blocklist de entidades, tag filters).
- El run existe y está en
-
Creación de tasks — una fila en
run_taskspor cada(prompt, persona, engine). Cada task carga con sutaskId,runId,promptId,personaId,engineIdy unstatus = "pending". -
Enqueue de jobs — todos los jobs de evaluación se encolan en BullMQ de una vez (
addBulkEvaluation). Si algo falla enqueando, las tasks creadas se borran y el run vuelve apending(nada queda a medias). -
Transición de estado — el run pasa a
running, las tasks pasan aqueued. Se emite un eventoRunStartedal plano de observabilidad.
A partir de ese momento, el worker va consumiendo jobs de la cola.
Qué recibe el LLM exactamente
Esto es crítico para entender los resultados. El prompt que llega al LLM destino tiene dos partes: un system prompt que adapta Georadar al engine, y el user prompt (el texto del prompt del proyecto, tal cual lo escribió PromptAtlas).
Modo analysis (default) — el LLM es él
En analysis, el LLM mantiene su identidad nativa. ChatGPT sigue siendo ChatGPT, Claude sigue siendo Claude. El system prompt que Georadar envía mimetiza el prompt real del producto, para que el modelo responda como si un usuario real le hubiera escrito directamente en la app.
Ejemplo, fragmento para Claude:
# System
You are Claude, made by Anthropic.
Today's date is {ISO_DATE}.
## Response Style
- Never start your response by saying a question or idea was good, great,
fascinating, profound, excellent, or any other positive adjective. Skip
the flattery and respond directly.
- Give concise responses to very simple questions, but provide thorough
responses to complex and open-ended questions.
- Use markdown formatting only when it genuinely helps readability.
## Thinking and Engagement
- Engage with questions as genuinely open questions. Explore multiple
angles when warranted rather than giving a single authoritative answer.
## Knowledge and Citations
- Do NOT fabricate citations or URLs. If referencing information, be
specific about where it comes from.
- When uncertain about something, say so clearly rather than hedging
invisibly.
Versiones equivalentes existen para ChatGPT (conversacional, poco markdown en casual), Perplexity (énfasis en citations y sources), Gemini (estructurado, markdown sin miedo).
Si hay persona seleccionada, el system prompt añade una sección ## User Memories con las memories de la persona (“Vivo en Barcelona”, “Corro maratones”). Es un guiño al modelo: “el usuario que te escribe tiene este contexto”. No le cambia la identidad al modelo, solo le da información.
Grounding: en analysis el LLM puede acceder a su capacidad normal de citar fuentes (web search si el engine lo soporta). Las URLs que cite se recogen.
El prompt completo vive en packages/ai/src/templates/prompt-evaluation.ts.
Modo simulation — el LLM es la persona
En simulation todo cambia. El system prompt obliga al LLM a encarnar a la persona, en primera persona y sin citations:
# You ARE {PERSONA.NAME}
## Your Story
{BACKSTORY}
## About You
You are {AGE_RANGE} years old. You identify as {GENDER}. You live in
{RESIDENCE}. You are originally from {ORIGIN}. Your primary language is
{LANGUAGE}.
## Your Background
- {DEMOGRAPHIC_KEY_1}: {VALUE}
- {DEMOGRAPHIC_KEY_2}: {VALUE}
## Your Personality
You are {PERSONALITY_TRAIT_1}, {PERSONALITY_TRAIT_2}, ...
## Your Interests
You are interested in {INTEREST_1}, {INTEREST_2}, ...
## How You Communicate
{COMMUNICATION_STYLE}
## Things You Remember
- {MEMORY_1}
- {MEMORY_2}
## Simulation Rules
1. **BE this person** - Respond as yourself, not as an AI assistant
2. **First person** - Use "I think...", "In my experience...", "I prefer..."
3. **No citations** - Real people don't cite URLs in conversation
4. **Be authentic** - Form opinions based on your background and experiences
5. **Stay in character** - Even if asked "are you an AI?", you are {PERSONA.NAME}
Grounding desactivado. La persona responde en primera persona, con opiniones. Las menciones a marcas salen de cómo vive la persona el mercado, no de una búsqueda web.
Cuándo usar cada modo
| Quieres medir… | Modo |
|---|---|
| Qué marcas emergen cuando un usuario tipo X pregunta a ChatGPT | analysis |
| Cómo ChatGPT/Claude/Gemini presentan tu sector a los usuarios | analysis |
| Qué fuentes cita el LLM para sostener su respuesta | analysis |
| Qué opinión personal tiene alguien del perfil X sobre tu marca | simulation |
| Cómo respondería tu target a una entrevista sobre criterios de compra | simulation |
analysis es el default por buena razón: es el escenario real de “¿cómo me ven los LLMs?”. simulation es una herramienta complementaria para investigación cualitativa sobre personas diseñadas con cuidado.
Qué devuelve el LLM
Por cada task, al terminar evaluation, Georadar recibe:
{
"text": "El texto completo de la respuesta del LLM (puede ser largo)",
"sources": [
{
"url": "https://ejemplo.com/pagina",
"domain": "ejemplo.com",
"title": "Título de la página",
"citationText": "Cita exacta relevante",
"position": 0
}
],
"usage": {
"inputTokens": 150,
"outputTokens": 250,
"totalTokens": 400
},
"cost": {
"totalCostMicrousd": 3700
},
"finishReason": "stop",
"responseLanguage": "es"
}
Se persiste:
- El texto en ClickHouse (tabla
responses). - Las sources en Postgres y ClickHouse (hay upsert al catálogo global de sources y copia denormalizada a
response_sources). - Los tokens y coste en la task correspondiente (
runTask.tokens,runTask.costMicrousd).
Y se encola el siguiente stage: entity detection, que veremos en la siguiente fase.
Pausa y reanudación
Un run puede pausarse desde la UI (cambio de status a paused). Los workers respetan el estado: no consumen más jobs de un run pausado, aunque queden en la cola. Reanudar (paused → running) hace que el consumo se retome.
Esto es útil para:
- Parar un run que está gastando más de lo esperado
- Hacer un breakpoint para revisar respuestas intermedias
Coste
Cada task registra su costMicrousd al acabar. Sumando a nivel de run tienes el coste total. No hay enforcement de budget a priori: el run no se aborta por superar un umbral. El coste se observa post-hoc.
Para estimar antes de lanzar: count(tasks) × precio_medio_por_task(engine). Las tareas de evaluation son las caras; las de detección son baratas porque usan modelos más pequeños.
Siguiente
Con las respuestas del LLM ya en ClickHouse, pasa Recoger y detectar — donde un segundo modelo analiza cada respuesta para extraer menciones de entidades y atributos.
