diff --git a/README.md b/README.md index ee04b2b..9eda927 100644 --- a/README.md +++ b/README.md @@ -81,9 +81,9 @@ Console.WriteLine(completion.Output.Text); ```csharp var history = new List { - new("user", "Please remember this number, 42"), - new("assistant", "I have remembered this number."), - new("user", "What was the number I metioned before?") + ChatMessage.User("Please remember this number, 42"), + ChatMessage.Assistant("I have remembered this number."), + ChatMessage.User("What was the number I metioned before?") } var parameters = new TextGenerationParameters() { @@ -137,7 +137,7 @@ var tools = new List() var history = new List { - new("user", "What is the weather today in C.A?") + ChatMessage.User("What is the weather today in C.A?") }; var parameters = new TextGenerationParamters() @@ -155,7 +155,7 @@ Console.WriteLine(completion.Output.Choice[0].Message.ToolCalls[0].Function.Name // calling tool that model requests and append result into history. var result = GetCurrentWeather(JsonSerializer.Deserialize(completion.Output.Choice[0].Message.ToolCalls[0].Function.Arguments)); -history.Add(new("tool", result, nameof(GetCurrentWeather))); +history.Add(ChatMessage.Tool(result, nameof(GetCurrentWeather))); // get back answers. completion = await client.GetQWenChatCompletionAsync(QWenLlm.QWenMax, history, parameters); @@ -179,8 +179,8 @@ Using uploaded file id in messages. ```csharp var history = new List { - new(uploadedFile.Id), // use array for multiple files, e.g. [file1.Id, file2.Id] - new("user", "Summarize the content of file.") + ChatMessage.File(uploadedFile.Id), // use array for multiple files, e.g. [file1.Id, file2.Id] + ChatMessage.User("Summarize the content of file.") } var parameters = new TextGenerationParameters() { diff --git a/README.zh-Hans.md b/README.zh-Hans.md index 936246f..b8cc16b 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -5,7 +5,7 @@ # Cnblogs.DashScopeSDK -由博客园维护并使用的非官方灵积服务 SDK。 +由博客园维护并使用的非官方灵积(百炼)服务 SDK。 使用前注意:当前项目正在积极开发中,小版本也可能包含破坏性更改,升级前请查看对应版本 Release Note 进行迁移。 @@ -63,7 +63,7 @@ public class YourService(IDashScopeClient client) - 人像风格重绘 - `CreateWanxImageGenerationTaskAsync()` and `GetWanxImageGenerationTaskAsync()` - 图像背景生成 - `CreateWanxBackgroundGenerationTaskAsync()` and `GetWanxBackgroundGenerationTaskAsync()` - 适用于 QWen-Long 的文件 API `dashScopeClient.UploadFileAsync()` and `dashScopeClient.DeleteFileAsync` - +- 其他使用相同 Endpoint 的模型 # 示例 @@ -82,9 +82,9 @@ Console.WriteLine(completion.Output.Text); ```csharp var history = new List { - new("user", "Please remember this number, 42"), - new("assistant", "I have remembered this number."), - new("user", "What was the number I metioned before?") + ChatMessage.User("Please remember this number, 42"), + ChatMessage.Assistant("I have remembered this number."), + ChatMessage.User("What was the number I metioned before?") } var parameters = new TextGenerationParameters() { @@ -134,7 +134,7 @@ var tools = new List() var history = new List { - new("user", "杭州现在天气如何?") + ChatMessage.User("What is the weather today in C.A?") }; var parameters = new TextGenerationParamters() @@ -175,8 +175,8 @@ var uploadedFile = await dashScopeClient.UploadFileAsync(file.OpenRead(), file.N ```csharp var history = new List { - new(uploadedFile.Id), // 多文件情况下可以直接传入文件 Id 数组, 例如:[file1.Id, file2.Id] - new("user", "总结一下文件的内容。") + ChatMessage.File(uploadedFile.Id), // 多文件情况下可以直接传入文件 Id 数组, 例如:[file1.Id, file2.Id] + ChatMessage.User("总结一下文件的内容。") } var parameters = new TextGenerationParameters() { diff --git a/sample/Cnblogs.DashScope.Sample/Program.cs b/sample/Cnblogs.DashScope.Sample/Program.cs index 0572a8c..e25fbd6 100644 --- a/sample/Cnblogs.DashScope.Sample/Program.cs +++ b/sample/Cnblogs.DashScope.Sample/Program.cs @@ -73,7 +73,7 @@ async Task ChatStreamAsync() { Console.Write("user > "); var input = Console.ReadLine()!; - history.Add(new ChatMessage("user", input)); + history.Add(ChatMessage.User(input)); var stream = dashScopeClient.GetQWenChatStreamAsync( QWenLlm.QWenMax, history, @@ -109,10 +109,10 @@ async Task ChatWithFilesAsync() Console.WriteLine("file uploaded, id: " + uploadedFile.Id); Console.WriteLine(); - var fileMessage = new ChatMessage(uploadedFile.Id); + var fileMessage = ChatMessage.File(uploadedFile.Id); history.Add(fileMessage); Console.WriteLine("system > " + fileMessage.Content); - var userPrompt = new ChatMessage("user", "该文件的内容是什么"); + var userPrompt = ChatMessage.User("该文件的内容是什么"); history.Add(userPrompt); Console.WriteLine("user > " + userPrompt.Content); var stream = dashScopeClient.GetQWenChatStreamAsync( @@ -156,7 +156,7 @@ async Task ChatWithToolsAsync() new JsonSchemaBuilder().FromType().Build())) }; var chatParameters = new TextGenerationParameters() { ResultFormat = ResultFormats.Message, Tools = tools }; - var question = new ChatMessage("user", "请问现在杭州的天气如何?"); + var question = ChatMessage.User("请问现在杭州的天气如何?"); history.Add(question); Console.WriteLine($"{question.Role} > {question.Content}"); @@ -168,7 +168,7 @@ async Task ChatWithToolsAsync() var toolResponse = GetWeather( JsonSerializer.Deserialize(toolCallMessage.ToolCalls[0].Function!.Arguments!)!); - var toolMessage = new ChatMessage("tool", toolResponse, nameof(GetWeather)); + var toolMessage = ChatMessage.Tool(toolResponse, nameof(GetWeather)); history.Add(toolMessage); Console.WriteLine($"{toolMessage.Role} > {toolMessage.Content}"); diff --git a/src/Cnblogs.DashScope.Core/ChatMessage.cs b/src/Cnblogs.DashScope.Core/ChatMessage.cs index acbca89..0c3c0be 100644 --- a/src/Cnblogs.DashScope.Core/ChatMessage.cs +++ b/src/Cnblogs.DashScope.Core/ChatMessage.cs @@ -9,12 +9,14 @@ namespace Cnblogs.DashScope.Core; /// The role of this message. /// The content of this message. /// Used when role is tool, represents the function name of this message generated by. +/// Notify model that next message should use this message as prefix. /// Calls to the function. [method: JsonConstructor] public record ChatMessage( string Role, string Content, string? Name = null, + bool? Partial = null, List? ToolCalls = null) : IMessage { /// @@ -34,4 +36,69 @@ public ChatMessage(IEnumerable fileIds) : this("system", string.Join(',', fileIds.Select(f => f.ToUrl()))) { } + + /// + /// Creates a file message. + /// + /// The id of the file. + /// + public static ChatMessage File(DashScopeFileId fileId) + { + return new ChatMessage(fileId); + } + + /// + /// Creates a file message. + /// + /// The file id list. + /// + public static ChatMessage File(IEnumerable fileIds) + { + return new ChatMessage(fileIds); + } + + /// + /// Create a user message. + /// + /// Content of the message. + /// Author name. + /// + public static ChatMessage User(string content, string? name = null) + { + return new ChatMessage(DashScopeRoleNames.User, content, name); + } + + /// + /// Create a system message. + /// + /// The content of the message. + /// + public static ChatMessage System(string content) + { + return new ChatMessage(DashScopeRoleNames.System, content); + } + + /// + /// Create an assistant message + /// + /// The content of the message. + /// When set to true, content of this message would be the prefix of next model output. + /// Author name. + /// Tool calls by model. + /// + public static ChatMessage Assistant(string content, bool? partial = null, string? name = null, List? toolCalls = null) + { + return new ChatMessage(DashScopeRoleNames.Assistant, content, name, partial, toolCalls); + } + + /// + /// Create a tool message. + /// + /// The output from tool. + /// The name of the tool. + /// + public static ChatMessage Tool(string content, string? name = null) + { + return new ChatMessage(DashScopeRoleNames.Tool, content, name); + } } diff --git a/src/Cnblogs.DashScope.Core/DashScopeResponseFormat.cs b/src/Cnblogs.DashScope.Core/DashScopeResponseFormat.cs new file mode 100644 index 0000000..1492e41 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/DashScopeResponseFormat.cs @@ -0,0 +1,17 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Available formats for . +/// +public record DashScopeResponseFormat(string Type) +{ + /// + /// Output should be text. + /// + public static readonly DashScopeResponseFormat Text = new("text"); + + /// + /// Output should be json object. + /// + public static readonly DashScopeResponseFormat Json = new("json_object"); +} diff --git a/src/Cnblogs.DashScope.Core/DashScopeRoleNames.cs b/src/Cnblogs.DashScope.Core/DashScopeRoleNames.cs new file mode 100644 index 0000000..9322630 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/DashScopeRoleNames.cs @@ -0,0 +1,27 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Common role name. +/// +public static class DashScopeRoleNames +{ + /// + /// User inputs. + /// + public const string User = "user"; + + /// + /// Model outputs. + /// + public const string Assistant = "assistant"; + + /// + /// System message. + /// + public const string System = "system"; + + /// + /// Tool outputs. + /// + public const string Tool = "tool"; +} diff --git a/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs b/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs index 6466e73..c32bb72 100644 --- a/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs +++ b/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs @@ -7,14 +7,34 @@ public interface ITextGenerationParameters : IIncrementalOutputParameter, ISeedParameter, IProbabilityParameter, IPenaltyParameter, IMaxTokenParameter, IStopTokenParameter { /// - /// The format of the result message, must be text or message. + /// The format of the result, must be text or message. /// /// /// text - original text format. /// message - OpenAI compatible message format /// + /// + /// Sets result_format to message + /// + /// parameter.ResultFormat = ResultFormats.Message; + /// + /// public string? ResultFormat { get; } + /// + /// The format of response message, must be text or json_object + /// + /// + /// This property is not . Be sure not to confuse them. + /// + /// + /// Set response format to json_object. + /// + /// parameter.ResponseFormat = DashScopeResponseFormat.Json; + /// + /// + public DashScopeResponseFormat? ResponseFormat { get; } + /// /// Enable internet search when generation. Defaults to false. /// diff --git a/src/Cnblogs.DashScope.Core/TextGenerationStopConvertor.cs b/src/Cnblogs.DashScope.Core/Internals/TextGenerationStopConvertor.cs similarity index 97% rename from src/Cnblogs.DashScope.Core/TextGenerationStopConvertor.cs rename to src/Cnblogs.DashScope.Core/Internals/TextGenerationStopConvertor.cs index 769df58..1efd6b5 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationStopConvertor.cs +++ b/src/Cnblogs.DashScope.Core/Internals/TextGenerationStopConvertor.cs @@ -1,12 +1,12 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Cnblogs.DashScope.Core; +namespace Cnblogs.DashScope.Core.Internals; /// /// JSON convertor for . /// -public class TextGenerationStopConvertor : JsonConverter +internal class TextGenerationStopConvertor : JsonConverter { /// public override TextGenerationStop? Read( diff --git a/src/Cnblogs.DashScope.Core/ToolChoiceJsonConverter.cs b/src/Cnblogs.DashScope.Core/Internals/ToolChoiceJsonConverter.cs similarity index 95% rename from src/Cnblogs.DashScope.Core/ToolChoiceJsonConverter.cs rename to src/Cnblogs.DashScope.Core/Internals/ToolChoiceJsonConverter.cs index 14cfefe..b771420 100644 --- a/src/Cnblogs.DashScope.Core/ToolChoiceJsonConverter.cs +++ b/src/Cnblogs.DashScope.Core/Internals/ToolChoiceJsonConverter.cs @@ -1,12 +1,12 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Cnblogs.DashScope.Core; +namespace Cnblogs.DashScope.Core.Internals; /// /// The converter for /// -public class ToolChoiceJsonConverter : JsonConverter +internal class ToolChoiceJsonConverter : JsonConverter { /// public override ToolChoice? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) diff --git a/src/Cnblogs.DashScope.Core/MultimodalMessage.cs b/src/Cnblogs.DashScope.Core/MultimodalMessage.cs index 0996690..d1034b0 100644 --- a/src/Cnblogs.DashScope.Core/MultimodalMessage.cs +++ b/src/Cnblogs.DashScope.Core/MultimodalMessage.cs @@ -8,4 +8,35 @@ namespace Cnblogs.DashScope.Core; /// The role associated with this message. /// The contents of this message. public record MultimodalMessage(string Role, IReadOnlyList Content) - : IMessage>; + : IMessage> +{ + /// + /// Create a user message. + /// + /// Message contents. + /// + public static MultimodalMessage User(IReadOnlyList contents) + { + return new MultimodalMessage(DashScopeRoleNames.User, contents); + } + + /// + /// Create a system message. + /// + /// Message contents. + /// + public static MultimodalMessage System(IReadOnlyList contents) + { + return new MultimodalMessage(DashScopeRoleNames.System, contents); + } + + /// + /// Creates an assistant message. + /// + /// Message contents. + /// + public static MultimodalMessage Assistant(IReadOnlyList contents) + { + return new MultimodalMessage(DashScopeRoleNames.Assistant, contents); + } +} diff --git a/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs b/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs index 27f9d75..f6ffed7 100644 --- a/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs +++ b/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs @@ -8,9 +8,58 @@ namespace Cnblogs.DashScope.Core; /// Image url. /// Text content. /// Audio url. +/// Video urls. +/// For qwen-vl-ocr only. Minimal pixels for ocr task. +/// For qwen-vl-ocr only. Maximum pixels for ocr task. public record MultimodalMessageContent( [StringSyntax(StringSyntaxAttribute.Uri)] string? Image = null, string? Text = null, [StringSyntax(StringSyntaxAttribute.Uri)] - string? Audio = null); + string? Audio = null, + IEnumerable? Video = null, + int? MinPixels = null, + int? MaxPixels = null) +{ + /// + /// Represents an image content. + /// + /// Image url. + /// For qwen-vl-ocr only. Minimal pixels for ocr task. + /// For qwen-vl-ocr only. Maximum pixels for ocr task. + /// + public static MultimodalMessageContent ImageContent(string url, int? minPixels = null, int? maxPixels = null) + { + return new MultimodalMessageContent(url, MinPixels: minPixels, MaxPixels: maxPixels); + } + + /// + /// Represents a text content. + /// + /// Text content. + /// + public static MultimodalMessageContent TextContent(string text) + { + return new MultimodalMessageContent(Text: text); + } + + /// + /// Represents an audio content. + /// + /// The url of the audio. + /// + public static MultimodalMessageContent AudioContent(string audioUrl) + { + return new MultimodalMessageContent(Audio: audioUrl); + } + + /// + /// Represents video contents. + /// + /// The urls of the videos. + /// + public static MultimodalMessageContent VideoContent(IEnumerable videoUrls) + { + return new MultimodalMessageContent(Video: videoUrls); + } +} diff --git a/src/Cnblogs.DashScope.Core/MultimodalTokenUsage.cs b/src/Cnblogs.DashScope.Core/MultimodalTokenUsage.cs index d85575f..c6d5e90 100644 --- a/src/Cnblogs.DashScope.Core/MultimodalTokenUsage.cs +++ b/src/Cnblogs.DashScope.Core/MultimodalTokenUsage.cs @@ -24,4 +24,9 @@ public class MultimodalTokenUsage /// The token usage of input audio. /// public int? AudioTokens { get; set; } + + /// + /// The token usage of input video. + /// + public int? VideoTokens { get; set; } } diff --git a/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs b/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs index fbe42e5..c5151f3 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs +++ b/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs @@ -8,6 +8,9 @@ public class TextGenerationParameters : ITextGenerationParameters /// public string? ResultFormat { get; set; } + /// + public DashScopeResponseFormat? ResponseFormat { get; set; } + /// public ulong? Seed { get; set; } diff --git a/src/Cnblogs.DashScope.Core/TextGenerationStop.cs b/src/Cnblogs.DashScope.Core/TextGenerationStop.cs index cc3c567..20e7b07 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationStop.cs +++ b/src/Cnblogs.DashScope.Core/TextGenerationStop.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using Cnblogs.DashScope.Core.Internals; namespace Cnblogs.DashScope.Core; diff --git a/src/Cnblogs.DashScope.Core/ToolChoice.cs b/src/Cnblogs.DashScope.Core/ToolChoice.cs index 030c5c4..a80f536 100644 --- a/src/Cnblogs.DashScope.Core/ToolChoice.cs +++ b/src/Cnblogs.DashScope.Core/ToolChoice.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using Cnblogs.DashScope.Core.Internals; namespace Cnblogs.DashScope.Core; diff --git a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs index 32cb00f..3f99f6b 100644 --- a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs +++ b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs @@ -3,12 +3,15 @@ const string basePath = "../../../../Cnblogs.DashScope.Sdk.UnitTests/RawHttpData"; var snapshots = new DirectoryInfo(basePath); -Console.Write("ApiKey > "); -var apiKey = Console.ReadLine(); -var handler = new SocketsHttpHandler() +Console.WriteLine("Reading key from environment variable DASHSCOPE_KEY"); +var apiKey = Environment.GetEnvironmentVariable("DASHSCOPE_API_KEY"); +if (string.IsNullOrEmpty(apiKey)) { - AutomaticDecompression = DecompressionMethods.All, -}; + Console.Write("ApiKey > "); + apiKey = Console.ReadLine(); +} + +var handler = new SocketsHttpHandler() { AutomaticDecompression = DecompressionMethods.All, }; var client = new HttpClient(handler) { BaseAddress = new Uri("https://dashscope.aliyuncs.com/api/v1/") }; client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}"); @@ -51,7 +54,12 @@ static async Task UpdateSnapshotsAsync(HttpClient client, string name) var contentType = "application/json"; foreach (var header in requestHeader.Skip(1)) { - var values = header.Split(':', StringSplitOptions.TrimEntries); + if (string.IsNullOrWhiteSpace(header)) + { + continue; + } + + var values = header.Split(':', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); if (values[0] == "Content-Type") { contentType = values[1]; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs index ace9d1d..8889981 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs @@ -41,7 +41,8 @@ public async Task MultimodalGeneration_Sse_SuccessAsync( // Act var message = new StringBuilder(); var outputs = await client.GetMultimodalGenerationStreamAsync(testCase.RequestModel).ToListAsync(); - outputs.ForEach(x => message.Append(x.Output.Choices[0].Message.Content[0].Text)); + outputs.ForEach( + x => message.Append(x.Output.Choices[0].Message.Content.FirstOrDefault()?.Text ?? string.Empty)); // Assert handler.Received().MockSend( @@ -50,15 +51,27 @@ public async Task MultimodalGeneration_Sse_SuccessAsync( outputs.SkipLast(1).Should().AllSatisfy(x => x.Output.Choices[0].FinishReason.Should().Be("null")); outputs.Last().Should().BeEquivalentTo( testCase.ResponseModel, - o => o.Excluding(y => y.Output.Choices[0].Message.Content[0].Text)); + o => o.Excluding(y => y.Output.Choices[0].Message.Content)); message.ToString().Should().Be(testCase.ResponseModel.Output.Choices[0].Message.Content[0].Text); } public static TheoryData, ModelResponse>> NoSseData - => new() { Snapshots.MultimodalGeneration.VlNoSse, Snapshots.MultimodalGeneration.AudioNoSse }; + => new() + { + Snapshots.MultimodalGeneration.VlNoSse, + Snapshots.MultimodalGeneration.AudioNoSse, + Snapshots.MultimodalGeneration.OcrNoSse, + Snapshots.MultimodalGeneration.VideoNoSse + }; public static TheoryData, ModelResponse>> SseData - => new() { Snapshots.MultimodalGeneration.VlSse, Snapshots.MultimodalGeneration.AudioSse }; + => new() + { + Snapshots.MultimodalGeneration.VlSse, + Snapshots.MultimodalGeneration.AudioSse, + Snapshots.MultimodalGeneration.OcrSse, + Snapshots.MultimodalGeneration.VideoSse + }; } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs index b5cec43..e3b5424 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs @@ -9,9 +9,11 @@ public class QWenMultimodalApiTests { private static readonly List Messages = [ - new MultimodalMessage( - "user", - new List { new("https://cdn.example.com/image.jpg"), new("说明一下这张图片的内容") }) + MultimodalMessage.User( + [ + MultimodalMessageContent.ImageContent("https://cdn.example.com/image.jpg"), + MultimodalMessageContent.TextContent("说明一下这张图片的内容") + ]) ]; [Fact] diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.body.json new file mode 100644 index 0000000..303157e --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.body.json @@ -0,0 +1,26 @@ +{ + "model": "qwen-max", + "input": { + "messages": [ + { + "role": "user", + "content": "请对“春天来了,大地”这句话进行续写,来表达春天的美好和作者的喜悦之情" + }, + { + "role": "assistant", + "content": "春天来了,大地", + "partial": true + } + ] + }, + "parameters": { + "result_format": "message", + "seed": 1234, + "top_p": 0.8, + "top_k": 100, + "repetition_penalty": 1.1, + "temperature": 0.85, + "stop": [[37763, 367]], + "enable_search": false + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt new file mode 100644 index 0000000..e7d8a02 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt @@ -0,0 +1,7 @@ +POST /api/v1/services/aigc/text-generation/generation HTTP/1.1 +Content-Type: application/json +Cache-Control: no-cache +Host: dashscope.aliyuncs.com +Accept-Encoding: gzip, deflate, br +Connection: keep-alive +Content-Length: 707 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt new file mode 100644 index 0000000..f76bd73 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":"仿佛从漫长的冬眠中苏醒过来,万物复苏。嫩绿的小草悄悄地探出了头,争先恐后地想要沐浴在温暖的阳光下;五彩斑斓的花朵也不甘示弱,竞相绽放着自己最美丽的姿态,将田野、山林装扮得分外妖娆。微风轻轻吹过,带来了泥土的气息与花香混合的独特香味,让人心旷神怡。小鸟们开始忙碌起来,在枝头欢快地歌唱,似乎也在庆祝这个充满希望的新季节的到来。这一切美好景象不仅让人感受到了大自然的魅力所在,更激发了人们对生活无限热爱和向往的心情。"}}]},"usage":{"total_tokens":165,"output_tokens":131,"input_tokens":34},"request_id":"4c45d7fd-3158-9ff4-96a0-6e92c710df2c"} \ No newline at end of file diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt new file mode 100644 index 0000000..27359c1 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +eagleeye-traceid: 388380d48c981a6d71df681abd540082 +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Encoding +X-Request-ID: 4c45d7fd-3158-9ff4-96a0-6e92c710df2c +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 10106 +req-arrive-time: 1732607238505 +resp-start-time: 1732607248611 +x-envoy-upstream-service-time: 10099 +Set-Cookie: acw_tc=4c45d7fd-3158-9ff4-96a0-6e92c710df2ca00c6f0f6a7b293956229af636cc6480;path=/;HttpOnly;Max-Age=1800 +Date: Tue, 26 Nov 2024 07:47:28 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.body.txt index 1a206a5..078c43b 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.body.txt +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.body.txt @@ -1 +1 @@ -{"output":{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":[{"text":"这是在海滩上。"}]}}]},"usage":{"output_tokens":6,"input_tokens":3613,"image_tokens":3577},"request_id":"e74b364a-034f-9d0d-8e55-8e5b3580045f"} \ No newline at end of file +{"output":{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":[{"text":"海滩。"}]}}]},"usage":{"output_tokens":3,"input_tokens":3613,"image_tokens":3577},"request_id":"e81aa922-be6c-9f9d-bd4f-0f43e21fd913"} \ No newline at end of file diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.header.txt index 46cc64f..5ae6d1f 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.header.txt +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.header.txt @@ -1,15 +1,15 @@ HTTP/1.1 200 OK -eagleeye-traceid: c72728928fd0d00883f6edd204cc6721 +eagleeye-traceid: 6ef123e0e464aa2286b86b1e22f1fba8 Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Encoding -X-Request-ID: e74b364a-034f-9d0d-8e55-8e5b3580045f +X-Request-ID: e81aa922-be6c-9f9d-bd4f-0f43e21fd913 x-dashscope-timeout: 180 x-dashscope-call-gateway: true x-dashscope-finished: true -req-cost-time: 3064 -req-arrive-time: 1732531979928 -resp-start-time: 1732531982993 -x-envoy-upstream-service-time: 3054 -Set-Cookie: acw_tc=e74b364a-034f-9d0d-8e55-8e5b3580045f47b5c24e3af603d8590358e45e4696a6;path=/;HttpOnly;Max-Age=1800 -Date: Mon, 25 Nov 2024 10:53:02 GMT +req-cost-time: 2842 +req-arrive-time: 1732600384861 +resp-start-time: 1732600387704 +x-envoy-upstream-service-time: 2834 +Set-Cookie: acw_tc=e81aa922-be6c-9f9d-bd4f-0f43e21fd913a06f2cf8189460ce1bbb22a9635a0746;path=/;HttpOnly;Max-Age=1800 +Date: Tue, 26 Nov 2024 05:53:07 GMT Server: istio-envoy Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json new file mode 100644 index 0000000..2f6ea86 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json @@ -0,0 +1,24 @@ +{ + "model": "qwen-vl-ocr", + "input":{ + "messages":[ + { + "role": "user", + "content": [ + { + "image": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/ctdzex/biaozhun.jpg", + "min_pixels": 3136, + "max_pixels": 1003520 + }, + {"text": "Read all the text in the image."} + ] + } + ] + }, + "parameters": { + "top_p": 0.01, + "temperature": 0.1, + "repetition_penalty": 1.05, + "max_tokens":2000 + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt new file mode 100644 index 0000000..54ebe45 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/services/aigc/multimodal-generation/generation HTTP/1.1 +Content-Type: application/json +Accept: */* +Cache-Control: no-cache +Host: dashscope.aliyuncs.com +Accept-Encoding: gzip, deflate, br +Connection: keep-alive +Content-Length: 660 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt new file mode 100644 index 0000000..5b61913 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":[{"text":"读者对象 如果你是Linux环境下的系统管理员,那么学会编写shell脚本将让你受益匪浅。本书并未细述安装 Linux系统的每个步骤,但只要系统已安装好Linux并能运行起来,你就可以开始考虑如何让一些日常 的系统管理任务实现自动化。这时shell脚本编程就能发挥作用了,这也正是本书的作用所在。本书将 演示如何使用shell脚本来自动处理系统管理任务,包括从监测系统统计数据和数据文件到为你的老板 生成报表。 如果你是家用Linux爱好者,同样能从本书中获益。现今,用户很容易在诸多部件堆积而成的图形环境 中迷失。大多数桌面Linux发行版都尽量向一般用户隐藏系统的内部细节。但有时你确实需要知道内部 发生了什么。本书将告诉你如何启动Linux命令行以及接下来要做什么。通常,如果是执行一些简单任 务(比如文件管理) , 在命令行下操作要比在华丽的图形界面下方便得多。在命令行下有大量的命令 可供使用,本书将会展示如何使用它们。"}]}}]},"usage":{"output_tokens":225,"input_tokens":1248,"image_tokens":1219},"request_id":"195c98cd-4ee5-998b-b662-132b7aebc048"} \ No newline at end of file diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt new file mode 100644 index 0000000..8aa0cea --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +eagleeye-traceid: a95a2bd8e12ed1d4309408b093be46db +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Encoding +X-Request-ID: 195c98cd-4ee5-998b-b662-132b7aebc048 +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 2952 +req-arrive-time: 1732601627527 +resp-start-time: 1732601630480 +x-envoy-upstream-service-time: 2944 +Set-Cookie: acw_tc=195c98cd-4ee5-998b-b662-132b7aebc048678d4710803e7adaf580dc20e7394b8d;path=/;HttpOnly;Max-Age=1800 +Date: Tue, 26 Nov 2024 06:13:50 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json new file mode 100644 index 0000000..ace7eda --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json @@ -0,0 +1,25 @@ +{ + "model": "qwen-vl-ocr", + "input":{ + "messages":[ + { + "role": "user", + "content": [ + { + "image": "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/ctdzex/biaozhun.jpg", + "min_pixels": 3136, + "max_pixels": 1003520 + }, + {"text": "Read all the text in the image."} + ] + } + ] + }, + "parameters": { + "top_p": 0.01, + "temperature": 0.1, + "repetition_penalty": 1.05, + "max_tokens":2000, + "incremental_output": true + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt new file mode 100644 index 0000000..0d47535 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/services/aigc/multimodal-generation/generation HTTP/1.1 +Accept: text/event-stream +Content-Type: application/json +Cache-Control: no-cache +Host: dashscope.aliyuncs.com +Accept-Encoding: gzip, deflate, br +Connection: keep-alive +Content-Length: 697 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt new file mode 100644 index 0000000..9f548bf --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt @@ -0,0 +1,300 @@ +id:1 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"读者"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":1,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:2 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"对象"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":2,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:3 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" 如果"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":3,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:4 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"你是"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":4,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:5 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"Linux环境下的系统"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":8,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:6 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"管理员,那么学会"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":12,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:7 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"编写shell脚本"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":16,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:8 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"将让你受益匪"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":20,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:9 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"浅。本书并未"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":24,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:10 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"细述安装 Linux"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":28,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:11 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"系统的每个步骤,"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":32,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:12 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"但只要系统已"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":36,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:13 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"安装好Linux并"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":40,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:14 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"能运行起来,"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":44,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:15 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"你就可以开始考虑"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":48,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:16 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"如何让一些日常"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":52,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:17 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" 的系统管理任务"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":56,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:18 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"实现自动化。这时"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":60,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:19 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"shell脚本编程"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":64,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:20 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"就能发挥作用了,"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":68,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:21 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"这也正是本书的作用"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":72,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:22 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"所在。本书将"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":76,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:23 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" 演示"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":80,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:24 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"如何使用shell脚"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":84,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:25 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"本来自动处理系统"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":88,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:26 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"管理任务,包括"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":92,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:27 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"从监测系统统计数据"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":96,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:28 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"和数据文件到"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":100,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:29 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"为你的老板"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":104,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:30 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" 生成报表。 如果"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":108,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:31 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"你是家用Linux爱好者"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":112,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:32 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":",同样能从"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":116,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:33 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"本书中获益"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":120,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:34 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"。现今,用户"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":124,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:35 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"很容易在诸多部件"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":128,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:36 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"堆积而成的图形"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":132,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:37 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"环境 中迷失。"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":136,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:38 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"大多数桌面Linux发行"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":140,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:39 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"版都尽量向"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":144,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:40 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"一般用户隐藏系统的"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":148,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:41 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"内部细节。但"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":152,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:42 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"有时你确实需要"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":156,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:43 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"知道内部 发生"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":160,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:44 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"了什么。本书"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":164,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:45 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"将告诉你如何启动"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":168,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:46 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"Linux命令行以及"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":172,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:47 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"接下来要做什么。"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":176,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:48 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"通常,如果是执行"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":180,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:49 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"一些简单任"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":184,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:50 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" 务(比如文件"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":188,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:51 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"管理) , 在"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":192,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:52 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"命令行下操作"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":196,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:53 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"要比在华丽的"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":200,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:54 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"图形界面下方便"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":204,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:55 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"得多。在命令"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":208,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:56 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"行下有大量的命令"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":212,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:57 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" 可供使用"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":216,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:58 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":",本书将会展示"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":220,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:59 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"如何使用它们。"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1248,"output_tokens":224,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + +id:60 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[],"role":"assistant"},"finish_reason":"stop"}]},"usage":{"input_tokens":1248,"output_tokens":225,"image_tokens":1219},"request_id":"fb33a990-3826-9386-8b0a-8317dfc38c1c"} + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt new file mode 100644 index 0000000..ca1ca40 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +eagleeye-traceid: b382371c2f6a177a3148f0daafa306db +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers +X-Request-ID: fb33a990-3826-9386-8b0a-8317dfc38c1c +x-dashscope-call-gateway: true +x-dashscope-timeout: 180 +x-dashscope-finished: false +req-cost-time: 961 +req-arrive-time: 1732602722387 +resp-start-time: 1732602723349 +x-envoy-upstream-service-time: 952 +Set-Cookie: acw_tc=fb33a990-3826-9386-8b0a-8317dfc38c1c2967802ac6bc4eab0577862bd43cfc3d;path=/;HttpOnly;Max-Age=1800 +Date: Tue, 26 Nov 2024 06:32:03 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.body.txt index d50c368..ef98f2d 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.body.txt +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.body.txt @@ -1,44 +1,70 @@ -id:1 +id:1 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"这张"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":1,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"这是一个"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":1,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:2 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"照片"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":2,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"海滩"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":2,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:3 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"显示"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":3,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":","}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":3,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:4 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"的是海滩景色,但是"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":8,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"有沙滩和海浪"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":8,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:5 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"无法确定具体的位置信息。图中"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":16,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"。在前景中坐着一个女人与"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":16,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:6 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"有一名女子和一只狗在沙滩"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":24,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"她的宠物狗互动。背景中有海水"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":24,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:7 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"上互动。背景中有海洋和夕阳"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":32,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"、阳光及远处的海岸线。"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":32,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:8 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"的余晖照耀着天空。"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":40,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"由于没有具体标识物或地标信息"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":40,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:9 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"请注意这是一张插画风格的艺术"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":48,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":",我无法提供更精确的位置描述"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":48,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:10 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"作品,并非实际的照片或新闻内容"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1284,"output_tokens":56,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"。这可能是一个公共海滩或是私人"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":56,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + id:11 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":[{"text":"。"}],"role":"assistant"},"finish_reason":"stop"}]},"usage":{"input_tokens":1284,"output_tokens":58,"image_tokens":1247},"request_id":"81001ee4-6155-9d17-8533-195f61c8f036"} +data:{"output":{"choices":[{"message":{"content":[{"text":"区域。重要的是要注意不要泄露任何"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":64,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + +id:12 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"个人隐私,并遵守当地的规定和法律法规"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":72,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + +id:13 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"。欣赏自然美景的同时请尊重环境"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"input_tokens":1283,"output_tokens":80,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + +id:14 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"和其他访客。"}],"role":"assistant"},"finish_reason":"stop"}]},"usage":{"input_tokens":1283,"output_tokens":85,"image_tokens":1247},"request_id":"13c5644d-339c-928a-a09a-e0414bfaa95c"} + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.header.txt index 421b505..dc9b3ca 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.header.txt +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.header.txt @@ -1,13 +1,14 @@ -HTTP/1.1 200 OK -eagleeye-traceid: 7d51c7163d594abe4fbbbbfedf1acb30 -x-request-id: 81001ee4-6155-9d17-8533-195f61c8f036 -content-type: text/event-stream;charset=UTF-8 +HTTP/1.1 200 OK +eagleeye-traceid: 8453e525821035977b4d7f8cf52b063a +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers +X-Request-ID: 13c5644d-339c-928a-a09a-e0414bfaa95c x-dashscope-call-gateway: true -content-encoding: gzip -req-cost-time: 1831 -req-arrive-time: 1709020672460 -resp-start-time: 1709020674291 -x-envoy-upstream-service-time: 1825 -date: Tue, 27 Feb 2024 07:57:54 GMT -server: istio-envoy -transfer-encoding: chunked +x-dashscope-timeout: 180 +x-dashscope-finished: false +req-cost-time: 881 +req-arrive-time: 1732600387756 +resp-start-time: 1732600388637 +x-envoy-upstream-service-time: 873 +Date: Tue, 26 Nov 2024 05:53:08 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json new file mode 100644 index 0000000..ee71700 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json @@ -0,0 +1,29 @@ +{ + "model": "qwen-vl-max", + "input": { + "messages": [ + { + "role": "user", + "content": [ + { + "video": [ + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/xzsgiz/football1.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/tdescd/football2.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/zefdja/football3.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/aedbqh/football4.jpg" + ] + }, + { + "text": "描述这个视频的具体过程" + } + ] + } + ] + }, + "parameters": { + "seed": 1234, + "top_p": 0.01, + "temperature": 0.1, + "repetition_penalty": 1.05 + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt new file mode 100644 index 0000000..af4637d --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/services/aigc/multimodal-generation/generation HTTP/1.1 +Content-Type: application/json +Accept: */* +Cache-Control: no-cache +Host: dashscope.aliyuncs.com +Accept-Encoding: gzip, deflate, br +Connection: keep-alive +Content-Length: 885 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt new file mode 100644 index 0000000..29f9112 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":[{"text":"这段视频展示了一场足球比赛的精彩瞬间。具体过程如下:\n\n1. **背景**:画面中是一个大型体育场,观众席上坐满了观众,气氛热烈。\n2. **球员位置**:球场上有两队球员,一队穿着红色球衣,另一队穿着蓝色球衣。守门员穿着绿色球衣,站在球门前准备防守。\n3. **射门动作**:一名身穿红色球衣的球员在禁区内接到队友传球后,迅速起脚射门。\n4. **守门员扑救**:守门员看到对方射门后,立即做出反应,向左侧跃出试图扑救。\n5. **进球瞬间**:尽管守门员尽力扑救,但皮球还是从他的右侧飞入了球网。\n\n整个过程充满了紧张和刺激,展示了足球比赛中的精彩时刻。"}]}}]},"usage":{"output_tokens":180,"video_tokens":1440,"input_tokens":1466},"request_id":"d538f8cc-8048-9ca8-9e8a-d2a49985b479"} \ No newline at end of file diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt new file mode 100644 index 0000000..4a21dd0 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +eagleeye-traceid: 0e28027cbf3a53882af7ea3a786d3c0a +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Encoding +X-Request-ID: d538f8cc-8048-9ca8-9e8a-d2a49985b479 +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 10391 +req-arrive-time: 1732605634343 +resp-start-time: 1732605644735 +x-envoy-upstream-service-time: 10383 +Set-Cookie: acw_tc=d538f8cc-8048-9ca8-9e8a-d2a49985b479887bd46885d75b2d029895e0a0f631bd;path=/;HttpOnly;Max-Age=1800 +Date: Tue, 26 Nov 2024 07:20:44 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.body.json new file mode 100644 index 0000000..5df0a00 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.body.json @@ -0,0 +1,30 @@ +{ + "model": "qwen-vl-max", + "input": { + "messages": [ + { + "role": "user", + "content": [ + { + "video": [ + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/xzsgiz/football1.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/tdescd/football2.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/zefdja/football3.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/aedbqh/football4.jpg" + ] + }, + { + "text": "描述这个视频的具体过程" + } + ] + } + ] + }, + "parameters": { + "seed": 1234, + "top_p": 0.01, + "temperature": 0.1, + "repetition_penalty": 1.05, + "incremental_output": true + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt new file mode 100644 index 0000000..f7fbab5 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/services/aigc/multimodal-generation/generation HTTP/1.1 +Accept: text/event-stream +Content-Type: application/json +Cache-Control: no-cache +Host: dashscope.aliyuncs.com +Accept-Encoding: gzip, deflate, br +Connection: keep-alive +Content-Length: 918 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt new file mode 100644 index 0000000..5acd2ae --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt @@ -0,0 +1,235 @@ +id:1 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"这段"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":1},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:2 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"视频"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":2},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:3 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"展示"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":3},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:4 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"了一场"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":4},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:5 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"足球比赛的精彩"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":8},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:6 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"瞬间。具体过程"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":12},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:7 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"如下:\n\n1."}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":16},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:8 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" **背景**:"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":20},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:9 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"画面中是一个大型"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":24},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:10 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"体育场,观众席"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":28},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:11 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"上坐满了观众"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":32},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:12 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":",气氛热烈。"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":36},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:13 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"\n2. **球员"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":40},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:14 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"位置**:场"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":44},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:15 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"上有两队球员"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":48},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:16 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":",一队穿着"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":52},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:17 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"红色球衣,"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":56},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:18 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"另一队穿着蓝色"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":60},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:19 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"球衣。守"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":64},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:20 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"门员穿着绿色"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":68},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:21 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"球衣,站在"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":72},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:22 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"球门前准备防守"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":76},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:23 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"。\n3. **"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":80},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:24 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"射门动作**"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":84},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:25 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":":一名身穿红色"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":88},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:26 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"球衣的球员"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":92},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:27 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"在禁区内接到"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":96},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:28 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"队友传球后,"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":100},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:29 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"迅速起脚射"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":104},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:30 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"门。\n4."}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":108},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:31 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":" **扑救尝试"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":112},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:32 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"**:守门"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":116},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:33 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"员看到射门"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":120},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:34 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"后立即做出反应"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":124},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:35 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":",向左侧跃"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":128},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:36 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"出试图扑救"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":132},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:37 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"。\n5. **"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":136},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:38 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"进球瞬间**:"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":140},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:39 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"尽管守门员"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":144},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:40 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"尽力扑救,"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":148},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:41 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"但皮球还是"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":152},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:42 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"从他的右侧飞"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":156},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:43 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"入了球网"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":160},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:44 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"。\n\n整个过程充满了"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":164},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:45 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"紧张和刺激,"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":168},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:46 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"展示了足球比赛中的"}],"role":"assistant"},"finish_reason":"null"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":172},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + +id:47 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":[{"text":"精彩时刻。"}],"role":"assistant"},"finish_reason":"stop"}]},"usage":{"video_tokens":1440,"input_tokens":1466,"output_tokens":176},"request_id":"851745a1-22ba-90e2-ace2-c04e7445ec6f"} + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt new file mode 100644 index 0000000..0bfc050 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt @@ -0,0 +1,14 @@ +HTTP/1.1 200 OK +eagleeye-traceid: 09ccc1f2abe78d28e9f4a516b156be9f +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers +X-Request-ID: 851745a1-22ba-90e2-ace2-c04e7445ec6f +x-dashscope-call-gateway: true +x-dashscope-timeout: 180 +x-dashscope-finished: false +req-cost-time: 4629 +req-arrive-time: 1732605644800 +resp-start-time: 1732605649430 +x-envoy-upstream-service-time: 4620 +Date: Tue, 26 Nov 2024 07:20:49 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.body.json new file mode 100644 index 0000000..3dd0091 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.body.json @@ -0,0 +1,24 @@ +{ + "model": "qwen-max", + "input": { + "messages": [ + { + "role": "user", + "content": "请问 1+1 是多少?用 JSON 格式输出。" + } + ] + }, + "parameters": { + "result_format": "message", + "seed": 1234, + "max_tokens": 1500, + "top_p": 0.8, + "top_k": 100, + "repetition_penalty": 1.1, + "temperature": 0.85, + "stop": [[37763, 367]], + "enable_search": false, + "incremental_output": false, + "response_format": { "type": "json_object" } + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.header.txt new file mode 100644 index 0000000..061b3f8 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/services/aigc/text-generation/generation HTTP/1.1 +Content-Type: application/json +Accept: */* +Cache-Control: no-cache +Host: dashscope.aliyuncs.com +Accept-Encoding: gzip, deflate, br +Connection: keep-alive +Content-Length: 616 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.body.txt new file mode 100644 index 0000000..dbaa6c2 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":"{\n \"result\": 2\n}"}}]},"usage":{"total_tokens":34,"output_tokens":9,"input_tokens":25},"request_id":"6af9571b-1033-98f9-a287-c06f2e9d6f7f"} \ No newline at end of file diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.header.txt new file mode 100644 index 0000000..80d82cb --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +eagleeye-traceid: 6c8828e3019673424bb954fcabd824d2 +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Encoding +X-Request-ID: 6af9571b-1033-98f9-a287-c06f2e9d6f7f +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 1037 +req-arrive-time: 1732599712701 +resp-start-time: 1732599713739 +x-envoy-upstream-service-time: 1029 +Set-Cookie: acw_tc=6af9571b-1033-98f9-a287-c06f2e9d6f7f149f359cea6c216c66a1630c9eaa00b9;path=/;HttpOnly;Max-Age=1800 +Date: Tue, 26 Nov 2024 05:41:53 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs index 7df2c1d..4cb54b0 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs @@ -93,7 +93,27 @@ public async Task SingleCompletion_MessageFormatSse_SuccessAsync() } [Theory] - [MemberData(nameof(ConversationMessageFormatData))] + [MemberData(nameof(ConversationMessageFormatNoSseData))] + public async Task ConversationCompletion_MessageFormatNoSse_SuccessAsync( + RequestSnapshot, + ModelResponse> testCase) + { + // Arrange + const bool sse = false; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var response = await client.GetTextCompletionAsync(testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + response.Should().BeEquivalentTo(testCase.ResponseModel); + } + + [Theory] + [MemberData(nameof(ConversationMessageFormatSseData))] public async Task ConversationCompletion_MessageFormatSse_SuccessAsync( RequestSnapshot, ModelResponse> testCase) @@ -124,7 +144,11 @@ public async Task ConversationCompletion_MessageFormatSse_SuccessAsync( Snapshots.TextGeneration.MessageFormat.SingleMessageWithTools); public static readonly TheoryData, - ModelResponse>> ConversationMessageFormatData = new( + ModelResponse>> ConversationMessageFormatSseData = new( Snapshots.TextGeneration.MessageFormat.ConversationMessageIncremental, Snapshots.TextGeneration.MessageFormat.ConversationMessageWithFilesIncremental); + + public static readonly TheoryData, + ModelResponse>> ConversationMessageFormatNoSseData = new( + Snapshots.TextGeneration.MessageFormat.ConversationPartialMessageNoSse); } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Cases.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Cases.cs index ad439df..ef89ef4 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Cases.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Cases.cs @@ -11,5 +11,5 @@ internal class Cases public const string ImageUrl = "https://www.cnblogs.com/image.png"; public static readonly List TextMessages = - [new("system", "you are a helpful assistant"), new("user", "hello")]; + [ChatMessage.System("you are a helpful assistant"), ChatMessage.User("hello")]; } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs index ec6cf77..8ed0fb0 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs @@ -12,10 +12,10 @@ public static readonly RequestSnapshot, DashScopeError> AuthError = new( "auth-error", - new() + new ModelRequest { Model = "qwen-max", - Input = new() { Prompt = "请问 1+1 是多少?" }, + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, Parameters = new TextGenerationParameters { ResultFormat = "text", @@ -30,7 +30,7 @@ public static readonly IncrementalOutput = false } }, - new() + new DashScopeError { Code = "InvalidApiKey", Message = "Invalid API-key provided.", @@ -41,10 +41,10 @@ public static readonly RequestSnapshot, DashScopeError> ParameterError = new( "parameter-error", - new() + new ModelRequest { Model = "qwen-max", - Input = new() { Prompt = "请问 1+1 是多少?", Messages = [] }, + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, Parameters = new TextGenerationParameters { ResultFormat = "text", @@ -59,7 +59,7 @@ public static readonly IncrementalOutput = false } }, - new() + new DashScopeError { Code = "InvalidParameter", Message = "Role must be user or assistant and Content length must be greater than 0", @@ -70,10 +70,10 @@ public static readonly RequestSnapshot, DashScopeError> ParameterErrorSse = new( "parameter-error", - new() + new ModelRequest { Model = "qwen-max", - Input = new() { Prompt = "请问 1+1 是多少?", Messages = [] }, + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, Parameters = new TextGenerationParameters { ResultFormat = "text", @@ -88,7 +88,7 @@ public static readonly IncrementalOutput = true } }, - new() + new DashScopeError { Code = "InvalidParameter", Message = "Role must be user or assistant and Content length must be greater than 0", @@ -97,7 +97,7 @@ public static readonly public static readonly RequestSnapshot UploadErrorNoSse = new( "upload-file-error", - new() + new DashScopeError { Code = "invalid_request_error", Message = "'purpose' must be 'file-extract'", @@ -113,10 +113,10 @@ public static class TextFormat ModelResponse> SinglePrompt = new( "single-generation-text", - new() + new ModelRequest { Model = "qwen-max", - Input = new() { Prompt = "请问 1+1 是多少?" }, + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, Parameters = new TextGenerationParameters { ResultFormat = "text", @@ -131,14 +131,14 @@ public static class TextFormat IncrementalOutput = false } }, - new() + new ModelResponse { - Output = new() + Output = new TextGenerationOutput { FinishReason = "stop", Text = "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下两个一相加的结果都是二。" }, RequestId = "4ef2ed16-4dc3-9083-a723-fb2e80c84d3b", - Usage = new() + Usage = new TextGenerationTokenUsage { InputTokens = 8, OutputTokens = 35, @@ -150,10 +150,10 @@ public static class TextFormat ModelResponse> SinglePromptIncremental = new( "single-generation-text", - new() + new ModelRequest { Model = "qwen-max", - Input = new() { Prompt = "请问 1+1 是多少?" }, + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, Parameters = new TextGenerationParameters { ResultFormat = "text", @@ -168,14 +168,11 @@ public static class TextFormat IncrementalOutput = true } }, - new() + new ModelResponse { - Output = new() - { - FinishReason = "stop", Text = "1+1等于2。" - }, + Output = new TextGenerationOutput { FinishReason = "stop", Text = "1+1等于2。" }, RequestId = "5b441aa7-0b9c-9fbc-ae0a-e2b212b71eac", - Usage = new() + Usage = new TextGenerationTokenUsage { InputTokens = 16, OutputTokens = 6, @@ -190,11 +187,11 @@ public static class MessageFormat ModelResponse> SingleMessage = new( "single-generation-message", - new() + new ModelRequest { Model = "qwen-max", Input = - new() { Messages = [new("user", "请问 1+1 是多少?")] }, + new TextGenerationInput { Messages = [ChatMessage.User("请问 1+1 是多少?")] }, Parameters = new TextGenerationParameters { ResultFormat = "message", @@ -209,23 +206,22 @@ public static class MessageFormat IncrementalOutput = false } }, - new() + new ModelResponse { - Output = new() + Output = new TextGenerationOutput { Choices = [ - new() + new TextGenerationChoice { FinishReason = "stop", - Message = new( - "assistant", + Message = ChatMessage.Assistant( "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") } ] }, RequestId = "e764bfe3-c0b7-97a0-ae57-cd99e1580960", - Usage = new() + Usage = new TextGenerationTokenUsage { TotalTokens = 47, OutputTokens = 39, @@ -233,15 +229,61 @@ public static class MessageFormat } }); + public static readonly RequestSnapshot, + ModelResponse> + SingleMessageJson = new( + "single-generation-message-json", + new ModelRequest + { + Model = "qwen-max", + Input = + new TextGenerationInput { Messages = [ChatMessage.User("请问 1+1 是多少?用 JSON 格式输出。")] }, + Parameters = new TextGenerationParameters + { + ResultFormat = "message", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new int[][] { [37763, 367] }, + EnableSearch = false, + IncrementalOutput = false, + ResponseFormat = DashScopeResponseFormat.Json + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = ChatMessage.Assistant("{\\n \\\"result\\\": 2\\n}") + } + ] + }, + RequestId = "6af9571b-1033-98f9-a287-c06f2e9d6f7f", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 34, + OutputTokens = 9, + InputTokens = 25 + } + }); + public static readonly RequestSnapshot, ModelResponse> SingleMessageIncremental = new( "single-generation-message", - new() + new ModelRequest { Model = "qwen-max", Input = - new() { Messages = [new("user", "请问 1+1 是多少?")] }, + new TextGenerationInput { Messages = [ChatMessage.User("请问 1+1 是多少?")] }, Parameters = new TextGenerationParameters { ResultFormat = "message", @@ -256,23 +298,22 @@ public static class MessageFormat IncrementalOutput = true } }, - new() + new ModelResponse { - Output = new() + Output = new TextGenerationOutput { Choices = [ - new() + new TextGenerationChoice { FinishReason = "stop", - Message = new( - "assistant", + Message = ChatMessage.Assistant( "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") } ] }, RequestId = "d272255f-82d7-9cc7-93c5-17ff77024349", - Usage = new() + Usage = new TextGenerationTokenUsage { TotalTokens = 48, OutputTokens = 40, @@ -285,10 +326,10 @@ public static readonly ModelResponse> SingleMessageWithTools = new( "single-generation-message-with-tools", - new() + new ModelRequest { Model = "qwen-max", - Input = new() { Messages = [new("user", "杭州现在的天气如何?")] }, + Input = new TextGenerationInput { Messages = [ChatMessage.User("杭州现在的天气如何?")] }, Parameters = new TextGenerationParameters() { ResultFormat = "message", @@ -299,7 +340,7 @@ public static readonly RepetitionPenalty = 1.1f, PresencePenalty = 1.2f, Temperature = 0.85f, - Stop = new("你好"), + Stop = new TextGenerationStop("你好"), EnableSearch = false, IncrementalOutput = false, Tools = @@ -310,7 +351,7 @@ public static readonly "get_current_weather", "获取现在的天气", new JsonSchemaBuilder().FromType( - new() + new SchemaGeneratorConfiguration { PropertyNameResolver = PropertyNameResolvers.LowerSnakeCase }) @@ -319,19 +360,18 @@ public static readonly ToolChoice = ToolChoice.FunctionChoice("get_current_weather") } }, - new() + new ModelResponse { - Output = new() + Output = new TextGenerationOutput { Choices = [ - new() + new TextGenerationChoice { FinishReason = "stop", - Message = new( - "assistant", + Message = ChatMessage.Assistant( string.Empty, - ToolCalls: + toolCalls: [ new ToolCall( "call_cec4c19d27624537b583af", @@ -344,7 +384,7 @@ public static readonly ] }, RequestId = "67300049-c108-9987-b1c1-8e0ee2de6b5d", - Usage = new() + Usage = new TextGenerationTokenUsage { InputTokens = 211, OutputTokens = 8, @@ -352,21 +392,72 @@ public static readonly } }); + public static readonly RequestSnapshot, + ModelResponse> + ConversationPartialMessageNoSse = new( + "conversation-generation-message-partial", + new ModelRequest() + { + Model = "qwen-max", + Input = new TextGenerationInput() + { + Messages = + [ + ChatMessage.User("请对“春天来了,大地”这句话进行续写,来表达春天的美好和作者的喜悦之情"), + ChatMessage.Assistant("春天来了,大地", true) + ] + }, + Parameters = new TextGenerationParameters() + { + ResultFormat = ResultFormats.Message, + Seed = 1234, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new int[][] { [37763, 367] }, + EnableSearch = false + } + }, + new ModelResponse() + { + RequestId = "4c45d7fd-3158-9ff4-96a0-6e92c710df2c", + Output = new TextGenerationOutput() + { + Choices = + [ + new TextGenerationChoice() + { + FinishReason = "stop", + Message = + ChatMessage.Assistant( + "仿佛从漫长的冬眠中苏醒过来,万物复苏。嫩绿的小草悄悄地探出了头,争先恐后地想要沐浴在温暖的阳光下;五彩斑斓的花朵也不甘示弱,竞相绽放着自己最美丽的姿态,将田野、山林装扮得分外妖娆。微风轻轻吹过,带来了泥土的气息与花香混合的独特香味,让人心旷神怡。小鸟们开始忙碌起来,在枝头欢快地歌唱,似乎也在庆祝这个充满希望的新季节的到来。这一切美好景象不仅让人感受到了大自然的魅力所在,更激发了人们对生活无限热爱和向往的心情。") + } + ] + }, + Usage = new TextGenerationTokenUsage() + { + TotalTokens = 165, + OutputTokens = 131, + InputTokens = 34 + } + }); + public static readonly RequestSnapshot, ModelResponse> ConversationMessageIncremental = new( "conversation-generation-message", - new() + new ModelRequest { Model = "qwen-max", Input = - new() + new TextGenerationInput { Messages = [ - new("user", "现在请你记住一个数字,42"), - new("assistant", "好的,我已经记住了这个数字。"), - new("user", "请问我刚才提到的数字是多少?") + ChatMessage.User("现在请你记住一个数字,42"), + ChatMessage.Assistant("好的,我已经记住了这个数字。"), + ChatMessage.User("请问我刚才提到的数字是多少?") ] }, Parameters = new TextGenerationParameters @@ -383,17 +474,20 @@ public static readonly IncrementalOutput = true } }, - new() + new ModelResponse { - Output = new() + Output = new TextGenerationOutput { Choices = [ - new() { FinishReason = "stop", Message = new("assistant", "您刚才提到的数字是42。") } + new TextGenerationChoice + { + FinishReason = "stop", Message = ChatMessage.Assistant("您刚才提到的数字是42。") + } ] }, RequestId = "9188e907-56c2-9849-97f6-23f130f7fed7", - Usage = new() + Usage = new TextGenerationTokenUsage { TotalTokens = 33, OutputTokens = 9, @@ -405,16 +499,17 @@ public static readonly ModelResponse> ConversationMessageWithFilesIncremental = new( "conversation-generation-message-with-files", - new() + new ModelRequest { Model = "qwen-long", Input = - new() + new TextGenerationInput { Messages = [ - new(["file-fe-WTTG89tIUTd4ByqP3K48R3bn", "file-fe-l92iyRvJm9vHCCfonLckf1o2"]), - new("user", "这两个文件是相同的吗?") + ChatMessage.File( + ["file-fe-WTTG89tIUTd4ByqP3K48R3bn", "file-fe-l92iyRvJm9vHCCfonLckf1o2"]), + ChatMessage.User("这两个文件是相同的吗?") ] }, Parameters = new TextGenerationParameters @@ -431,23 +526,22 @@ public static readonly IncrementalOutput = true } }, - new() + new ModelResponse { - Output = new() + Output = new TextGenerationOutput { Choices = [ - new() + new TextGenerationChoice { FinishReason = "stop", - Message = new( - "assistant", + Message = ChatMessage.Assistant( "你上传的两个文件并不相同。第一个文件`test1.txt`包含两行文本,每行都是“测试”。而第二个文件`test2.txt`只有一行文本,“测试2”。尽管它们都含有“测试”这个词,但具体内容和结构不同。") } ] }, RequestId = "7865ae43-8379-9c79-bef6-95050868bc52", - Usage = new() + Usage = new TextGenerationTokenUsage { TotalTokens = 115, OutputTokens = 57, @@ -463,22 +557,21 @@ public static class MultimodalGeneration ModelResponse> VlNoSse = new( "multimodal-generation-vl", - new() + new ModelRequest { Model = "qwen-vl-plus", - Input = new() + Input = new MultimodalInput { Messages = [ - new( - "system", - [new(null, "You are a helpful assistant.")]), - new( - "user", - [ - new("https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), - new(null, "这个图片是哪里,请用简短的语言回答") - ]) + MultimodalMessage.System( + [MultimodalMessageContent.TextContent("You are a helpful assistant.")]), + MultimodalMessage.User( + [ + MultimodalMessageContent.ImageContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + ]) ] }, Parameters = new MultimodalParameters @@ -494,24 +587,21 @@ public static class MultimodalGeneration Stop = "你好" } }, - new() + new ModelResponse { - Output = new( + Output = new MultimodalOutput( [ - new( + new MultimodalChoice( "stop", - new( - "assistant", - [ - new( - null, - "这是在海滩上。") - ])) + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent("海滩。") + ])) ]), - RequestId = "e74b364a-034f-9d0d-8e55-8e5b3580045f", - Usage = new() + RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", + Usage = new MultimodalTokenUsage { - OutputTokens = 6, + OutputTokens = 3, InputTokens = 3613, ImageTokens = 3577 } @@ -521,22 +611,21 @@ public static class MultimodalGeneration ModelResponse> VlSse = new( "multimodal-generation-vl", - new() + new ModelRequest { Model = "qwen-vl-plus", - Input = new() + Input = new MultimodalInput { Messages = [ - new( - "system", - [new(null, "You are a helpful assistant.")]), - new( - "user", - [ - new("https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), - new(null, "这个图片是哪里,请用简短的语言回答") - ]) + MultimodalMessage.System( + [MultimodalMessageContent.TextContent("You are a helpful assistant.")]), + MultimodalMessage.User( + [ + MultimodalMessageContent.ImageContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + ]) ] }, Parameters = new MultimodalParameters @@ -547,49 +636,147 @@ public static class MultimodalGeneration TopP = 0.81f } }, - new() + new ModelResponse { - Output = new( + Output = new MultimodalOutput( [ - new( + new MultimodalChoice( "stop", - new( - "assistant", - [ - new( - null, - "这张照片显示的是海滩景色,但是无法确定具体的位置信息。图中有一名女子和一只狗在沙滩上互动。背景中有海洋和夕阳的余晖照耀着天空。请注意这是一张插画风格的艺术作品,并非实际的照片或新闻内容。") - ])) + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") + ])) ]), - RequestId = "81001ee4-6155-9d17-8533-195f61c8f036", - Usage = new() + RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", + Usage = new MultimodalTokenUsage { - OutputTokens = 58, - InputTokens = 1284, + OutputTokens = 85, + InputTokens = 1283, ImageTokens = 1247 } }); + public static readonly RequestSnapshot, + ModelResponse> + OcrNoSse = new( + "multimodal-generation-vl-ocr", + new ModelRequest + { + Model = "qwen-vl-ocr", + Input = new MultimodalInput + { + Messages = + [ + MultimodalMessage.User( + [ + MultimodalMessageContent.ImageContent( + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/ctdzex/biaozhun.jpg", + 3136, + 1003520), + MultimodalMessageContent.TextContent("Read all the text in the image.") + ]), + ] + }, + Parameters = new MultimodalParameters + { + Temperature = 0.1f, + RepetitionPenalty = 1.05f, + MaxTokens = 2000, + TopP = 0.01f + } + }, + new ModelResponse + { + RequestId = "195c98cd-4ee5-998b-b662-132b7aebc048", + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "读者对象 如果你是Linux环境下的系统管理员,那么学会编写shell脚本将让你受益匪浅。本书并未细述安装 Linux系统的每个步骤,但只要系统已安装好Linux并能运行起来,你就可以开始考虑如何让一些日常 的系统管理任务实现自动化。这时shell脚本编程就能发挥作用了,这也正是本书的作用所在。本书将 演示如何使用shell脚本来自动处理系统管理任务,包括从监测系统统计数据和数据文件到为你的老板 生成报表。 如果你是家用Linux爱好者,同样能从本书中获益。现今,用户很容易在诸多部件堆积而成的图形环境 中迷失。大多数桌面Linux发行版都尽量向一般用户隐藏系统的内部细节。但有时你确实需要知道内部 发生了什么。本书将告诉你如何启动Linux命令行以及接下来要做什么。通常,如果是执行一些简单任 务(比如文件管理) , 在命令行下操作要比在华丽的图形界面下方便得多。在命令行下有大量的命令 可供使用,本书将会展示如何使用它们。") + ])) + ]), + Usage = new MultimodalTokenUsage + { + InputTokens = 1248, + OutputTokens = 225, + ImageTokens = 1219 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + OcrSse = new( + "multimodal-generation-vl-ocr", + new ModelRequest + { + Model = "qwen-vl-ocr", + Input = new MultimodalInput + { + Messages = + [ + MultimodalMessage.User( + [ + MultimodalMessageContent.ImageContent( + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/ctdzex/biaozhun.jpg", + 3136, + 1003520), + MultimodalMessageContent.TextContent("Read all the text in the image.") + ]), + ] + }, + Parameters = new MultimodalParameters + { + Temperature = 0.1f, + RepetitionPenalty = 1.05f, + MaxTokens = 2000, + TopP = 0.01f, + IncrementalOutput = true + } + }, + new ModelResponse + { + RequestId = "fb33a990-3826-9386-8b0a-8317dfc38c1c", + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "读者对象 如果你是Linux环境下的系统管理员,那么学会编写shell脚本将让你受益匪浅。本书并未细述安装 Linux系统的每个步骤,但只要系统已安装好Linux并能运行起来,你就可以开始考虑如何让一些日常 的系统管理任务实现自动化。这时shell脚本编程就能发挥作用了,这也正是本书的作用所在。本书将 演示如何使用shell脚本来自动处理系统管理任务,包括从监测系统统计数据和数据文件到为你的老板 生成报表。 如果你是家用Linux爱好者,同样能从本书中获益。现今,用户很容易在诸多部件堆积而成的图形环境 中迷失。大多数桌面Linux发行版都尽量向一般用户隐藏系统的内部细节。但有时你确实需要知道内部 发生了什么。本书将告诉你如何启动Linux命令行以及接下来要做什么。通常,如果是执行一些简单任 务(比如文件管理) , 在命令行下操作要比在华丽的图形界面下方便得多。在命令行下有大量的命令 可供使用,本书将会展示如何使用它们。") + ])) + ]), + Usage = new MultimodalTokenUsage + { + InputTokens = 1248, + OutputTokens = 225, + ImageTokens = 1219 + } + }); + public static readonly RequestSnapshot, ModelResponse> AudioNoSse = new( "multimodal-generation-audio", - new() + new ModelRequest { Model = "qwen-audio-turbo", - Input = new() + Input = new MultimodalInput { Messages = [ - new( - "system", - [new(Text: "You are a helpful assistant.")]), - new( - "user", - [ - new(Audio: "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/2channel_16K.wav"), - new(Text: "这段音频在说什么,请用简短的语言回答") - ]) + MultimodalMessage.System( + [MultimodalMessageContent.TextContent("You are a helpful assistant.")]), + MultimodalMessage.User( + [ + MultimodalMessageContent.AudioContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/2channel_16K.wav"), + MultimodalMessageContent.TextContent("这段音频在说什么,请用简短的语言回答") + ]) ] }, Parameters = new MultimodalParameters @@ -599,22 +786,20 @@ public static class MultimodalGeneration TopP = 0.81f } }, - new() + new ModelResponse { RequestId = "6b6738bd-dd9d-9e78-958b-02574acbda44", - Output = new( + Output = new MultimodalOutput( [ - new( + new MultimodalChoice( "stop", - new( - "assistant", - [ - new( - Text: - "这段音频在说中文,内容是\"没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网\"。") - ])) + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "这段音频在说中文,内容是\"没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网\"。") + ])) ]), - Usage = new() + Usage = new MultimodalTokenUsage { InputTokens = 786, OutputTokens = 38, @@ -626,22 +811,21 @@ public static class MultimodalGeneration ModelResponse> AudioSse = new( "multimodal-generation-audio", - new() + new ModelRequest { Model = "qwen-audio-turbo", - Input = new() + Input = new MultimodalInput { Messages = [ - new( - "system", - [new(Text: "You are a helpful assistant.")]), - new( - "user", - [ - new(Audio: "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/2channel_16K.wav"), - new(Text: "这段音频的第一句话说了什么?") - ]) + MultimodalMessage.System( + [MultimodalMessageContent.TextContent("You are a helpful assistant.")]), + MultimodalMessage.User( + [ + MultimodalMessageContent.AudioContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/2channel_16K.wav"), + MultimodalMessageContent.TextContent("这段音频的第一句话说了什么?") + ]) ] }, Parameters = new MultimodalParameters @@ -652,26 +836,132 @@ public static class MultimodalGeneration IncrementalOutput = true } }, - new() + new ModelResponse { RequestId = "bb6ab962-af57-99f1-9af8-eb7016ebc18e", - Output = new( + Output = new MultimodalOutput( [ - new( + new MultimodalChoice( "stop", - new( - "assistant", - [ - new(Text: "第一句话说了没有我互联网。") - ])) + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent("第一句话说了没有我互联网。") + ])) ]), - Usage = new() + Usage = new MultimodalTokenUsage { InputTokens = 783, OutputTokens = 7, AudioTokens = 752 } }); + + public static readonly RequestSnapshot, + ModelResponse> + VideoNoSse = new( + "multimodal-generation-vl-video", + new ModelRequest() + { + Model = "qwen-vl-max", + Input = new MultimodalInput() + { + Messages = + [ + MultimodalMessage.User( + [ + MultimodalMessageContent.VideoContent( + [ + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/xzsgiz/football1.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/tdescd/football2.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/zefdja/football3.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/aedbqh/football4.jpg" + ]), + MultimodalMessageContent.TextContent("描述这个视频的具体过程") + ]), + ] + }, + Parameters = new MultimodalParameters() + { + Seed = 1234, + TopP = 0.01f, + Temperature = 0.1f, + RepetitionPenalty = 1.05f + } + }, + new ModelResponse() + { + RequestId = "d538f8cc-8048-9ca8-9e8a-d2a49985b479", + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "这段视频展示了一场足球比赛的精彩瞬间。具体过程如下:\n\n1. **背景**:画面中是一个大型体育场,观众席上坐满了观众,气氛热烈。\n2. **球员位置**:球场上有两队球员,一队穿着红色球衣,另一队穿着蓝色球衣。守门员穿着绿色球衣,站在球门前准备防守。\n3. **射门动作**:一名身穿红色球衣的球员在禁区内接到队友传球后,迅速起脚射门。\n4. **守门员扑救**:守门员看到对方射门后,立即做出反应,向左侧跃出试图扑救。\n5. **进球瞬间**:尽管守门员尽力扑救,但皮球还是从他的右侧飞入了球网。\n\n整个过程充满了紧张和刺激,展示了足球比赛中的精彩时刻。") + ])) + ]), + Usage = new MultimodalTokenUsage() + { + VideoTokens = 1440, + InputTokens = 1466, + OutputTokens = 180 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + VideoSse = new( + "multimodal-generation-vl-video", + new ModelRequest() + { + Model = "qwen-vl-max", + Input = new MultimodalInput() + { + Messages = + [ + MultimodalMessage.User( + [ + MultimodalMessageContent.VideoContent( + [ + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/xzsgiz/football1.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/tdescd/football2.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/zefdja/football3.jpg", + "https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20241108/aedbqh/football4.jpg" + ]), + MultimodalMessageContent.TextContent("描述这个视频的具体过程") + ]), + ] + }, + Parameters = new MultimodalParameters() + { + Seed = 1234, + TopP = 0.01f, + Temperature = 0.1f, + RepetitionPenalty = 1.05f, + IncrementalOutput = true + } + }, + new ModelResponse() + { + RequestId = "851745a1-22ba-90e2-ace2-c04e7445ec6f", + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "这段视频展示了一场足球比赛的精彩瞬间。具体过程如下:\n\n1. **背景**:画面中是一个大型体育场,观众席上坐满了观众,气氛热烈。\n2. **球员位置**:场上有两队球员,一队穿着红色球衣,另一队穿着蓝色球衣。守门员穿着绿色球衣,站在球门前准备防守。\n3. **射门动作**:一名身穿红色球衣的球员在禁区内接到队友传球后,迅速起脚射门。\n4. **扑救尝试**:守门员看到射门后立即做出反应,向左侧跃出试图扑救。\n5. **进球瞬间**:尽管守门员尽力扑救,但皮球还是从他的右侧飞入了球网。\n\n整个过程充满了紧张和刺激,展示了足球比赛中的精彩时刻。") + ])) + ]), + Usage = new MultimodalTokenUsage() + { + VideoTokens = 1440, + InputTokens = 1466, + OutputTokens = 176 + } + }); } public static class TextEmbedding @@ -679,26 +969,26 @@ public static class TextEmbedding public static readonly RequestSnapshot, ModelResponse> NoSse = new( "text-embedding", - new() + new ModelRequest { - Input = new() { Texts = ["代码改变世界"] }, + Input = new TextEmbeddingInput { Texts = ["代码改变世界"] }, Model = "text-embedding-v2", Parameters = new TextEmbeddingParameters { TextType = "query" } }, - new() + new ModelResponse { - Output = new([new(0, [])]), + Output = new TextEmbeddingOutput([new TextEmbeddingItem(0, [])]), RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", - Usage = new(3) + Usage = new TextEmbeddingTokenUsage(3) }); public static readonly RequestSnapshot, ModelResponse> BatchNoSse = new( "batch-text-embedding", - new() + new ModelRequest { - Input = new() + Input = new BatchGetEmbeddingsInput { Url = "https://modelscope.oss-cn-beijing.aliyuncs.com/resource/text_embedding_file.txt" @@ -706,10 +996,10 @@ public static readonly Model = "text-embedding-async-v2", Parameters = new BatchGetEmbeddingsParameters { TextType = "query" } }, - new() + new ModelResponse { RequestId = "db5ce040-4548-9919-9a75-3385ee152335", - Output = new() + Output = new BatchGetEmbeddingsOutput { TaskId = "6075262c-b56d-4968-9abf-2a9784a90f3e", TaskStatus = DashScopeTaskStatus.Pending @@ -723,16 +1013,16 @@ public static readonly RequestSnapshot, ModelResponse> TokenizeNoSse = new( "tokenization", - new() + new ModelRequest { - Input = new() { Messages = [new("user", "代码改变世界")] }, + Input = new TextGenerationInput { Messages = [ChatMessage.User("代码改变世界")] }, Model = "qwen-max", Parameters = new TextGenerationParameters { Seed = 1234 } }, - new() + new ModelResponse { - Output = new([46100, 101933, 99489], ["代码", "改变", "世界"]), - Usage = new(3), + Output = new TokenizationOutput([46100, 101933, 99489], ["代码", "改变", "世界"]), + Usage = new TokenizationUsage(3), RequestId = "6615ba01-081d-9147-93ff-7bd26f3adf93" }); } @@ -742,16 +1032,16 @@ public static class Tasks public static readonly RequestSnapshot> Unknown = new( "get-task-unknown", - new( + new DashScopeTask( "85c25460-6440-91a7-b14e-2978fe60bd0f", - new() { TaskId = "1111", TaskStatus = DashScopeTaskStatus.Unknown })); + new BatchGetEmbeddingsOutput { TaskId = "1111", TaskStatus = DashScopeTaskStatus.Unknown })); public static readonly RequestSnapshot> BatchEmbeddingSuccess = new( "get-task-batch-text-embedding-success", - new( + new DashScopeTask( "0b2ebeda-a91b-948f-986a-d395cbf1d0e1", - new() + new BatchGetEmbeddingsOutput { TaskId = "7408ef3d-a0be-4379-9e72-a6e95a569483", TaskStatus = DashScopeTaskStatus.Succeeded, @@ -761,29 +1051,29 @@ public static readonly RequestSnapshot> ImageSynthesisRunning = new( "get-task-running", - new( + new DashScopeTask( "edbd4e81-d37b-97f1-9857-d7394829dd0f", - new() + new ImageSynthesisOutput { TaskStatus = DashScopeTaskStatus.Running, TaskId = "9e2b6ef6-285d-4efa-8651-4dbda7d571fa", SubmitTime = new DateTime(2024, 3, 1, 17, 38, 24, 817), ScheduledTime = new DateTime(2024, 3, 1, 17, 38, 24, 831), - TaskMetrics = new(4, 0, 0) + TaskMetrics = new DashScopeTaskMetrics(4, 0, 0) })); public static readonly RequestSnapshot> ImageSynthesisSuccess = new( "get-task-image-synthesis-success", - new( + new DashScopeTask( "6662e925-4846-9afe-a3af-0d131805d378", - new() + new ImageSynthesisOutput { TaskId = "9e2b6ef6-285d-4efa-8651-4dbda7d571fa", TaskStatus = DashScopeTaskStatus.Succeeded, @@ -792,25 +1082,25 @@ public static readonly RequestSnapshot> ImageGenerationSuccess = new( "get-task-image-generation-success", - new( + new DashScopeTask( "f927c766-5079-90f8-9354-6a87d2167897", - new() + new ImageGenerationOutput { TaskId = "c4f94e00-5899-431b-9579-eb1ebe686379", TaskStatus = DashScopeTaskStatus.Succeeded, @@ -832,9 +1122,9 @@ public static readonly RequestSnapshot> BackgroundGenerationSuccess = new( "get-task-background-generation-success", - new( + new DashScopeTask( "8b22164d-c784-9a31-bda3-3c26259d4213", - new() + new BackgroundGenerationOutput { TaskId = "b2e98d78-c79b-431c-b2d7-c7bcd54465da", TaskStatus = DashScopeTaskStatus.Succeeded, @@ -843,25 +1133,25 @@ public static readonly RequestSnapshot { { "y1", 257 }, { "x1", 0 }, @@ -884,7 +1181,7 @@ public static readonly RequestSnapshot { { "y1", 0 }, { "x1", 0 }, @@ -930,7 +1234,7 @@ public static readonly RequestSnapshot { { "y1", 257 }, { "x1", 0 }, @@ -978,7 +1289,7 @@ public static readonly RequestSnapshot { { "y1", 0 }, { "x1", 0 }, @@ -1024,7 +1342,7 @@ public static readonly RequestSnapshot CancelCompletedTask = new( "cancel-completed-task", - new( + new DashScopeTaskOperationResponse( "4d496c94-1389-9ca9-a92a-3e732f675686", "UnsupportedOperation", "Failed to cancel the task, please confirm if the task is in PENDING status.")); @@ -1088,10 +1406,10 @@ public static readonly RequestSnapshot, ModelResponse> CreateTask = new( "image-synthesis", - new() + new ModelRequest { Model = "wanx-v1", - Input = new() { Prompt = "一只奔跑的猫" }, + Input = new ImageSynthesisInput { Prompt = "一只奔跑的猫" }, Parameters = new ImageSynthesisParameters { N = 4, @@ -1100,9 +1418,9 @@ public static readonly Style = "" } }, - new() + new ModelResponse { - Output = new() + Output = new ImageSynthesisOutput { TaskId = "9e2b6ef6-285d-4efa-8651-4dbda7d571fa", TaskStatus = DashScopeTaskStatus.Pending @@ -1117,19 +1435,19 @@ public static readonly RequestSnapshot, ModelResponse> CreateTaskNoSse = new( "image-generation", - new() + new ModelRequest { Model = "wanx-style-repaint-v1", - Input = new() + Input = new ImageGenerationInput { ImageUrl = "https://public-vigen-video.oss-cn-shanghai.aliyuncs.com/public/dashscope/test.png", StyleIndex = 3 } }, - new() + new ModelResponse { - Output = new() + Output = new ImageGenerationOutput { TaskId = "c4f94e00-5899-431b-9579-eb1ebe686379", TaskStatus = DashScopeTaskStatus.Pending, }, @@ -1143,9 +1461,9 @@ public static readonly RequestSnapshot, ModelResponse> CreateTaskNoSse = new( "background-generation", - new() + new ModelRequest { - Input = new() + Input = new BackgroundGenerationInput { BaseImageUrl = "http://inner-materials.oss-cn-beijing.aliyuncs.com/graphic_design/jianguo/lllcho.lc/test_data/demo_example/demo/hailuo_2236873898_2.png", @@ -1164,10 +1482,10 @@ public static readonly RefPromptWeight = 0.5f } }, - new() + new ModelResponse { RequestId = "a010df33-effc-9e32-aaa0-e55fffa40ef5", - Output = new() + Output = new BackgroundGenerationOutput { TaskId = "b2e98d78-c79b-431c-b2d7-c7bcd54465da", TaskStatus = DashScopeTaskStatus.Pending @@ -1193,8 +1511,20 @@ public static class File "list", false, [ - new("file-fe-qBKjZKfTx64R9oYmwyovNHBH", "file", 6, 1720582024, "test1.txt", "file-extract"), - new("file-fe-WTTG89tIUTd4ByqP3K48R3bn", "file", 6, 1720535665, "test1.txt", "file-extract") + new DashScopeFile( + "file-fe-qBKjZKfTx64R9oYmwyovNHBH", + "file", + 6, + 1720582024, + "test1.txt", + "file-extract"), + new DashScopeFile( + "file-fe-WTTG89tIUTd4ByqP3K48R3bn", + "file", + 6, + 1720535665, + "test1.txt", + "file-extract") ])); public static readonly RequestSnapshot DeleteFileNoSse = new(