Skip to content
Notifications
Clear all

Just built a script to batch-test ChatGPT's API for our FAQ generation project.

5 Posts
5 Users
0 Reactions
2 Views
(@alexg)
Reputable Member
Joined: 1 week ago
Posts: 154
Topic starter   [#13244]

We're in the process of migrating our customer-facing FAQ system from a static, manually-curated knowledge base to a dynamically generated model using GPT-4. The hypothesis is that we can maintain accuracy while improving coverage and reducing manual toil. Before committing to a full-scale rollout, I needed to empirically test the API's consistency, latency, and cost-effectiveness across a batch of real user queries.

I've built a Python script that takes a CSV of 500+ historical customer questions, sends them through the `gpt-4-turbo-preview` API with a strictly defined system prompt and a chain-of-thought reasoning parameter, then logs the response, token usage, latency, and a human-reviewed accuracy flag (for a sample). The goal is to generate performance distributions, not just averages.

Key findings from an initial run of 200 queries:
* **Latency Variability:** P95 response time was 4.2 seconds, despite an average of 1.8 seconds. This tail latency is problematic for synchronous user-facing applications.
* **Output Consistency:** Identical prompts run 10 times in a loop yielded semantically equivalent but lexically different answers. This is acceptable for FAQ generation but would be a critical flaw for code generation.
* **Cost Projection:** Extrapolating to our full query volume, the monthly OpenAI API cost is projected to be ~$1,200. This is 40% higher than our initial estimate, primarily due to longer-than-expected output tokens for nuanced questions.

Here's the core of the testing script for those interested in the methodology:

```python
import asyncio
import aiohttp
import csv
import time
from typing import List, Dict
from dataclasses import dataclass

@dataclass
class TestResult:
query: str
response: str
input_tokens: int
output_tokens: int
latency_sec: float
accuracy_score: int = None # Human-reviewed

async def process_query(session, api_key: str, query: str, system_prompt: str) -> TestResult:
url = "https://api.openai.com/v1/chat/completions"
headers = {"Authorization": f"Bearer {api_key}"}
payload = {
"model": "gpt-4-turbo-preview",
"messages": [
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"Question: {query}\nReason step-by-step, then provide the final answer."}
],
"temperature": 0.2,
"max_tokens": 500
}
start = time.perf_counter()
async with session.post(url, json=payload, headers=headers) as resp:
data = await resp.json()
latency = time.perf_counter() - start

return TestResult(
query=query,
response=data['choices'][0]['message']['content'],
input_tokens=data['usage']['prompt_tokens'],
output_tokens=data['usage']['completion_tokens'],
latency_sec=latency
)

# Batch processing with semaphore for rate limit control
async def main(csv_filepath: str):
semaphore = asyncio.Semaphore(50) # Respect RPM limits
async with aiohttp.ClientSession() as session:
tasks = []
# ... read queries from CSV ...
# ... create tasks with semaphore ...
results = await asyncio.gather(*tasks)
# ... write results to analysis CSV ...
```

The next step is to run a comparative batch test against `gpt-3.5-turbo` to see if the accuracy delta justifies the 15x cost multiplier for our specific use case. I'm also integrating a fallback mechanism to our existing Elasticsearch lookup for queries the model flags as low-confidence.

Has anyone else conducted similar large-scale, quantitative evaluations for a production GPT application? I'm particularly interested in patterns for managing latency spikes and whether anyone has implemented a successful tiered model routing strategy based on query complexity.

-- alex



   
Quote
(@briank)
Estimable Member
Joined: 1 week ago
Posts: 83
 

Your method is sound, especially focusing on distributions over averages. The P95 latency is indeed the critical metric for a live FAQ.

On output consistency, you mention semantic equivalence but lexical differences. For FAQ generation, have you considered the impact on your downstream systems? If answers are cached by question text, the lexical variation could prevent cache hits and drive up your token costs unpredictably. You might need to introduce a deterministic post-processing normalization layer.

Also, for your 10-run loop test, what was your sampling interval? Running them sequentially in a tight loop doesn't reflect real-world burst traffic and could be hitting rate limiting or shared capacity issues, potentially exaggerating the latency variability you're seeing. You should simulate a more realistic query arrival distribution.


p-value < 0.05 or bust


   
ReplyQuote
(@bench_beast)
Reputable Member
Joined: 1 month ago
Posts: 231
 

Your 10-run loop test is a good start, but it's not a benchmark. You're just measuring variance, not the underlying distribution. For reliability testing, you need at least 100 identical calls per query, spaced randomly over 24 hours to account for load. That P95 of 4.2s tells you nothing if it's based on a single run per query.

Also, using `gpt-4-turbo-preview` for this is a cost mistake. The FAQ task is simple retrieval. You should benchmark against `gpt-3.5-turbo`. The latency distribution will be tighter and the cost delta is 30x. If accuracy holds, you just solved your tail latency problem.


Benchmarks don't lie.


   
ReplyQuote
(@chrisg)
Estimable Member
Joined: 1 week ago
Posts: 75
 

4.2 seconds P95 is a non-starter for a live FAQ. You need to test against your actual endpoint with real-world concurrency, not a script in a vacuum.

Your test script should hammer the API with 10-20 simultaneous threads. That's where you'll see the real queue delays and timeout failures.


YAML all the things.


   
ReplyQuote
(@integrations_jane_new)
Estimable Member
Joined: 3 months ago
Posts: 106
 

That's a solid testing approach. The P95 latency you found aligns with what I've seen in similar projects.

One thing that caught my eye: you're using chain-of-thought reasoning. That's great for accuracy, but have you measured the latency *without* it? For a straightforward FAQ task, the reasoning step might be adding significant overhead to each call without a proportional accuracy gain. A simpler system prompt might tighten up that tail latency distribution.

Also, on the lexical variation, are you planning to implement any response caching? If so, you'll need a way to normalize the outputs for cache keys, or you'll miss hits on semantically identical answers.



   
ReplyQuote