当前位置:首页 > AI > 正文内容

完成阿里云模型服务灵积 DashScope 的 Semantic Kernel Connector

邻居的猫1个月前 (12-09)AI1427

Semantic Kernel 内置的 IChatCompletionService 完结只支撑 OpenAI 与 Azure OpenAI,而我却计划结合 DashScope(阿里云模型服务灵积) 学习 Semantic Kernel。

所以决议自己着手完结一个支撑 DashScope 的 Semantic Kernel Connector —— DashScopeChatCompletionService,完结的进程也是学习 Semantic Kernel 源码的进程,
并且凭借 Sdcb.DashScope,完结变得更简单了,详见前一篇博文 凭借 .NET 开源库 Sdcb.DashScope 调用阿里云灵积通义千问 API

这儿只完结用于调用 chat completion 服务的 connector,所以只需完结 IChatCompletionService 接口,该接口承继了 IAIService 接口,总共需求完结2个办法+1个特点。

public sealed class DashScopeChatCompletionService : IChatCompletionService
{
    public IReadOnlyDictionary<string, object?> Attributes { get; }

    public Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }
}

先完结 GetChatMessageContentsAsync 办法,调用 Kernel.InvokePromptAsync 办法时会用到这个办法。

完结起来比较简单,便是易手生意:

  • 把 Semantic Kernel 的 ChatHistory 转化为 Sdcb.DashScope 的 IReadOnlyList<ChatMessage>
  • 把 Semantic Kernel 的 PromptExecutionSettings 转化为 Sdcb.DashScope 的 ChatParameters
  • 把 Sdcb.DashScope 的 ResponseWrapper<ChatOutput, ChatTokenUsage> 转化为 Semantic Kernel 的 IReadOnlyList<ChatMessageContent>

完结代码如下:

public async Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, CancellationToken cancellationToken = default)
{
    var chatMessages = chatHistory
        .Where(x => !string.IsNullOrEmpty(x.Content))
        .Select(x => new ChatMessage(x.Role.ToString(), x.Content!)).
        ToList();

    ChatParameters? chatParameters = null;
    if (executionSettings?.ExtensionData?.Count > 0)
    {
        var json = JsonSerializer.Serialize(executionSettings.ExtensionData);
        chatParameters = JsonSerializer.Deserialize<ChatParameters>(
            json,
            new JsonSerializerOptions { NumberHandling = JsonNumberHandling.AllowReadingFromString });
    }

    var response = await _dashScopeClient.TextGeneration.Chat(_modelId, chatMessages, chatParameters, cancellationToken);

    return [new ChatMessageContent(new AuthorRole(chatMessages.First().Role), response.Output.Text)];
}

接下来完结 GetStreamingChatMessageContentsAsync,调用 Kernel.InvokePromptStreamingAsync 时会用到它,相同也是易手生意。

ChatHistoryPromptExecutionSettings 参数的转化与 GetChatMessageContentsAsync 相同,所以引进2个扩展办法 ChatHistory.ToChatMessagesPromptExecutionSettings.ToChatParameters 削减重复代码,别的需求将 ChatParameters.IncrementalOutput 设置为 true

不同之处是返回值类型,需求将 Sdcb.DashScope 的 IAsyncEnumerable<ResponseWrapper<ChatOutput, ChatTokenUsage>> 转化为 IAsyncEnumerable<StreamingChatMessageContent>

完结代码如下:

public async IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(
    ChatHistory chatHistory,
    PromptExecutionSettings? executionSettings = null,
    Kernel? kernel = null,
    [EnumeratorCancellation] CancellationToken cancellationToken = default)
{
    var chatMessages = chatHistory.ToChatMessages();
    var chatParameters = executionSettings?.ToChatParameters() ?? new ChatParameters();
    chatParameters.IncrementalOutput = true;

    var responses = _dashScopeClient.TextGeneration.ChatStreamed(_modelId, chatMessages, chatParameters, cancellationToken);

    await foreach (var response in responses)
    {
        yield return new StreamingChatMessageContent(new AuthorRole(chatMessages[0].Role), response.Output.Text);
    }
}

