Service d’évaluation Gen AI de Vertex AI

La fonctionnalité vertex-eval relie adk-eval au service d’évaluation Gen AI de Vertex AI. Les jugements fondés sur des modèles sont exécutés par l’autorater du service plutôt que par un LLM local, et les trajectoires des outils sont évaluées par les métriques de trajectoire basées sur le calcul du service. Chaque appel est un POST unique vers projects.locations:evaluateInstances (v1beta1).

Configuration

[dependencies]
adk-eval = { version = "2.1.0", features = ["vertex-eval"] }

L’authentification utilise les identifiants par défaut de l’application (gcloud auth application-default login ou l’identité de charge de travail d’un conteneur déployé). L’appelant a besoin de l’autorisation aiplatform.endpoints.predict (roles/aiplatform.user).

Variable d’environnementObjet
GOOGLE_CLOUD_PROJECTProjet GCP pour VertexEvalConfig::from_env
GOOGLE_CLOUD_LOCATIONRégion, par ex. us-central1

Juge adossé à un service

VertexEvalJudge reproduit l'interface d'évaluation de LlmJudge — mêmes noms de méthodes, mêmes types de résultats — et s'intègre donc au code écrit pour le juge local :

use adk_eval::{VertexEvalClient, VertexEvalConfig, VertexEvalJudge};
use adk_eval::criteria::{Rubric, RubricConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = VertexEvalConfig::from_env()?;
    let judge = VertexEvalJudge::new(VertexEvalClient::new_with_adc(config)?);

    // Semantic equivalence (pointwiseMetricInput under the hood)
    let result = judge
        .semantic_match("The capital is Paris", "Paris is the capital of France", None)
        .await?;
    println!("score={} equivalent={}", result.score, result.equivalent);

    // Rubric-based quality, weight-normalized like LlmJudge
    let rubrics = RubricConfig {
        rubrics: vec![
            Rubric::new("Accuracy", "Response is factually correct").with_weight(2.0),
            Rubric::new("Clarity", "Response is easy to follow"),
        ],
    };
    let quality = judge.evaluate_rubrics("agent output", "task context", &rubrics).await?;
    println!("overall={}", quality.overall_score);

    // Safety and hallucination checks
    let safety = judge.evaluate_safety("agent output").await?;
    let hallucination = judge
        .detect_hallucinations("agent output", "provided context", Some("ground truth"))
        .await?;
    println!("safe={} grounded={}", safety.is_safe, hallucination.hallucination_free);
    Ok(())
}

Différences par rapport à LlmJudge, toutes deux dues au fait que le service renvoie une paire {score, explanation} par jugement :

  • Les verdicts booléens (equivalent, is_safe, hallucination_free) sont dérivés du score — une valeur supérieure ou égale à 0.5 est considérée comme une réussite.
  • issues contient l'explication du service sous la forme d'une seule entrée au lieu d'une liste analysée.

Métriques de trajectoire

VertexEvalClient::evaluate_trajectory mappe les valeurs adk-eval ToolUse sur la structure Trajectory du format filaire (name → toolName, args → JSON-encodé toolInput) et renvoie le score :

TrajectoryMetricSignification
ExactMatch1 si les trajectoires correspondent exactement, sinon 0
InOrderMatch1 si tous les appels d’outils de référence apparaissent dans l’ordre, sinon 0
AnyOrderMatch1 si tous les appels d’outils de référence apparaissent dans n’importe quel ordre, sinon 0
PrecisionPrécision moyenne des appels d’outils prédits
RecallRappel moyen des appels d’outils de référence
use adk_eval::{TrajectoryMetric, VertexEvalClient, VertexEvalConfig};
use adk_eval::schema::ToolUse;
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = VertexEvalClient::new_with_adc(VertexEvalConfig::from_env()?)?;

    let predicted = vec![ToolUse::new("get_weather").with_args(json!({ "city": "Paris" }))];
    let reference = predicted.clone();

    let score = client
        .evaluate_trajectory(TrajectoryMetric::ExactMatch, &predicted, &reference)
        .await?;
    assert_eq!(score, 1.0);
    Ok(())
}

Configuration du modèle juge

AutoraterConfig sélectionne le modèle juge et l’échantillonnage pour les métriques fondées sur un modèle ; le serveur l’ignore pour les métriques fondées sur le calcul :

use adk_eval::{AutoraterConfig, VertexEvalClient, VertexEvalConfig};

fn build() -> adk_core::Result<VertexEvalClient> {
    let client = VertexEvalClient::new_with_adc(VertexEvalConfig::from_env()?)?
        .with_autorater_config(
            AutoraterConfig::new()
                .with_autorater_model(
                    "projects/p/locations/us-central1/publishers/google/models/gemini-3.7-flash",
                )
                .with_sampling_count(1),
        );
    Ok(client)
}

Métriques personnalisées

evaluate_pointwise accepte n’importe quel PointwiseMetricSpec — le metricPromptTemplate contient des variables {placeholder} rendues côté serveur à partir de l’objet d’instance :

use adk_eval::{PointwiseMetricSpec, VertexEvalClient, VertexEvalConfig};
use serde_json::json;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = VertexEvalClient::new_with_adc(VertexEvalConfig::from_env()?)?;

    let spec = PointwiseMetricSpec::new(
        "Rate the politeness of the response from 0.0 to 1.0.\n\nResponse:\n{response}",
    );
    let result = client
        .evaluate_pointwise(&spec, &json!({ "response": "Thanks for asking!" }))
        .await?;
    println!("score={:?} explanation={:?}", result.score, result.explanation);
    Ok(())
}

evaluate_instances constitue le mécanisme de dernier recours brut : il envoie une requête POST avec n’importe quel corps EvaluateInstancesRequest et renvoie la réponse brute, donnant accès à toutes les autres métriques prises en charge par le service (BLEU, ROUGE, par paires, métriques d’appels d’outils).

Gestion des erreurs

Les erreurs sont des valeurs structurées AdkError avec le composant eval et des codes eval.vertex.* (eval.vertex.rate_limited, eval.vertex.unauthorized, eval.vertex.invalid_response, ...). Les méthodes VertexEvalJudge renvoient le EvalError::JudgeError du crate, conformément à LlmJudge.

Voir aussi