首页 > 编程语言 >C#实现一个HttpClient集成通义千问-多轮对话功能实现

C#实现一个HttpClient集成通义千问-多轮对话功能实现

时间:2024-12-15 18:30:50浏览次数:6  
标签:千问 必填 C# messages content 消息 字符串 string HttpClient

多轮对话功能实现

视频教程

<iframe allowfullscreen="true" data-mediaembed="bilibili" frameborder="0" id="8N5yHjY0-1733735615877" src="https://player.bilibili.com/player.html?aid=113622051199870"></iframe>

.Net+AI开发入门HttpClient实现通义千问集成-多轮对话功能实现

实现原理

一直保留更新messages

在这里插入图片描述

现在设置的meessages只设置了两条内容

  1. system:系统消息,给AI设置一个角色,
  2. user:用户消息,你提的问题

消息的类型

根据OpenAI API官网,消息有以下几种类型

在这里插入图片描述

我们现在主要用的就三个:

  • System Message :系统消息,用于指定模型的目标或角色(放在messages第一位)
  • User Message:用户消息,用户发送给模型的消息。
  • Assistant Message:助手消息,模型对用户消息的回复。

实现的效果:

messages:
system:xx
user:xxx
assistant:xxx
user:xxx
assistant:xxx

功能开发

消息类

创建一个消息类

 public class ChatMessage
 {
     public string role { get; set; }

     public string message { get; set; }
 }

修改请求体

修改请求体,将message内容改成一个占位字符串,用于后面修改

在这里插入图片描述

增加一个消息集合messages 用于存储消息

   List<ChatMessage> messages = new List<ChatMessage>();
   messages.Add(new ChatMessage() { role = "system", content = "你是一个C#高手" });

修改发送请求函数

增加一个result,获取流式输出的content完整内容,返回完整的助手消息内容,用于后续添加到messages中

 private static async Task<string> SendPostRequestAsync(
     string url,
     string jsonContent,
     string apiKey
 )
 {
     using (var content = new StringContent(jsonContent, Encoding.UTF8, "application/json"))
     {
         // 发送请求并获取响应
         HttpResponseMessage response = await httpClient.PostAsync(url, content);

         // 处理响应
         if (response.IsSuccessStatusCode)
         {
             string result = "";
             using (Stream stream = await response.Content.ReadAsStreamAsync())
             using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
             {
                 string line;
                 while ((line = await reader.ReadLineAsync()) != null)
                 {
                     if (string.IsNullOrEmpty(line))
                         continue;
                     string data = line.Substring(6);
                     if (data == "[DONE]")
                     {
                         //结束标志
                         break;
                     }
                     var streamObject = JsonSerializer.Deserialize<StreamObject>(data);
                     if (streamObject.choices.Count() > 0)
                     {
                         var contentRes = streamObject.choices[0].delta.content;
                         Console.Write(contentRes);
                         result += contentRes;
                     }
                     if (streamObject.usage != null)
                     {
                         Console.WriteLine(
                             $"Usage: prompt_tokens:{streamObject.usage.prompt_tokens}, completion_tokens:{streamObject.usage.completion_tokens}, total_tokens:{streamObject.usage.total_tokens}"
                         );
                     }
                     Thread.Sleep(200);
                 }
                 Console.WriteLine();
             }
             return result;
             // return await response.Content.ReadAsStringAsync();
         }
         else
         {
             Console.WriteLine($"请求失败: {response.StatusCode}");
             return $"请求失败: {response.StatusCode}";
         }
     }
 }

将httpclient设置请求头的代码拿到一开始,只设置一次

在这里插入图片描述

修改用户消息输入

  1. 修改用户消息,改成用户直接在控制台上输入,输入之后再加入到消息中
  2. 然后将消息集合messages序列化成字符串,替换掉jsonContent里面的消息占位符messagesContent,再发送出去
  3. 接收到模型返回的助手消息之后,将助手消息也添加到messages中去,role为"assistant"
  4. 然后下次发送,这些消息累加一起再发送
  while (true)
  {
      Console.Write("User:");
      var usermessage = Console.ReadLine();
      if (string.IsNullOrEmpty(usermessage))
      {
          continue;
      }
      if (usermessage == "exit")
      {
          break;
      }
      var user = new ChatMessage() { role = "user", content = usermessage };
      messages.Add(user);
      var str = JsonSerializer.Serialize(messages);
      var send = jsonContent.Replace("messagesContent", str);
      // 发送请求并获取响应
      Console.WriteLine("assistant:");

      var result = await SendPostRequestAsync(url, send, apiKey);
      messages.Add(new ChatMessage() { role = "assistant", content = result });
  }

多轮对话的token

多轮对话的token是持续累加的,第二次发送的时候相当于第一次发送和返回的消息也发送了,都算在第二次发送的token中

在这里插入图片描述


消息完整文档

以下详细内容来着OpenAI API翻译

https://platform.openai.com/docs/api-reference/chat/create

消息类型

系统消息 (System message)

object

  • content (字符串或数组) 必填

    系统消息的内容。

  • role (字符串) 必填

    消息作者的角色,此处为 "system"

  • name (字符串) 可选

    用于区分相同角色参与者的可选名称。


用户消息 (User message)

object

  • content (字符串或数组) 必填

    用户消息的内容。

  • role (字符串) 必填

    消息作者的角色,此处为 "user"

  • name (字符串) 可选

    用于区分相同角色参与者的可选名称。

助手消息 (Assistant message)

