Special Characteristics of AI Service CI/CD

Traditional software CI/CD focuses on "whether the code is correct" — verified through unit tests and integration tests. However, the correctness of AI services depends not only on code but also on model weights, prompts, and data — all of which are "alive" and change with version iterations. AI CI/CD requires additional verification: whether model performance has regressed (new version vs. old version on evaluation sets), whether inference latency has worsened, and whether output format remains compatible.

Automated Evaluation Pipeline

The core of AI CI/CD is automated evaluation. Recommended layered testing strategy: L1 - Functional tests (API response codes, timeouts, format correctness, completed in seconds) → L2 - Benchmark evaluation (run on 100 standard evaluation sets, compare against historical baselines, completed in minutes) → L3 - Full evaluation (run on 1000+ evaluation sets, including adversarial examples and edge cases, completed in hours). L1 runs on every commit, L2 runs on PRs, and L3 runs before release.

Evaluation Pipeline Implementation

import json, time, requests
from openai import OpenAI

client = OpenAI(api_key="your-deepseek-api-key", base_url="https://api.deepseek.com")

class AIEvaluator:
    def __init__(self, baseline_file="baseline.json"):
        self.baseline = json.load(open(baseline_file)) if baseline_file else {}
        self.results = []

    def run_eval(self, test_cases, endpoint_url):
        for tc in test_cases:
            start = time.time()
            resp = requests.post(endpoint_url, json={"prompt": tc["input"]})
            latency = time.time() - start

            if resp.status_code != 200:
                self.results.append({"test": tc["name"], "status": "FAIL",
                                     "error": f"HTTP {resp.status_code}"})
                continue

            output = resp.json()["output"]
            score = self._judge(tc, output)
            self.results.append({
                "test": tc["name"], "status": "PASS" if score >= 0.7 else "FAIL",
                "score": score, "latency_ms": round(latency*1000)
            })
        return self._summary()

    def _judge(self, test_case, output):
        prompt = f"""Evaluate AI output quality (0-1):
Input: {test_case['input']}
Expected concepts: {test_case.get('expected', [])}
Actual output: {output[:1000]}
Return JSON: {{"score":0.85}}"""
        resp = client.chat.completions.create(model="deepseek-chat",
            messages=[{"role":"user","content":prompt}], temperature=0)
        return json.loads(resp.choices[0].message.content)["score"]

    def _summary(self):
        passed = sum(1 for r in self.results if r["status"] == "PASS")
        total = len(self.results)
        avg_latency = sum(r.get("latency_ms", 0) for r in self.results) / total if total else 0
        return {
            "pass_rate": f"{passed}/{total} ({passed/total*100:.1f}%)",
            "avg_latency_ms": avg_latency,
            "regression": self._check_regression()
        }

    def _check_regression(self):
        """Compare against baseline to detect regression"""
        if not self.baseline:
            return None
        current_pass = sum(1 for r in self.results if r["status"] == "PASS")
        return current_pass / len(self.results) - self.baseline.get("pass_rate", 1)

evaluator = AIEvaluator()
tests = [{"name":"greeting","input":"你好","expected":["问候","友好"]}]
print(evaluator.run_eval(tests, "http://localhost:8000/chat"))

Performance Benchmarks and Deployment Gates

In addition to effectiveness evaluation, performance benchmarks are equally important: TTFT (time to first token, affects user experience), throughput (tokens/s, affects service capacity), P50/P95/P99 latency (tail latency affects worst-case user experience), GPU memory usage (affects deployment density and cost). Deployment gate rules: effectiveness score must not be lower than 97% of baseline, P95 latency must not exceed 120% of baseline, GPU memory usage must not exceed 110% of baseline. If gates fail, deployment is automatically blocked and the team is notified.

GitHub Actions Integration Example

Integrate AI evaluation in GitHub Actions: use self-hosted runners (with GPU) to run evaluations, cache model weights to speed up the pipeline.

Waterline, evaluation results are automatically posted as PR comments, and branch protection rules are set to require evaluation to pass before merging. For CI environments without GPU, API proxy mode can be used - the CI Runner calls the deployed evaluation service via API instead of loading the model locally.

Lifecycle Management of Evaluation Data

AI evaluation datasets are not static—they become outdated, are 'gamed', and need expansion. We have established a lifecycle management process for evaluation data: Regular review (monthly checks on whether the questions in the evaluation set are still representative, and whether new user question patterns need to be added), Model blind spot detection (analyzing cases with low user satisfaction online, abstracting typical failure modes into new evaluation cases to add to the evaluation set), Anti-cheating mechanisms (monitoring whether the model's scores on new versions of the evaluation set are artificially 'inflated'—for example, if the prompt contains keywords from the evaluation set's questions or answers), Difficulty stratification (dividing the evaluation set into Easy/Medium/Hard levels based on task difficulty, tracking the model's performance at each level separately, ensuring that improvements on simple tasks do not come at the expense of difficult tasks). This management process ensures that the evaluation set always reflects real user needs and the boundaries of model capabilities.

Confidence and Statistical Thinking in Evaluation Results

AI evaluation is not a binary 'pass/fail' judgment, but a statistical estimate with uncertainty. The difference between 85% and 90% scores on a 100-item evaluation set may just be sampling error—we cannot assert that 'the new version is better' based on that alone. The statistical rigor practices we introduced: Confidence intervals—calculate 95% confidence intervals for each evaluation metric (via Bootstrap sampling 1000 times), and only when the lower bound of the new version's confidence interval is greater than the upper bound of the old version's confidence interval do we consider it a significant improvement; Effect size—not only look at 'whether it is significant' but also 'how large the improvement is' (Cohen's d), to avoid statistically significant but practically meaningless small fluctuations; Multiple testing correction—use Benjamini-Hochberg correction when monitoring multiple evaluation metrics simultaneously to control the false discovery rate. Statistical thinking has improved decision quality—30% of past 'model upgrades' were judged as 'no significant difference' after introducing confidence interval analysis, avoiding unnecessary deployment risks.

Want to orchestrate this skill chain yourself?

Open in Skill Chain →