LLM Testing Framework Using LLMs as Quality Assurance Agents

various · Tech · 2024 · source Agentic: yes · promotional bias: med · source-backed · extracted with prompt 0.5.6 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: Conversational AI quality assurance

Alaska Airlines and Bitra needed a scalable way to test customer-facing generative-AI chatbots against happy-path, adversarial, and brand-risk conversations before release, because manual probing found issues but could not cover hundreds of conversational paths or ongoing regressions.

Constraints:

Architecture

The team built CARL, an LLM-powered QA Response Liaison that simulates user personas, converses with a model under test, scores the conversation, stores logs and metrics, and routes risky or changing results into human review. The production architecture uses configurable JSON/storage/CI inputs, persona-tuned models in a model registry, Vertex AI endpoints, a conversation coordinator running as containers on GCP Autopilot, Cloud Storage for metrics, AlloyDB plus Vertex AI extensions for text analysis, Cloud Composer smoke tests, and Cloud Build CI/CD integration.

Diagram confidence: explicit (topology described by the source).

flowchart LR
  A["Test configuration interface"] --> F["Conversation coordinator"]
  B["Persona-tuned CARL models"] --> D["Vertex AI endpoints"]
  C["Model registry"] --> B
  C --> D
  D --> F
  E["Model under test"] --> F
  F --> G["Cloud Storage metrics store"]
  F --> H["AlloyDB conversation store"]
  F --> I["Config update module"]
  I --> J["Human review GUI"]
  H --> J
  K["Cloud Composer smoke tests"] --> A
  L["Cloud Build CI"] --> A
  G --> M["Reporting dashboards"]
  H --> M
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
Test configuration interface Accepts JSON, storage-based, or CI/CD test definitions with tags, topics, depth, and persona descriptions. Conversation coordinator, Cloud Build CI
Persona-tuned CARL models Simulate happy-path, adversarial, trolly, or malicious users in conversations with target chatbots. Model registry, Vertex AI endpoints, Conversation coordinator
Model registry Stores tuned persona models as reusable model artifacts. Persona-tuned CARL models, Vertex AI endpoints
Vertex AI endpoints Serve CARL models and model-under-test endpoints, while allowing different LLM backends to be swapped. Persona-tuned CARL models, Model under test, Conversation coordinator
Model under test The customer-facing chatbot or LLM application being evaluated by CARL. Vertex AI endpoints, Conversation coordinator
Conversation coordinator Runs as a small set of containers on GCP Autopilot to proxy conversations, apply criteria, score results, and store outputs. Test configuration interface, Persona-tuned CARL models, Model under test, Cloud Storage metrics store, AlloyDB conversation store, Config update module
Cloud Storage metrics store Stores metadata, conversation logs, latency, rate-limit hits, ratings, and reporting inputs. Conversation coordinator, Reporting dashboards
AlloyDB conversation store Stores text-based conversation outputs and enables Vertex AI extension-based summarization and metrics. Conversation coordinator, Reporting dashboards, Human review GUI
Config update module Flags conversations and supports semi-automated business-rule or prompt configuration updates. Conversation coordinator, Human review GUI
Human review GUI Lets non-technical stakeholders read conversations, inspect outputs, and flag issues. Config update module, AlloyDB conversation store
Cloud Composer smoke tests Runs CARL on a scheduled cadence to detect quality degradation over time. Test configuration interface, Conversation coordinator
Cloud Build CI Runs CARL checks when business logic or LLM changes are pushed. Test configuration interface, Conversation coordinator
Reporting dashboards Aggregate tags, scores, trends, and degradation signals for product and business stakeholders. Cloud Storage metrics store, AlloyDB conversation store

Data flow

A test configuration supplies tags, topics, depth, personas, goals, attitudes, and success criteria. Persona-tuned or base LLMs are served through Vertex AI or other LLM APIs, the conversation coordinator proxies messages between CARL and the model under test, evaluation criteria score each conversation, logs and metrics go to Cloud Storage and AlloyDB, and low scores, score changes, or sampled successful conversations are surfaced to humans for review and configuration/prompt updates.

5 supporting quotes
“Carl engages in conversation with any gen chatbot residing on gcp and there's a ton of customization we built in right we wanted to be able to customize uh by goals”transcript, stated
“it sort of proxies those conversations back and forth it runs the criteria it starts running evaluation it does its scoring and then it stores that data into two places”transcript, stated
“we store everything in class CL storage and we look at cloud storage and we're using it as effectively our metric store”transcript, stated
“we also throw everything into alloy DB and it's interesting why we do this it was sort of a we were getting excited when the extensions for vertex a were being announced”transcript, stated
“we orchestrate that all through Cloud composer it's just scheduled on a crun the second bit is we use a lot of cloud build”transcript, stated