object

  • content (字符串或数组) 可选

    助手消息的内容。除非指定 tool_callsfunction_call,否则必填。

  • refusal (字符串或 null) 可选

    助手的拒绝消息。

  • role (字符串) 必填

    消息作者的角色,此处为 "assistant"

  • name (字符串) 可选

    用于区分相同角色参与者的可选名称。

  • audio (对象或 null) 可选

    与助手之前的音频响应相关的数据。

    • id (字符串)必填

      唯一标识模型生成的音频响应。

  • tool_call (数组) 必填

    模型生成的工具调用列表(例如函数调用)。

    • id (字符串)必填

      具调用的唯一 ID。

    • type (字符串)必填

      工具类型,目前仅支持 function

    • function (对象)必填

      模型调用的函数。

      • name (字符串)必填

        要调用的函数名称。

      • arguments (字符串)必填

        模型以 JSON 格式生成的函数调用参数。

        • 注意:模型生成的参数可能无效,或者包含未在函数定义中描述的参数。
        • 建议: 在调用函数之前,应在代码中验证参数
  • function_call 已弃用 (对象 或者 null) 选填

    模型生成的工具调用列表(例如函数调用)。

    • name (字符串)必填

      要调用的函数名称。

    • arguments (字符串)必填

      模型以 JSON 格式生成的函数调用参数。


工具消息 (Tool message)

object

  • role (字符串) 必填

    消息作者的角色,此处为 "tool"

  • content (字符串或数组) 必填

    工具消息的内容。

  • tool_call_id (字符串) 必填

    对应工具调用的消息 ID。


函数消息 (Function message)

(已弃用)

object

  • role (字符串) 必填

    消息作者的角色,此处为 "function"

  • content (字符串或 null) 必填

    函数消息的内容。

  • name (字符串) 必填

    函数名称。

标签:千问,必填,C#,messages,content,消息,字符串,string,HttpClient
From: https://blog.csdn.net/qq_39427511/article/details/144338623

相关文章

  • 搭建Tomcat(三)---重写service方法
    目录引入一、在Java中创建一个新的空项目(初步搭建)问题:要求在tomcat软件包下的MyTomcat类中编写main文件,实现在MyTomcat中扫描myweb软件包中的所有Java文件,并返回“@WebServlet(url="myFirst")”中url内填写的值:①main函数解析:首先,main函数用try-catch做了异常处理:指定......
  • 【C 语言篇】函数模块拼图与代码复用灯塔:C 语言编程中探索函数调用的高效征程
    文章目录【C语言篇】函数模块拼图与代码复用灯塔:C语言编程中探索函数调用的高效征程前言一、创建和使用函数1.创建函数2.调用函数二、局部变量1.局部变量的特点2.局部变量的初始化3.局部变量的生命周期4.关于局部变量的总结三、全局变量1.全局变量的特点2......
  • 鸿蒙UI系统组件08——自定义弹窗(CustomDialog)
    1、概述自定义弹窗(CustomDialog)可用于广告、中奖、警告、软件更新等与用户交互响应操作。开发者可以通过CustomDialogController类显示自定义弹窗。2、创建自定义弹窗使用@CustomDialog装饰器装饰自定义弹窗。@CustomDialog装饰器用于装饰自定义弹框,此装饰器内进行自定义......
  • 鸿蒙UI系统组件15——画布(Canvas)
    概 述前一章我们学习了Shape绘制来绘制自定义形状(鸿蒙UI系统组件14——几何图形(Shape)),在实际的业务开发中,有可能我们需要绘制更复杂的图形,例如统计图中的饼图、折线图等,除了绘制图形外,可能还会绘制一些复杂的组件效果,此时,我们就需要用到画布(Canvas)组件来满足我们的需求了......
  • C语言之控制流关键字
    条件控制1.if...(elseif...) else...  用于条件判断,根据不同的条件执行不同的代码块,if、elseif、else后跟判断条件,之间则是根据不同条件需要执行的代码块2.switch... case...default  用于多路选择,根据表达式的值执行不同的代码块,switch后跟要判断的表达式,case后......
  • Windows Server 2022 DHCP 服务器 是一种网络服务,属于 动态主机配置协议(DHCP, Dynamic
    WindowsServer2022DHCP服务器是一种网络服务,属于动态主机配置协议(DHCP,DynamicHostConfigurationProtocol)实现的一部分,用于自动为网络中的计算机和设备分配IP地址和其他网络配置信息,如子网掩码、默认网关和DNS服务器等。功能和作用:自动化IP地址分配:DHCP服......
  • 线程池C++11实现
    设计思路tasks:任务队列,每当有新任务时,就addTask到该队列workers:工作线程,不断地从tasks中取任务执行queueMutex:任务队列互斥锁,防止在addTask时出现冲突condition_variable:条件变量,当任务队列为空时阻塞线程,等待任务被添加进队列function<void()>:函数对象,tasks队列......
  • lang.IllegalStateException_ Type handler was null on parameter mapping for prope
    在使用mybatis-plus的removeIds()方法时抛出此异常。在调用的时候传入了实体类对象的list的集合使用id的集合即可List<PojoInfo>totalList;//错误用法service.removeByIds(totalList);//正确用法List<Long>idList=totalList.stream().map(PojoInfo::getId).collec......
  • MySQL 中 VARCHAR(100) 和 VARCHAR(10) 的区别是什么?
    在MySQL中,VARCHAR(100)和VARCHAR(10)都是变长字符串类型,但它们的主要区别在于能够存储的最大字符长度不同:1.存储长度VARCHAR(100):表示该字段可以存储最多100个字符(根据字符集的不同,一个字符可能占用1到多个字节)。如果存储的数据长度小于100个字符,MySQL只会占用实际......
  • Caused by_ net.sf.jsqlparser.parser.ParseException_ Encountered unexpected token
    问题:在xml里写完sql语句进行测试时抛出ParseException异常,如下:selectbasic.idas'id',frombasic_infobasic<iftest="request.behaveType!=null">innerjoinapply_infoapplyonapply.basic_info_id=basic.id&......