Conseil
Chaque exemple est fonctionnellement équivalent entre les langages. L’extrait TypeScript est déplié par défaut : sélectionnez votre langue dans les sections repliables pour voir la même logique dans le SDK correspondant.
Vue d’ensemble
Le SDK expose les données d’utilisation par le biais de deux mécanismes complémentaires :
- Événements de session : événements éphémères émis par l’environnement d’exécution au cours de l’exécution d’un tour. Abonnez-vous à ceux-ci pour obtenir des données en temps réel pour chaque appel d’API.
- Méthodes RPC : appels de requête/réponse que vous effectuez à la demande. Utilisez-les pour obtenir un instantané des totaux cumulés ou consulter le quota du compte.
Le tableau ci-dessous mappe chaque signal à l’API qui l’expose.
| Signal | API | Scope | Type |
|---|---|---|---|
| Nombre de jetons par appel | |||
événement assistant.usage | Session | Événement | |
| Utilisation de la fenêtre contextuelle | |||
événement session.usage_info | Session | Événement | |
| Répartition des fenêtres contextuelles (à la demande) | session.metadata.context | Session | RPC |
| Totaux cumulés des crédits d’IA et des jetons | session.usage.get | Session | RPC |
| Tarification des crédits IA par modèle | models.list | Serveur | RPC |
| Interactions entre le quota du compte et la version premium | account.getQuota | Serveur | RPC |
Remarque
session.usage.getMetrics, session.metadata.contextInfoet session.metadata.recomputeContextTokens sont marqués expérimentaux dans la surface RPC générée. Dans .NET, ils émettent le diagnostic expérimental GHCP001, que vous supprimez avec #pragma warning disable GHCP001 ou avec <NoWarn>GHCP001</NoWarn> au niveau du projet. Épinglez le Kit de développement logiciel (SDK) et le runtime cli Copilot si votre application en dépend.
Les tableaux de champs ci-dessous répertorient uniquement les champs utilisés dans les exemples de cette page. La référence des champs complète et toujours à jour se compose des types du SDK générés ainsi que de Événements de session de streaming, qui est régénéré à partir du schéma CLI à chaque mise à jour des dépendances. Considérez-les comme la référence et cette page comme un guide pratique.
Nombre de jetons par appel
L’événement assistant.usage est émis une fois pour chaque appel d’API de modèle à son tour (y compris les appels effectués par les sous-agents). Il indique le nombre de tokens et le multiplicateur de facturation pour cet appel uniquement.
L’exemple ci-dessous utilise ces champs. Consultez Événements de session de streaming pour obtenir la liste complète, notamment le cache, le raisonnement, la latence et les champs de suivi.
| Champ | Type | Description |
|---|---|---|
model | string | Identificateur de modèle pour cet appel |
inputTokens | number | Jetons d’entrée consommés |
outputTokens | number | Jetons de sortie produits |
cost | number | Multiplicateur de demande Premium appliqué à cet appel |
Conseil
assistant.usage est éphémère ; il est donc diffusé en direct, mais n’est pas rejoué lorsque vous reprenez une session. Pour lire les totaux cumulés a posteriori, appelez session.usage.getMetrics (voir Crédits IA et totaux de jetons cumulés).
session.on("assistant.usage", (event) => {
const { model, inputTokens, outputTokens, cost } = event.data;
console.log(
`${model}: in=${inputTokens ?? 0} out=${outputTokens ?? 0} cost=${cost ?? 0}`,
);
});
def on_usage(event):
if event.type == SessionEventType.ASSISTANT_USAGE:
data = event.data
print(f"{data.model}: in={data.input_tokens or 0} out={data.output_tokens or 0} cost={data.cost or 0}")
session.on(on_usage)
session.On(func(event copilot.SessionEvent) {
d, ok := event.Data.(*copilot.AssistantUsageData)
if !ok {
return
}
in, out, cost := int64(0), int64(0), float64(0)
if d.InputTokens != nil {
in = *d.InputTokens
}
if d.OutputTokens != nil {
out = *d.OutputTokens
}
if d.Cost != nil {
cost = *d.Cost
}
fmt.Printf("%s: in=%d out=%d cost=%g\n", d.Model, in, out, cost)
})
session.On<AssistantUsageEvent>(evt =>
{
var data = evt.Data;
Console.WriteLine(
$"{data.Model}: in={data.InputTokens ?? 0} out={data.OutputTokens ?? 0} cost={data.Cost ?? 0}");
});
session.on(AssistantUsageEvent.class, event -> {
var data = event.getData();
long in = data.inputTokens() != null ? data.inputTokens() : 0;
long out = data.outputTokens() != null ? data.outputTokens() : 0;
double cost = data.cost() != null ? data.cost() : 0.0;
System.out.printf("%s: in=%d out=%d cost=%s%n", data.model(), in, out, cost);
});
use github_copilot_sdk::session_events::AssistantUsageData;
let mut events = session.subscribe();
while let Ok(event) = events.recv().await {
if event.event_type == "assistant.usage" {
if let Some(data) = event.typed_data::<AssistantUsageData>() {
println!(
"{}: in={} out={} cost={}",
data.model,
data.input_tokens.unwrap_or(0),
data.output_tokens.unwrap_or(0),
data.cost.unwrap_or(0.0),
);
}
}
}
Utilisation de la fenêtre contextuelle
Les nombres de jetons vous indiquent ce que chaque appel a consommé. L’utilisation de la fenêtre de contexte vous indique à quel point la fenêtre de contexte du modèle est remplie actuellement, ce qui est utile pour afficher une barre de progression ou avertir l’utilisateur avant que le compactage automatique ne se déclenche.
Mises à jour en direct avec session.usage_info
Le runtime émet un session.usage_info événement chaque fois que la taille de la fenêtre de contexte change. L’exemple utilise currentTokens et tokenLimit; consultez Événements de session de streaming pour la charge utile complète.
| Champ | Type | Description |
|---|---|---|
currentTokens | number | Tokens actuellement dans la fenêtre de contexte |
tokenLimit | number | Nombre maximal de jetons pour la fenêtre de contexte du modèle |
session.on("session.usage_info", (event) => {
const { currentTokens, tokenLimit } = event.data;
const pct = Math.round((currentTokens / tokenLimit) * 100);
console.log(`Context: ${currentTokens}/${tokenLimit} (${pct}%)`);
});
def on_usage_info(event):
if event.type == SessionEventType.SESSION_USAGE_INFO:
data = event.data
pct = round(data.current_tokens / data.token_limit * 100)
print(f"Context: {data.current_tokens}/{data.token_limit} ({pct}%)")
session.on(on_usage_info)
session.On(func(event copilot.SessionEvent) {
d, ok := event.Data.(*copilot.SessionUsageInfoData)
if !ok {
return
}
pct := int(float64(d.CurrentTokens) / float64(d.TokenLimit) * 100)
fmt.Printf("Context: %d/%d (%d%%)\n", d.CurrentTokens, d.TokenLimit, pct)
})
session.On<SessionUsageInfoEvent>(evt =>
{
var pct = (int)Math.Round((double)evt.Data.CurrentTokens / evt.Data.TokenLimit * 100);
Console.WriteLine($"Context: {evt.Data.CurrentTokens}/{evt.Data.TokenLimit} ({pct}%)");
});
session.on(SessionUsageInfoEvent.class, event -> {
var data = event.getData();
long pct = Math.round((double) data.currentTokens() / data.tokenLimit() * 100);
System.out.printf("Context: %d/%d (%d%%)%n", data.currentTokens(), data.tokenLimit(), pct);
});
use github_copilot_sdk::session_events::SessionUsageInfoData;
let mut events = session.subscribe();
while let Ok(event) = events.recv().await {
if event.event_type == "session.usage_info" {
if let Some(data) = event.typed_data::<SessionUsageInfoData>() {
let pct = (data.current_tokens as f64 / data.token_limit as f64 * 100.0) as i64;
println!("Context: {}/{} ({}%)", data.current_tokens, data.token_limit, pct);
}
}
}
Décomposition à la demande avec session.metadata.contextInfo
Les événements se déclenchent uniquement lorsque le contexte change. Pour lire la répartition actuelle à tout moment, par exemple, juste après avoir repris une session, appelez session.metadata.contextInfo. Passez 0 pour promptTokenLimit afin d’utiliser la valeur par défaut de l’environnement d’exécution ; passez 0 pour outputTokenLimit si la valeur est inconnue.
Le null du résultat est contextInfo jusqu’à ce que la session ait été initialisée (l’invite système et les métadonnées de l’outil ont été mises en cache). Il décompose le total en systemTokens, conversationTokenset toolDefinitionsTokens, en même temps que le promptTokenLimit.
const { contextInfo } = await session.rpc.metadata.contextInfo({
promptTokenLimit: 0,
outputTokenLimit: 0,
});
if (contextInfo) {
console.log(
`Total ${contextInfo.totalTokens}/${contextInfo.promptTokenLimit} ` +
`(system=${contextInfo.systemTokens}, conversation=${contextInfo.conversationTokens})`,
);
}
result = await session.rpc.metadata.context_info(
MetadataContextInfoRequest(prompt_token_limit=0, output_token_limit=0)
)
info = result.context_info
if info is not None:
print(
f"Total {info.total_tokens}/{info.prompt_token_limit} "
f"(system={info.system_tokens}, conversation={info.conversation_tokens})"
)
result, _ := session.RPC.Metadata.ContextInfo(ctx, &rpc.MetadataContextInfoRequest{
PromptTokenLimit: 0,
OutputTokenLimit: 0,
})
if info := result.ContextInfo; info != nil {
fmt.Printf("Total %d/%d (system=%d, conversation=%d)\n",
info.TotalTokens, info.PromptTokenLimit, info.SystemTokens, info.ConversationTokens)
}
var result = await session.Rpc.Metadata.ContextInfoAsync(promptTokenLimit: 0, outputTokenLimit: 0);
var info = result.ContextInfo;
if (info is not null)
{
Console.WriteLine(
$"Total {info.TotalTokens}/{info.PromptTokenLimit} " +
$"(system={info.SystemTokens}, conversation={info.ConversationTokens})");
}
var result = session.getRpc().metadata
.contextInfo(new SessionMetadataContextInfoParams(null, 0L, 0L, null))
.join();
var info = result.contextInfo();
if (info != null) {
System.out.printf("Total %d/%d (system=%d, conversation=%d)%n",
info.totalTokens(), info.promptTokenLimit(), info.systemTokens(), info.conversationTokens());
}
use github_copilot_sdk::rpc::MetadataContextInfoRequest;
let result = session
.rpc()
.metadata()
.context_info(MetadataContextInfoRequest {
prompt_token_limit: 0,
output_token_limit: 0,
selected_model: None,
})
.await?;
if let Some(info) = result.context_info {
println!(
"Total {}/{} (system={}, conversation={})",
info.total_tokens, info.prompt_token_limit, info.system_tokens, info.conversation_tokens,
);
}
Totaux cumulés des crédits d’IA et des jetons
session.usage.getMetrics retourne les totaux cumulés de toute la session en un seul appel. C’est la façon la plus claire de consulter le coût en crédits IA, car elle agrège tous les appels à l’API (agent principal et sous-agents) pour vous.
L’exemple utilise les champs ci-dessous. Le type généré UsageGetMetricsResult est la référence complète.
| Champ | Type | Description |
|---|---|---|
totalNanoAiu | number | Coût en crédits IA sur l’ensemble de la session, en nano-unités d’IA |
total | number | Coût de la demande Premium sur tous les modèles, après les multiplicateurs |
modelMetrics | Record<string, ModelMetric> | Répartition par modèle ; chaque entrée a usage.inputTokens, usage.outputet totalNanoAiu |
Remarque
Le coût est signalé dans les unités nano-IA (le champ est nommé totalNanoAiu). La conversion exacte en crédits d’IA et la signification exacte du décompte des requêtes premium sont définies par la facturation de GitHub Copilot, et non par le SDK ; considérez la documentation de facturation de GitHub Copilot comme la référence faisant foi et vérifiez-la avant d’afficher aux utilisateurs des valeurs assimilables à des montants. Les exemples divisent les valeurs par 1e9 par souci de simplicité, conformément au préfixe SI nano ; vérifiez que cela correspond à la facturation actuelle avant de vous y fier. Les mappages modelMetrics et tokenDetails ont pour clés des chaînes définies à l’exécution (identifiants de modèle et noms de types de jeton) que le système de types SDK ne valide pas.
const metrics = await session.rpc.usage.getMetrics();
const aiCredits = (metrics.totalNanoAiu ?? 0) / 1e9;
console.log(`AI credits used: ${aiCredits.toFixed(6)}`);
console.log(`Premium requests: ${metrics.totalPremiumRequestCost}`);
for (const [model, m] of Object.entries(metrics.modelMetrics)) {
if (!m) continue;
console.log(
`${model}: in=${m.usage.inputTokens} out=${m.usage.outputTokens} ` +
`nanoAiu=${m.totalNanoAiu ?? 0}`,
);
}
metrics = await session.rpc.usage.get_metrics()
ai_credits = (metrics.total_nano_aiu or 0) / 1e9
print(f"AI credits used: {ai_credits:.6f}")
print(f"Premium requests: {metrics.total_premium_request_cost}")
for model, m in metrics.model_metrics.items():
print(f"{model}: in={m.usage.input_tokens} out={m.usage.output_tokens} nanoAiu={m.total_nano_aiu or 0}")
metrics, _ := session.RPC.Usage.GetMetrics(ctx)
aiCredits := float64(0)
if metrics.TotalNanoAiu != nil {
aiCredits = *metrics.TotalNanoAiu / 1e9
}
fmt.Printf("AI credits used: %.6f\n", aiCredits)
fmt.Printf("Premium requests: %v\n", metrics.TotalPremiumRequestCost)
for model, m := range metrics.ModelMetrics {
nanoAiu := float64(0)
if m.TotalNanoAiu != nil {
nanoAiu = *m.TotalNanoAiu
}
fmt.Printf("%s: in=%d out=%d nanoAiu=%v\n", model, m.Usage.InputTokens, m.Usage.OutputTokens, nanoAiu)
}
var metrics = await session.Rpc.Usage.GetMetricsAsync();
var aiCredits = (metrics.TotalNanoAiu ?? 0) / 1e9;
Console.WriteLine($"AI credits used: {aiCredits:F6}");
Console.WriteLine($"Premium requests: {metrics.TotalPremiumRequestCost}");
foreach (var (model, m) in metrics.ModelMetrics)
{
Console.WriteLine(
$"{model}: in={m.Usage.InputTokens} out={m.Usage.OutputTokens} nanoAiu={m.TotalNanoAiu ?? 0}");
}
var metrics = session.getRpc().usage.getMetrics().join();
double aiCredits = metrics.totalNanoAiu() != null ? metrics.totalNanoAiu() / 1e9 : 0;
System.out.printf("AI credits used: %.6f%n", aiCredits);
System.out.printf("Premium requests: %s%n", metrics.totalPremiumRequestCost());
metrics.modelMetrics().forEach((model, m) -> {
double nanoAiu = m.totalNanoAiu() != null ? m.totalNanoAiu() : 0;
System.out.printf("%s: in=%d out=%d nanoAiu=%s%n",
model, m.usage().inputTokens(), m.usage().outputTokens(), nanoAiu);
});
let metrics = session.rpc().usage().get_metrics().await?;
let ai_credits = metrics.total_nano_aiu.unwrap_or(0.0) / 1e9;
println!("AI credits used: {ai_credits:.6}");
println!("Premium requests: {}", metrics.total_premium_request_cost);
for (model, m) in &metrics.model_metrics {
let nano_aiu = m.total_nano_aiu.unwrap_or(0.0);
println!(
"{model}: in={} out={} nanoAiu={nano_aiu}",
m.usage.input_tokens, m.usage.output_tokens,
);
}
Tarification des crédits IA par modèle
Pour estimer le coût avant d’effectuer un tour, consultez le prix des jetons de chaque modèle dans models.list. Il s’agit d’un appel de portée serveur côté client, il ne nécessite donc pas de session. Les prix sont exprimés en crédits IA par lot de jetons facturé. Le type généré ModelBillingTokenPrices répertorie chaque champ, y compris cachePrice.
| Champ | Type | Description |
|---|---|---|
billing.multiplier | number | Multiplicateur de coût de la demande Premium par rapport au taux de base |
billing.token | number | Coût de crédit IA par lot de jetons d’entrée |
billing.token | number | Coût en crédits d’IA par lot de jetons de sortie |
billing.token | number | Nombre de jetons par lot de facturation |
Remarque
Les valeurs de prix changent à mesure que les plans et les modèles évoluent. Lisez-les au moment de l’exécution, comme indiqué ci-dessous ; ne codez jamais en dur les nombres dans votre application.
const { models } = await client.rpc.models.list({});
for (const model of models) {
const prices = model.billing?.tokenPrices;
if (!prices) continue;
console.log(
`${model.id}: input=${prices.inputPrice} output=${prices.outputPrice} ` +
`per ${prices.batchSize} tokens (x${model.billing?.multiplier ?? 1})`,
);
}
result = await client.rpc.models.list(ModelsListRequest())
for model in result.models:
prices = model.billing.token_prices if model.billing else None
if prices is None:
continue
multiplier = model.billing.multiplier if model.billing else 1
print(
f"{model.id}: input={prices.input_price} output={prices.output_price} "
f"per {prices.batch_size} tokens (x{multiplier})"
)
list, _ := client.RPC.Models.List(ctx, &rpc.ModelsListRequest{})
for _, model := range list.Models {
if model.Billing == nil || model.Billing.TokenPrices == nil {
continue
}
prices := model.Billing.TokenPrices
multiplier := 1.0
if model.Billing.Multiplier != nil {
multiplier = *model.Billing.Multiplier
}
in, out := 0.0, 0.0
if prices.InputPrice != nil {
in = *prices.InputPrice
}
if prices.OutputPrice != nil {
out = *prices.OutputPrice
}
batch := int64(0)
if prices.BatchSize != nil {
batch = *prices.BatchSize
}
fmt.Printf("%s: input=%v output=%v per %d tokens (x%v)\n", model.ID, in, out, batch, multiplier)
}
var list = await client.Rpc.Models.ListAsync();
foreach (var model in list.Models)
{
var prices = model.Billing?.TokenPrices;
if (prices is null) continue;
Console.WriteLine(
$"{model.Id}: input={prices.InputPrice} output={prices.OutputPrice} " +
$"per {prices.BatchSize} tokens (x{model.Billing?.Multiplier ?? 1})");
}
var list = client.getRpc().models.list().join();
for (var model : list.models()) {
var billing = model.billing();
if (billing == null || billing.tokenPrices() == null) {
continue;
}
var prices = billing.tokenPrices();
double multiplier = billing.multiplier() != null ? billing.multiplier() : 1;
System.out.printf("%s: input=%s output=%s per %d tokens (x%s)%n",
model.id(), prices.inputPrice(), prices.outputPrice(), prices.batchSize(), multiplier);
}
let list = client.rpc().models().list().await?;
for model in &list.models {
let Some(billing) = &model.billing else { continue };
let Some(prices) = &billing.token_prices else { continue };
let multiplier = billing.multiplier.unwrap_or(1.0);
println!(
"{}: input={} output={} per {} tokens (x{multiplier})",
model.id,
prices.input_price.unwrap_or(0.0),
prices.output_price.unwrap_or(0.0),
prices.batch_size.unwrap_or(0),
);
}
Interactions entre le quota du compte et la version premium
account.getQuota indique le quota Copilot restant de l’utilisateur authentifié. La table quotaSnapshots du résultat est indexée par type de quota, généralement premium_interactions, chat et completions. Utilisez-le pour montrer aux utilisateurs la quantité de leur allocation mensuelle restante ou pour effectuer un travail avant d’atteindre une limite.
L’exemple utilise les champs ci-dessous ; le type généré AccountQuotaSnapshot est la référence complète. Les quotaSnapshots clés sont des chaînes d’exécution que le système de type du Kit de développement logiciel (SDK) ne valide pas. Par conséquent, protégez vos recherches.
| Champ | Type | Description |
|---|---|---|
entitlement | number | Demandes incluses dans le forfait, ou -1 pour un nombre illimité |
usedRequests | number | Requêtes utilisées jusqu’à présent pendant cette période |
remaining | number | Pourcentage du droit restant |
resetDate | string | Date de réinitialisation du quota ISO 8601 |
Conseil
Pour lire le quota pour un utilisateur spécifique plutôt que le contexte d'authentification global de la connexion (par exemple, dans un serveur principal multilocataire), transmettez le jeton GitHub de cet utilisateur à getQuota. Consultez « Multilocataire et déploiements de serveurs ».
const { quotaSnapshots } = await client.rpc.account.getQuota({});
const premium = quotaSnapshots["premium_interactions"];
if (premium) {
console.log(
`Premium interactions: ${premium.usedRequests}/${premium.entitlementRequests} ` +
`(${premium.remainingPercentage.toFixed(1)}% left, resets ${premium.resetDate ?? "n/a"})`,
);
}
result = await client.rpc.account.get_quota(AccountGetQuotaRequest())
premium = result.quota_snapshots.get("premium_interactions")
if premium is not None:
print(
f"Premium interactions: {premium.used_requests}/{premium.entitlement_requests} "
f"({premium.remaining_percentage:.1f}% left, resets {premium.reset_date or 'n/a'})"
)
result, _ := client.RPC.Account.GetQuota(ctx, &rpc.AccountGetQuotaRequest{})
if premium, ok := result.QuotaSnapshots["premium_interactions"]; ok {
resets := "n/a"
if premium.ResetDate != nil {
resets = premium.ResetDate.Format(time.RFC3339)
}
fmt.Printf("Premium interactions: %d/%d (%.1f%% left, resets %s)\n",
premium.UsedRequests, premium.EntitlementRequests, premium.RemainingPercentage, resets)
}
var result = await client.Rpc.Account.GetQuotaAsync();
if (result.QuotaSnapshots.TryGetValue("premium_interactions", out var premium))
{
Console.WriteLine(
$"Premium interactions: {premium.UsedRequests}/{premium.EntitlementRequests} " +
$"({premium.RemainingPercentage:F1}% left, resets {premium.ResetDate?.ToString("o") ?? "n/a"})");
}
var result = client.getRpc().account.getQuota().join();
var premium = result.quotaSnapshots().get("premium_interactions");
if (premium != null) {
System.out.printf("Premium interactions: %d/%d (%.1f%% left, resets %s)%n",
premium.usedRequests(), premium.entitlementRequests(),
premium.remainingPercentage(), premium.resetDate());
}
let result = client.rpc().account().get_quota().await?;
if let Some(premium) = result.quota_snapshots.get("premium_interactions") {
let resets = premium.reset_date.as_deref().unwrap_or("n/a");
println!(
"Premium interactions: {}/{} ({:.1}% left, resets {resets})",
premium.used_requests, premium.entitlement_requests, premium.remaining_percentage,
);
}
Choix de l’API appropriée
Utilisez ce résumé pour déterminer l’API qui correspond à votre cas d’usage :
-
**Afficher un coût en temps réel ou un compteur de jetons pendant l’exécution d’un tour** : abonnez-vous à `assistant.usage` et `session.usage_info`. - Afficher un résumé des coûts finals après un tour ou une session : appel
session.usage.getMetrics. - Afficher l’utilisation de la fenêtre contextuelle lors de la reprise, avant tout nouveau tour : appel
session.metadata.contextInfo. - Estimer le coût avant l’exécution du travail : lire
models.listles prix des jetons. - Avertir les utilisateurs avant qu’ils n’épuisent leur plan : appel
account.getQuota.
Lectures complémentaires
- Événements de session de streaming : référence au niveau du champ complet pour
assistant.usage,session.usage_infoet chaque autre événement de session - Observabilité : exporter des données d’utilisation vers OpenTelemetry pour l’attribution des coûts
- Multilocataire et déploiements de serveurs : résoudre le quota et les modèles par utilisateur avec un jeton GitHub