Why this architecture

CARL uses an LLM to test another LLM because the team needed scalable conversation generation and insight synthesis across many personas, not a static manual test list. The architecture deliberately abstracts LLM backends, test configuration, orchestration, storage, and review so the framework can run in CI/CD, smoke tests, product workflows, and future model integrations without rebuilding around a single provider API.

4 supporting quotes
“we needed hundreds of different conversational paths we needed varying levels of adversarial intent from trolly to downright evil and we needed quick insights on Trends”transcript, stated
“if only there were some type of technology that could have conversations based on loose human prompts and then synthesiz size insights from those conversations”transcript, stated
“if you build for one API you're going to be screwed because in a week later there's going to be another one”transcript, stated
“we really started thinking well let's take everything we've done with mlops for the last few years how does that really apply to geni”transcript, stated

Models used: Gemini · Dialogflow with Gemini integration · persona-tuned LLMs · general LLM for summarization

Scale

Alternatives considered (roads not taken)

Manual adversarial testing by a developer

Rejected because: Manual probing surfaced examples quickly but could not scale to hundreds of conversation paths or trend analysis.

“when I was doing my initial adversarial testing with vzer of the bot within about two hours I got a handful of informative examples”transcript, stated
“a handful of examples is not enough right uh we needed something that could scale up”transcript, stated

Build CARL around one LLM API

Rejected because: The LLM landscape changed too quickly, so CARL had to plug into multiple APIs and models on both the tester and model-under-test sides.

“we wanted to make sure that Carl can plug into any llm and we wanted to take it a step further and we challenged ourselves to sort of start asking the inverse”transcript, stated

Send every conversation to human review

Rejected because: Reviewing everything would defeat the automation goal, so only low scores, score changes, and sampled 10-score conversations go to humans.

“human in the loop would be really annoying if we sent everything there it would actually defeat the purpose of trying to automate a much of this”transcript, stated

Overfit prompt fixes to every discovered failure case

Rejected because: The team looked for common threads across failures and made global system-prompt changes instead.

“we kind of look at that globally and we figure out what are changes we can make to the system prompt overall that are going to help improve this”transcript, stated

Patterns

llm-as-judge (evaluation)

CARL uses an LLM-driven evaluator to score chatbot conversations, cite deductions, summarize interactions, and flag whether the model under test behaved acceptably.

“Carl assesses the quality of each response uh and in assessing that quality rates every conversation on a scale from 1 to 10 and cites any reasons for deductions”transcript, stated

eval-driven-development (evaluation)

CARL is wired into smoke tests, CI/CD, score distributions, and regression tracking so chatbot changes are evaluated before beta or customer exposure.

“what we initially do as part of our smoke test and those initial QA bills of cicd is we run through we Run Carl through many good examples”transcript, stated
“before put any model out there this becomes a way for us to test it to make sure safe before put it in front of a customer”transcript, stated

multi-agent-orchestration (architecture)

The system coordinates a tester LLM and a model-under-test LLM through a conversation coordinator, with configurable personas and success criteria driving the interaction.

“it's really about coordinating this conversation between an between two llms it's about bringing flexibility into what those llms are both from your from the top side which is which is your conversation which is Carl and on the bottom side which is your model under test”transcript, stated

human-in-the-loop-gate (operations)

Human reviewers inspect low scores, score changes, and sampled high-scoring conversations, while non-technical users can read conversations and flag issues in a GUI.

“if the score is significantly low we do send it to human in the loop just to get someone to quickly check why this is the case”transcript, stated
“anything that's scoring on the 10 like we think it's a happy path we we just sample those and we send those to human in the loop”transcript, stated

model-routing (architecture)

The design keeps both the CARL persona model and the target chatbot backend swappable across Gemini, Dialogflow, and other LLMs rather than binding to one API.

“some are really good good for conversations some are really good for you know grounded truth some are really good with function calling”transcript, stated
“we got it to work with dialog flow because it had neat interactions with the web Hooks and then we also got it to run with dialog flow with the Gemini integration”transcript, stated

Tradeoffs

Use an LLM to test another LLM

Chose A generative-AI testing agent that simulates personas and scores conversations over Manual QA scripts and one-off adversarial conversations.

Rationale: The team needed scaled conversation generation and synthesis across loose human prompts, which is exactly the capability LLMs provide.

“if only there were some type of technology that could have conversations based on loose human prompts and then synthesiz size insights from those conversations”transcript, stated

Make model interfaces pluggable

Chose Support any LLM for both CARL and the model under test over Optimize only for one provider API.