到这儿2个办法就完结好了,还剩余很简单完结的1个特点,轻松搞定

public sealed class DashScopeChatCompletionService : IChatCompletionService
{
    private readonly DashScopeClient _dashScopeClient;
    private readonly string _modelId;
    private readonly Dictionary<string, object?> _attribues = [];

    public DashScopeChatCompletionService(
        IOptions<DashScopeClientOptions> options,
        HttpClient httpClient)
    {
        _dashScopeClient = new(options.Value.ApiKey, httpClient);
        _modelId = options.Value.ModelId;
        _attribues.Add(AIServiceExtensions.ModelIdKey, _modelId);
    }

    public IReadOnlyDictionary<string, object?> Attributes => _attribues;
}

到此,DashScopeChatCompletionService 的完结就完结了。

接下来,完结一个扩展办法,将 DashScopeChatCompletionService 注册到依靠注入容器

public static class DashScopeServiceCollectionExtensions
{
    public static IKernelBuilder AddDashScopeChatCompletion(
        this IKernelBuilder builder,
        string? serviceId = null,
        Action<HttpClient>? configureClient = null,
        string configSectionPath = "dashscope")
    {
        Func<IServiceProvider, object?, DashScopeChatCompletionService> factory = (serviceProvider, _) =>
            serviceProvider.GetRequiredService<DashScopeChatCompletionService>();

        if (configureClient == null)
        {
            builder.Services.AddHttpClient<DashScopeChatCompletionService>();
        }
        else
        {
            builder.Services.AddHttpClient<DashScopeChatCompletionService>(configureClient);
        }

        builder.Services.AddOptions<DashScopeClientOptions>().BindConfiguration(configSectionPath);
        builder.Services.AddKeyedSingleton<IChatCompletionService>(serviceId, factory);
        return builder;
    }
}

为了便利经过装备文件装备 ModelId 与 ApiKey,引进了 DashScopeClientOptions

public class DashScopeClientOptions : IOptions<DashScopeClientOptions>
{
    public string ModelId { get; set; } = string.Empty;

    public string ApiKey { get; set; } = string.Empty;

    public DashScopeClientOptions Value => this;
}

最终便是写测验代码验证完结是否成功,为了削减代码块的长度,下面的代码片段只列出其间一个测验用例

public class DashScopeChatCompletionTests
{
    [Fact]
    public async Task ChatCompletion_InvokePromptAsync_WorksCorrectly()
    {
        // Arrange
        var builder = Kernel.CreateBuilder();
        builder.Services.AddSingleton(GetConfiguration());
        builder.AddDashScopeChatCompletion();
        var kernel = builder.Build();

        var prompt = @"<message role=""user"">博客园是什么网站</message>";
        PromptExecutionSettings settings = new()
        {
            ExtensionData = new Dictionary<string, object>()
            {
                { "temperature", "0.8" }
            }
        };
        KernelArguments kernelArguments = new(settings);

        // Act
        var result = await kernel.InvokePromptAsync(prompt, kernelArguments);

        // Assert
        Assert.Contains("博客园", result.ToString());
        Trace.WriteLine(result.ToString());
    }

    private static IConfiguration GetConfiguration()
    {
        return new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json")
            .AddUserSecrets<DashScopeChatCompletionTests>()
            .Build();
    }
}

最终的最终便是运转测验,在 appsettings.json 中增加模型Id

{
  "dashscope": {
    "modelId": "qwen-max"
  }
}

注:qwen-max 是通义千问千亿级大模型

经过 user-secrets 增加 api key

dotnet user-secrets set "dashscope:apiKey" "sk-xxx"

dotnet test 指令运转测验

