(三) Dotnet为AI控制台对话添加依赖注入等集成

依赖注入

日常使用过程中,并不是直接构造IChatClient 实例,而是使用微软自带的依赖注入类库进行实例化生命周期管理。

引用依赖

添加nuget 包引用Microsoft.Extensions.Hosting。

xml 复制代码
<Project Sdk="Microsoft.NET.Sdk">
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.AI" Version="9.9.1" />
    <PackageReference Include="Microsoft.Extensions.AI.Abstractions" Version="9.9.1" />
    <PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="9.9.1-preview.1.25474.6" />
    <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.0-rc.1.25451.107" />
    <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.0-rc.1.25451.107" />
  </ItemGroup>
</Project>

主程序代码

创建Host 构建实例,用于添加指出配置,此处添加缓存服务Microsoft.Extensions.Caching.Memory,以内存作为缓存介质;进行IChatClient 实现类服务注册时,需要全局引入Microsoft.Extensions.AI,该Nuget 包含AddChatClient() 。

代码修改如下:

cs 复制代码
internal class Program
{
    async static Task Main(string[] args)
    {
        // 省略不变内容
        //-------------------------依赖注入---------------------------------
        // 构建默认主机构建器实例
        var builder = Host.CreateApplicationBuilder();
        // 添加缓存服务-内存作为缓存介质
        builder.Services.AddDistributedMemoryCache();
        // 注册IChatClient实现类型
        builder.Services.AddChatClient(new OpenAI.Chat.ChatClient(model, new ApiKeyCredential(apikey), new OpenAIClientOptions
        {
            Endpoint = new Uri(endpoint) // 指定api访问地址
        })
        .AsIChatClient()) // 注册ichatclient实例
            .UseLogging(); // 使用日志
        // 构建Host实例
        var host = builder.Build();
        // 获取ichatclient实现实例
        IChatClient client = host.Services.GetRequiredService<IChatClient>();
        //-------------------------依赖注入---------------------------------
        // 输入上下文 添加多轮会话历史 GetResponseAsync() 接受消息列表
        // 获取http请求响应(非流式)
        List<ChatMessage> history = [new ChatMessage(ChatRole.Assistant, "你是一个英语助手,拥有10年初中教学经验,对于用户提问,英文回复并用中文解释。")]; // 构建基本背景消息
        Console.WriteLine("开始会话,输入 bye 结束会话。");
        // 省略不变内容
}

运行后与直接构建实例无体验区别。

缓存处理

如果同一个问答内容,都调用模型,这明显有点浪费资源,添加上缓存,提高响应性能,降低资源损耗。

官方案例中,缓存主要添加在构建IChatClient 之前,并且是ChatClientBuilder 实例的扩展方法。

cs 复制代码
IChatClient client = new ChatClientBuilder(<ichatclient实例>) .UseDistributedCache(new MemoryDistributedCache( Options.Create(new MemoryDistributedCacheOptions()))) .Build();

实际AddChatClient() 返回类型就是ChatClientBuilder,因此可以直接在案例代码中进行修改。

cs 复制代码
// 省略不变内容
// 构建默认主机构建器实例
var builder = Host.CreateApplicationBuilder();
// 添加缓存服务-内存作为缓存介质
builder.Services.AddDistributedMemoryCache();
// 注册IChatClient实现类型
builder.Services.AddChatClient(new OpenAI.Chat.ChatClient(model, new ApiKeyCredential(apikey), new OpenAIClientOptions
{
    Endpoint = new Uri(endpoint) // 指定api访问地址
})
.AsIChatClient()) // 注册ichatclient实例
//-------------------------添加缓存---------------------------------
 .UseDistributedCache(new MemoryDistributedCache(
    Options.Create(new MemoryDistributedCacheOptions()))) // 使用缓存
//-------------------------添加缓存---------------------------------
    .UseLogging(); // 使用日志
// 省略不变内容

断点时局部变量(由于使用了日志,所以对象是AILogingChatClient)。

无缓存。

有缓存。

对话配置

默认问话模型服务,直接进行调用,需要对模型服务附带一些请求附加参数配置时,例如modelid、TopP、TopK、Temperature、Seed 等,按照实际需求对模型服务进行对话配置处理。

cs 复制代码
// 会话标识符
public string? ConversationId { get; set; }
// 请求指令
public string? Instructions { get; set; }
// 生成回复的温度
public float? Temperature { get; set; }
// 回复最大 token 数
public int? MaxOutputTokens { get; set; }
// 核采样因子(top p)
public float? TopP { get; set; }
// 生成时考虑的最可能 token 数(top k)
public int? TopK { get; set; }
// 重复 token 频率惩罚
public float? FrequencyPenalty { get; set; }
// 已出现 token 的惩罚
public float? PresencePenalty { get; set; }
// 随机种子
public long? Seed { get; set; }
// 回复格式
public ChatResponseFormat? ResponseFormat { get; set; }
// 模型 ID
public string? ModelId { get; set; }
// 停止序列列表
public IList<string>? StopSequences { get; set; }
// 是否允许多工具调用
public bool? AllowMultipleToolCalls { get; set; }
// 工具模式
public ChatToolMode? ToolMode { get; set; }
// 工具列表
[JsonIgnore]
public IList<AITool>? Tools { get; set; }
// 原始选项工厂回调
[JsonIgnore]
public Func<IChatClient, object?>? RawRepresentationFactory { get; set; }
// 附加属性
public AdditionalPropertiesDictionary? AdditionalProperties { get; set; }

实际案例代码调整如下:

cs 复制代码
internal class Program
{
    async static Task Main(string[] args)
    {
        // 省略不变内容
        string modelthink = "deepseek-reasoner"; // 思考 
        // 省略不变内容
        //-------------------------对话配置-附加配置------------------------
        // 模型服务配置
        client = ChatClientBuilderChatClientExtensions.AsBuilder(client)
                .ConfigureOptions(options => options.ModelId ??= model)
                .Build();
        //-------------------------对话配置-附加配置------------------------
        // 作为缓存对象构架分部署缓存
        // 输入上下文 添加多轮会话历史 GetResponseAsync() 接受消息列表
        // 获取http请求响应(非流式)
        List<ChatMessage> history = [new ChatMessage(ChatRole.Assistant, "你是一个英语助手,拥有10年初中教学经验,对于用户提问,英文回复并用中文解释。")]; // 构建基本背景消息
        Console.WriteLine("开始会话,输入 bye 结束会话。");
        //-------------------------对话配置实例----------------------------
        ChatOptions chatOptions = new ChatOptions();
        // 设置模型为思考模型
        chatOptions.ModelId = modelthink;
		// 设置Temperature 0.1 - 0.5(严谨、可复现)
		chatOptions.Temperature = 0.5f;
		// top-p 0.7-0.85 
		chatOptions.TopP = 0.7f;
		// top-k 20-40
		chatOptions.TopK = 20;
        //-------------------------对话配置实例----------------------------
        // 通过控制台输入添加用户角色信息且大模型响应消息作为最后的消息
        while (true) {
			// 省略不变内容
            //-------------------------对话配置---------------------------
            await foreach (ChatResponseUpdate update in client.GetStreamingResponseAsync(history, chatOptions)) {
                // 省略不变内容
            }
            //-------------------------对话配置---------------------------
            // 省略不变内容
        }
    }
}

输出结果如下:

以上完整代码如下:

cs 复制代码
internal class Program
{
    async static Task Main(string[] args)
    {
        string apikey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");// 通过环境变量获取apikey
        string model = "deepseek-chat"; // 非思考
        string modelthink = "deepseek-reasoner"; // 思考 
        string endpoint = "https://api.deepseek.com/v1"; // deepseek 中 提供兼容openai的访问api
        // 构建默认主机构建器实例
        var builder = Host.CreateApplicationBuilder();
        // 添加缓存服务-内存作为缓存介质
        builder.Services.AddDistributedMemoryCache();
        // 注册IChatClient实现类型
        builder.Services.AddChatClient(new OpenAI.Chat.ChatClient(model, new ApiKeyCredential(apikey), new OpenAIClientOptions
        {
            Endpoint = new Uri(endpoint) // 指定api访问地址
        })
        .AsIChatClient()) // 注册ichatclient实例
         .UseDistributedCache(new MemoryDistributedCache(
            Options.Create(new MemoryDistributedCacheOptions()))) // 使用缓存
            .UseLogging(); // 使用日志
        // 构建Host实例
        var host = builder.Build();
        // 获取ichatclient实现实例
        IChatClient client = host.Services.GetRequiredService<IChatClient>();
        //-------------------------对话配置-附加配置----------------------------
        // 模型服务配置
        client = ChatClientBuilderChatClientExtensions.AsBuilder(client)
                .ConfigureOptions(options => options.ModelId ??= model)
                .Build();
        //-------------------------对话配置-附加配置----------------------------
        // 作为缓存对象构架分部署缓存
        // 输入上下文 添加多轮会话历史 GetResponseAsync() 接受消息列表
        // 获取http请求响应(非流式)
        List<ChatMessage> history = [new ChatMessage(ChatRole.Assistant, "你是一个英语助手,拥有10年初中教学经验,对于用户提问,英文回复并用中文解释。")]; // 构建基本背景消息
        Console.WriteLine("开始会话,输入 bye 结束会话。");
        //-------------------------对话配置实例----------------------------
        ChatOptions chatOptions = new ChatOptions();
        // 设置模型为思考模型
        chatOptions.ModelId = modelthink;
        // 设置Temperature 0.1 - 0.5(严谨、可复现)
        chatOptions.Temperature = 0.5f;
        // top-p 0.7-0.85 
        chatOptions.TopP = 0.7f;
        // top-k 20-40
        chatOptions.TopK = 20;
        //-------------------------对话配置实例---------------------------------
        // 通过控制台输入添加用户角色信息且大模型响应消息作为最后的消息
        while (true) {
            Console.Write("Q:");
            string request = Console.ReadLine();
            if (request.Contains("bye"))
            {
                break;
            }
            // 输入询问内容并存储到消息集合中
            history.Add(new ChatMessage(ChatRole.User, request));
            // 将输出的响应结果进行集合保存
            List<ChatResponseUpdate> updates = [];
            //-------------------------对话配置---------------------------------
            await foreach (ChatResponseUpdate update in client.GetStreamingResponseAsync(history, chatOptions)) {
                // 输出实时流对话结果
                Console.Write(update);
                // 存储此次消息响应单项
                updates.Add(update);
            }
            //-------------------------对话配置---------------------------------
            // 添加对话结果保存到历史集合中
            history.AddMessages(updates);
            // 每一次对话输出完成进行换行
            Console.WriteLine();
        }
        Console.WriteLine("会话结束");
    }
}
相关推荐
张彦峰ZYF4 小时前
越过边界之前:Reward Seeker 实验如何改写智能体安全的时间逻辑
人工智能·ai agent·anthropic·智能体安全·reward seeker·“控制评价过程”泛化跨领域策略·envbom
拓恒技术4 小时前
无人机巡检AI算法的工程化落地:从需求到交付的5个核心环节
人工智能·算法·无人机
罗西的思考6 小时前
AI 时代的 “房谋杜断”:如何培养能力、品味与判断力
人工智能·算法·机器学习
字节跳动视频云技术团队7 小时前
720P 直升 8K,解密 2026 抖音美好奇妙夜巨幕超分黑科技
人工智能·音视频开发
打工仔折腾 AI7 小时前
在 Ubuntu ARM64 部署 Q1 V3.0 MuJoCo 模型:加载、单步推理与执行器响应解析
linux·运维·人工智能·python·深度学习·ubuntu·性能优化
特别关注外国供应商7 小时前
Qualys TotalAI:AI 安全治理的四大支柱
ai·大模型安全·ai数据安全·qualys·ai安全治理·ai saas 治理·ai代码安全
逐米时代7 小时前
从试点验证到协同深化:制造业AI转型三年路线图设计方法
人工智能
GlobalInfo7 小时前
全球及中国风电叶片检测机器人行业研究报告(2026版):市场现状、行业前景与占有率分析
运维·网络·人工智能·机器人
stormzhangV8 小时前
AI 越强,失业越严重
人工智能·aigc
夏文强9 小时前
Rerank 与混合检索:怎么让 RAG 从「能用」变成「好用」
人工智能·大模型·向量数据库·rag·检索增强生成