Rationale: The team expected model APIs and capabilities to change quickly, so lock-in would make the framework obsolete.

“if I've learned anything about llms over the last year and a half it's that every week there's something new that's out there”transcript, stated

Store results in both Cloud Storage and AlloyDB

Chose Cloud Storage for metric artifacts and AlloyDB for text outputs plus Vertex AI extension analysis over A single generic results store.

Rationale: Conversation metadata and text analysis had different access patterns: reporting needed metrics, while text summaries benefited from database-backed LLM extensions.

“we store everything in class CL storage and we look at cloud storage and we're using it as effectively our metric store”transcript, stated
“if we started throwing a lot of the summaries into uh alloy DB we can then extend them using sort of the vertx AI extensions”transcript, stated

Sample human review rather than reviewing every run

Chose Route low scores, score changes, and sampled 10-score conversations to humans over Sending all conversations to the human-in-the-loop queue.

Rationale: Reviewing every conversation would undermine the point of automation, but selective review still checks failures and validates apparent successes.

“human in the loop would be really annoying if we sent everything there it would actually defeat the purpose of trying to automate a much of this”transcript, stated

Gotchas (what bit them)

Manual adversarial testing gives a false sense of coverage.

Root cause: A human tester can find a few edge cases quickly, but the space of personas, intents, and conversation paths is much larger.

Resolution: Use CARL to generate hundreds of simulated conversations across goals, attitudes, depths, and success criteria.

“within about two hours I got a handful of informative examples of things that we were at risk of actually doing to the public”transcript, stated
“we needed something that could scale up we needed hundreds of different conversational paths”transcript, stated

Open-ended LLM-to-LLM conversations can run too long and hit rate limits.

Root cause: The prototype originally looped without a depth limit, causing long-running conversations and rate-limit problems.

Resolution: Add a depth parameter controlling how many turns happen before evaluation.

“we actually didn't have depth and we sort of just ran it as like a loop effectively when we were prototyping and first you get Lany second you get rate limits”transcript, stated
“we started controlling depth which is just how long a conversation should go before evaluation should happen”transcript, stated

Base LLMs may not simulate nuanced personas well enough for useful QA.

Root cause: Some base models could not carry the desired persona conversations properly.

Resolution: Fine-tune persona models with sample conversations from product teams and customer testing.

“when we saw Carl itself wouldn't carry the conversation properly with some base llms then we went to fine tuning”transcript, stated
“a lot of those personas really came from our product teams that are talking to end customers trying to see how they're going to use this product”transcript, stated

Fixing every failure individually can overfit the chatbot prompt.

Root cause: Edge cases often share broader motivational patterns, but treating each failed conversation as a unique patch bloats the system prompt.

Resolution: Look globally across failures and make common-thread prompt changes, such as framing the bot's purpose as a mission it should not deviate from.

“we're not necessarily overfitting with every single fix case into a system prompt uh and that really helps operationalize smoothly”transcript, stated
“when we saw that we phrased it as a mission and not to deviate from the mission that actually resolved a lot of the issues that we found”transcript, stated

Evaluation

CARL evaluates chatbot behavior through configurable simulated conversations, scores each conversation from 1 to 10, stores logs and metrics, tracks score distributions by intent/topic, runs happy-path and bad-path tests through smoke tests and CI/CD, and samples both low-score and high-score cases for human review.

Metrics: Conversation score from 1 to 10 · Score distributions across conversations and intent types · Score changes from smoke-test and CI/CD baselines · Latency and rate-limit hits · NPS lift in beta testing · Human-reviewed low-score and sampled high-score conversations

4 supporting quotes
“10 means the conversation happened and it successfully did what the llm is meant to do”transcript, stated
“one is just looking at the distribution of individual scores across conversations and we can break them down by intent types as well”transcript, stated
“there was a significant lift that we found in our NPS with customer testing pre- curl and post curl”transcript, stated
“if we're seeing changes so part of the whole reason we stored everything in alloy DB those results is it allows us to do quick simple sequel to find changes in scores”transcript, stated

Outcomes

The production design is built for repeated operation rather than a one-time demo: scheduled smoke tests every few hours, CI/CD checks on code and business-logic changes, hundreds of conversation paths, metrics in Cloud Storage, and score-change queries in AlloyDB.

4 supporting quotes
“we got it to work with dialog flow because it had neat interactions with the web Hooks and then we also got it to run with dialog flow with the Gemini integration”transcript, stated
“it is a legitimate use case you did get the chatbot to talk like a pirate but Carl caught it”transcript, stated
“there was a significant lift that we found in our NPS with customer testing pre- curl and post curl”transcript, stated
“that's effectively our cicd for these llms”transcript, stated