A total of 1 test files matched the specified pattern.
博客园是一个专心于供给信息技能(IT)范畴常识共享和技能沟通的中文博客渠道,创建于2004年。博客园主要由软件开发人员、系统管理员以及对IT技能有深沉爱好的人群运用,用户能够在该网站上编撰和发布自己的博客文章,内容包括编程、软件开发、云核算、人工智能等多个范畴。一起,博客园也供给了丰厚的技能文档、教程资源和社区互动功用,旨在促进IT专业人士之间的沟通与学习。

Passed!  - Failed:     0, Passed:     1, Skipped:     0, Total:     1, Duration: < 1 ms - SemanticKernel.DashScope.IntegrationTest.dll (net8.0)

测验经过!衔接 DashScope 的 Semantic Kernel Connector 开始完结完结。

完好完结代码放在 github 上,详见 https://github.com/cnblogs/semantic-kernel-dashscope/tree/v0.1.0

针对这个完结发布了 nuget 包 Cnblogs.SemanticKernel.Connectors.DashScope

扫描二维码推送至手机访问。

版权声明:本文由51Blog发布,如需转载请注明出处。

本文链接:https://www.51blog.vip/?id=404

分享给朋友:

“完成阿里云模型服务灵积 DashScope 的 Semantic Kernel Connector” 的相关文章

聊天ai,技术革新与未来展望

聊天ai,技术革新与未来展望

聊天AI的崛起:技术革新与未来展望一、聊天AI的起源与发展聊天AI的起源可以追溯到20世纪50年代,当时科学家们开始探索如何让计算机具备与人交流的能力。经过几十年的发展,聊天AI技术逐渐成熟,并在21世纪初开始广泛应用。随着自然语言处理(NLP)和机器学习(ML)技术的进步,聊天AI的能力得到了极大...

机器学习 分类,概述与关键技术

机器学习 分类,概述与关键技术

1. 二分类问题:将实例分为两个类别,例如垃圾邮件过滤(垃圾邮件/非垃圾邮件)。2. 多分类问题:将实例分为多个类别,例如手写数字识别(09)。5. 增量分类问题:在训练过程中,新的实例不断加入,模型需要不断更新以适应新数据。6. 异常检测:将正常实例和异常实例分开,例如信用卡欺诈检测。1. 决策树...

免费的ai作图软件,创意无限,轻松上手

免费的ai作图软件,创意无限,轻松上手

1. 笔魂AI:这是一款自动生成绘画功能的在线AI画图工具,只需输入文字描述即可进行智能AI作画,满足多种场n2. 云界AI:这是一款免费在线AI绘画工具,集AI创作工具与作品分享社区于一体,提供文生图、图生图、条件生图、模型训练服务。3. AIGAZOU:这是一款创新的免费AI图像生成工具,无需...

ai综合材料绘画,技术与艺术的融合创新

ai综合材料绘画,技术与艺术的融合创新

1. 综合材料绘画的概述综合材料绘画是一种现代绘画形式,它超越了传统画种的限制,将不同媒介材料进行混合运用,或者将非传统绘画媒介进行综合处理。这种艺术形式在融会贯通的基础上不断创造新的可能性。 2. 综合材料绘画的特点 材料多样性:综合材料绘画使用各种非传统材料,如报纸、麻袋、金属等,这些材料被粘...

畅言智ai,未来智能生活的引领者

畅言智ai,未来智能生活的引领者

畅言智AI是由科大讯飞股份有限公司开发的一款教育App,主要用于中小学的人工智能教育。该平台提供多种创新教育解决方案,涵盖语言、数学、科学等领域,帮助教师和学生轻松创建和分享精彩的微课。畅言智AI支持个性化学习,教师可以根据学生的特点规划学习路径,培养学生的自主学习能力。此外,畅言智AI还结合了沉浸...

ai软件有哪些,2024年必备的智能助手

ai软件有哪些,2024年必备的智能助手

1. 机器学习平台和框架: TensorFlow PyTorch scikitlearn Keras MXNet Caffe Theano2. 自然语言处理(NLP)工具: spaCy NLTK Stanford NLP Gensi...