如何拿到接口返回的消耗token
SemanticKernel
以下引用自官方案例
- Text模型
- 使用Kernel
FunctionResult functionResult = await kernel.InvokePromptAsync(promptTestDataGeneration); CompletionsUsage? usage = FunctionResult.Metadata?["Usage"] as CompletionsUsage; //回答消耗的Token Console.WriteLine(usage.CompletionTokens); //提示词消耗的Token Console.WriteLine(usage.PromptTokens); //一共消耗的Token Console.WriteLine(usage.TotalTokens); ```
- 直接使用AzureOpenAIChatCompletionService
var service = new AzureOpenAIChatCompletionService("deployment", "https://endpoint", "api-key", "model-id", this._httpClient); var result = await service.GetChatMessageContentsAsync([], settings, kernel); var usage = result[0].Metadata?["Usage"] as CompletionsUsage; //回答消耗的Token Console.WriteLine(usage.CompletionTokens); //提示词消耗的Token Console.WriteLine(usage.PromptTokens); //一共消耗的Token Console.WriteLine(usage.TotalTokens); ```
- 使用Kernel
- 暂不支持Embedding模型
客制方法
- 当前SK仅支持OpenAI和AzureOpenAI的模型调用,如何需要其他模型供应商目前有两种办法解决
- 使用OneAPI做一个中转成AzureOpenAI然后使用上述SK的方法使用。
- 自定义方法发送请求,使用AddKeyedSingleton注入。
-
定义IAzureTextEmbeddingCompletionService接口,引用ITextEmbeddingGenerationService
public interface IAzureTextEmbeddingCompletionService : ITextEmbeddingGenerationService { Task<(List<float>, TextEmbeddingUsage)> GenerateEmbeddingsByUsageAsync(IList<string> data, Kernel kernel = null, CancellationToken cancellationToken = default); }
-
定义AzureTextEmbeddingCompletionService实现IAzureTextEmbeddingCompletionService接口
public class AzureTextEmbeddingCompletionService : IAzureTextEmbeddingCompletionService { private readonly SemanticAzureOpenAIConfig config; private readonly Dictionary<string, object?> _attributes = new(); private readonly ModelClient client; public IReadOnlyDictionary<string, object> Attributes => _attributes; public AzureTextEmbeddingCompletionService(ModelOptions options) { config = new SemanticAzureOpenAIConfig() { ApiKey = options.ApiKey, Endpoint = options.Endpoint, DeploymentName = "text-embedding-ada-002", ApiVersion = options.ModelVersion }; client = new(config.ApiKey, ModelType.AzureOpenAI, config.Endpoint); } public async Task<IList<ReadOnlyMemory<float>>> GenerateEmbeddingsAsync(IList<string> data, Kernel kernel = null, CancellationToken cancellationToken = default) { var result = await client.AzureOpenAI.GenerateEmbeddingsAsync(config.DeploymentName, data.First()); var list = result.Data[0].Embedding.ToList(); IList<ReadOnlyMemory<float>> readOnlyMemoryList = list.Select(f => new ReadOnlyMemory<float>(new[] { f })).ToList(); return readOnlyMemoryList; } public async Task<(List<float>, TextEmbeddingUsage)> GenerateEmbeddingsByUsageAsync(IList<string> data, Kernel kernel = null, CancellationToken cancellationToken = default) { var result = await client.AzureOpenAI.GenerateEmbeddingsAsync(config.DeploymentName, data.First()); var list = result.Data[0].Embedding.ToList(); IList<ReadOnlyMemory<float>> readOnlyMemoryList = list.Select(f => new ReadOnlyMemory<float>(new[] { f })).ToList(); return (list, result.Usage); } } //定义入参类 public class ModelOptions { public string AppId { get; set; } public string ApiKey { get; set; } public string ApiSecret { get; set; } public string Endpoint { get; set; } public string DeploymentName { get; set; } public ChatHistory ChatHistory { get; set; } = new ChatHistory(); public string ModelVersion { get; set; } }
-
ModelClient的实现参考对话模型的对接方式实现,原理是一致的这里不详述。(.Net接入AzureOpenAI、OpenAI、通义千问、智谱AI、讯飞星火、文心一言大语言模型。 | FaceMan)
-
创建Kernel实例,注入IAzureTextEmbeddingCompletionService服务
var builder = Kernel.CreateBuilder(); var options = new ModelOptions() { Endpoint = "YourEndpoint", ApiKey = "YourApiKey", DeploymentName = "YourDeploymentName",, ChatHistory = "YourChatHistory",//Embedding可不填 }; builder.Services.AddKeyedSingleton<IAzureTextEmbeddingCompletionService>("AzureOpenAIEmbedding", new AzureTextEmbeddingCompletionService(options));
-
获取Embedding服务,获取Token
var service = _kernel.GetRequiredService<IAzureTextEmbeddingCompletionService>(); var res = await service.GenerateEmbeddingsByUsageAsync (new List<string> { partitionContent }, cancellationToken: cancellationToken) .ConfigureAwait(false); // item1 向量,item2消耗的token float[] result = res.Item1.ToArray<float>(); totalToken += res.Item2.TotalTokens; Embedding embedding = new Embedding(result);
-