From 9666b8a3c5e368296441296adeda021e34ca20e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 17 Mar 2025 13:25:46 +0800 Subject: [PATCH 01/35] feat: migrate to ms.extensions.ai 25161.3 --- .../Cnblogs.DashScope.Sample.csproj | 2 +- .../Cnblogs.DashScope.AI.csproj | 2 +- .../DashScopeChatClient.cs | 20 +++++++++---------- .../DashScopeTextEmbeddingGenerator.cs | 4 ---- .../ChatClientTests.cs | 4 ++-- 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj index a7ba2f0..88bfded 100644 --- a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj +++ b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj index fe758a6..63d65db 100644 --- a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj +++ b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs index f28456f..3e2561f 100644 --- a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs +++ b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs @@ -43,7 +43,7 @@ public DashScopeChatClient(IDashScopeClient dashScopeClient, string modelId) /// public async Task GetResponseAsync( - IList chatMessages, + IEnumerable chatMessages, ChatOptions? options = null, CancellationToken cancellationToken = default) { @@ -130,7 +130,7 @@ public async Task GetResponseAsync( /// public async IAsyncEnumerable GetStreamingResponseAsync( - IList chatMessages, + IEnumerable chatMessages, ChatOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default) { @@ -202,10 +202,10 @@ public async IAsyncEnumerable GetStreamingResponseAsync( yield return new ChatResponseUpdate() { ResponseId = completion.ResponseId, - Role = completion.Message.Role, + Role = completion.Messages[0].Role, AdditionalProperties = completion.AdditionalProperties, - Contents = completion.Message.Contents, - RawRepresentation = completion.Message.RawRepresentation, + Contents = completion.Messages[0].Contents, + RawRepresentation = completion.Messages[0].RawRepresentation, CreatedAt = completion.CreatedAt, FinishReason = completion.FinishReason, ModelId = completion.ModelId, @@ -392,11 +392,11 @@ private List ToMultimodalMessageContents(IList MultimodalMessageContent.TextContent(text.Text), - DataContent { Data.Length: > 0 } data when data.MediaTypeStartsWith("image") => + DataContent { Data.Length: > 0 } data when data.HasTopLevelMediaType("image") => MultimodalMessageContent.ImageContent( - data.Data.Value.Span, + data.Data.Span, data.MediaType ?? throw new InvalidOperationException("image media type should not be null")), - DataContent { Uri: { } uri } data when data.MediaTypeStartsWith("image") => + DataContent { Uri: { } uri } data when data.HasTopLevelMediaType("image") => MultimodalMessageContent.ImageContent(uri), _ => null }; @@ -422,7 +422,7 @@ private IEnumerable ToTextChatMessages( { yield return new TextChatMessage( from.Role.Value, - from.Text ?? string.Empty, + from.Text, from.AuthorName); } else if (from.Role == ChatRole.Tool) @@ -464,7 +464,7 @@ private IEnumerable ToTextChatMessages( // <400> InternalError.Algo.InvalidParameter: Empty tool_calls is not supported in message yield return new TextChatMessage( from.Role.Value, - from.Text ?? string.Empty, + from.Text, from.AuthorName, null, functionCall.Count > 0 ? functionCall : null); diff --git a/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs b/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs index fba5e02..06c28d7 100644 --- a/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs +++ b/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs @@ -29,7 +29,6 @@ public DashScopeTextEmbeddingGenerator(IDashScopeClient dashScopeClient, string _dashScopeClient = dashScopeClient; _modelId = modelId; _parameters = new TextEmbeddingParameters { Dimension = dimensions }; - Metadata = new EmbeddingGeneratorMetadata("dashscope", _dashScopeClient.BaseAddress, modelId, dimensions); } /// @@ -88,7 +87,4 @@ public void Dispose() options.AdditionalProperties?.GetValueOrDefault(nameof(TextEmbeddingParameters.TextType)) as string, }; } - - /// - public EmbeddingGeneratorMetadata Metadata { get; } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs index 89ac79c..c1f5096 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs @@ -46,7 +46,7 @@ public async Task ChatClient_TextCompletion_SuccessAsync() Arg.Is>( m => m.IsEquivalent(testCase.RequestModel)), Arg.Any()); - response.Message.Text.Should().Be(testCase.ResponseModel.Output.Choices?.First().Message.Content); + response.Messages[0].Text.Should().Be(testCase.ResponseModel.Output.Choices?.First().Message.Content); } [Fact] @@ -136,7 +136,7 @@ public async Task ChatClient_ImageRecognition_SuccessAsync() await dashScopeClient.Received().GetMultimodalGenerationAsync( Arg.Is>(m => m.IsEquivalent(testCase.RequestModel)), Arg.Any()); - response.Choices[0].Text.Should() + response.Messages[0].Text.Should() .BeEquivalentTo(testCase.ResponseModel.Output.Choices[0].Message.Content[0].Text); } From c298b14e45eefe8beca508e638bddaf416a7fcf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 17 Mar 2025 15:58:11 +0800 Subject: [PATCH 02/35] test: update test case with data uri --- test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs index b5e2483..fec5a40 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs @@ -781,7 +781,7 @@ public static class MultimodalGeneration MultimodalMessage.User( [ MultimodalMessageContent.ImageContent( - "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") ]) ] @@ -881,7 +881,7 @@ public static class MultimodalGeneration MultimodalMessage.User( [ MultimodalMessageContent.ImageContent( - "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") ]) ] From 1e23e967122bf80a92287328cfd748a44423186d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sat, 15 Mar 2025 23:39:23 +0800 Subject: [PATCH 03/35] feat: implement application call api --- .../ApplicationDocReference.cs | 20 ++++ .../ApplicationInput.cs | 48 +++++++++ .../ApplicationMessage.cs | 30 ++++++ .../ApplicationModelUsage.cs | 9 ++ .../ApplicationOutput.cs | 16 +++ .../ApplicationOutputThought.cs | 24 +++++ .../ApplicationParameters.cs | 37 +++++++ .../ApplicationRagOptions.cs | 39 ++++++++ .../ApplicationRequest.cs | 17 ++++ .../ApplicationResponse.cs | 16 +++ .../ApplicationUsage.cs | 7 ++ .../DashScopeClientCore.cs | 20 ++++ .../IDashScopeClient.cs | 24 +++++ .../Internals/ApiLinks.cs | 1 + .../ApplicationSerializationTests.cs | 26 +++++ .../Cnblogs.DashScope.Sdk.UnitTests.csproj | 4 +- ...le-generation-text-nosse.request.body.json | 15 +++ ...e-generation-text-nosse.request.header.txt | 9 ++ ...le-generation-text-nosse.response.body.txt | 1 + ...-generation-text-nosse.response.header.txt | 15 +++ .../Utils/Snapshots.cs | 99 +++++++++++++++++++ 21 files changed, 475 insertions(+), 2 deletions(-) create mode 100644 src/Cnblogs.DashScope.Core/ApplicationDocReference.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationInput.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationMessage.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationModelUsage.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationOutput.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationParameters.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationRequest.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationResponse.cs create mode 100644 src/Cnblogs.DashScope.Core/ApplicationUsage.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.header.txt diff --git a/src/Cnblogs.DashScope.Core/ApplicationDocReference.cs b/src/Cnblogs.DashScope.Core/ApplicationDocReference.cs new file mode 100644 index 0000000..83c48af --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationDocReference.cs @@ -0,0 +1,20 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// One reference for application output. +/// +/// The index id of the doc. +/// Text slice title. +/// Unique id of the doc been referenced. +/// Name of the doc been referenced. +/// Referenced content. +/// Image URLs beed referenced. +/// Page numbers of referenced content belongs to. +public record ApplicationDocReference( + string IndexId, + string Title, + string DocId, + string DocName, + string Text, + List? Images, + List? PageNumber); diff --git a/src/Cnblogs.DashScope.Core/ApplicationInput.cs b/src/Cnblogs.DashScope.Core/ApplicationInput.cs new file mode 100644 index 0000000..ffbd969 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationInput.cs @@ -0,0 +1,48 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Inputs for application call. +/// +public class ApplicationInput +{ + /// + /// The prompt for model to generate response upon. Optional when has been set. + /// + /// + /// Prompt will be appended to when both set. + /// + public string? Prompt { get; set; } = null; + + /// + /// The session id for conversation history. This will be ignored if has been set. + /// + public string? SessionId { get; set; } = null; + + /// + /// The conversation history. + /// + public IEnumerable? Messages { get; set; } = null; + + /// + /// The id of memory when enabled. + /// + public string? MemoryId { get; set; } = null; + + /// + /// List of image urls for inputs. + /// + public IEnumerable? ImageList { get; set; } +} + +/// +/// Inputs for application call. +/// +/// User defined custom content. +public class ApplicationInput : ApplicationInput + where TBizContent : class +{ + /// + /// User defined content. + /// + public TBizContent? Content { get; set; } = null; +} diff --git a/src/Cnblogs.DashScope.Core/ApplicationMessage.cs b/src/Cnblogs.DashScope.Core/ApplicationMessage.cs new file mode 100644 index 0000000..9edfdf5 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationMessage.cs @@ -0,0 +1,30 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// A single message for application call. +/// +/// The role of this message belongs to. +/// The content of the message. +public record ApplicationMessage(string Role, string Content) +{ + /// + /// Creates a user message. + /// + /// Content of the message. + /// + public static ApplicationMessage User(string content) => new("user", content); + + /// + /// Creates a system message. + /// + /// Content of the message. + /// + public static ApplicationMessage System(string content) => new("system", content); + + /// + /// Creates a assistant message. + /// + /// Content of the message. + /// + public static ApplicationMessage Assistant(string content) => new("assistant", content); +} diff --git a/src/Cnblogs.DashScope.Core/ApplicationModelUsage.cs b/src/Cnblogs.DashScope.Core/ApplicationModelUsage.cs new file mode 100644 index 0000000..e0e838e --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationModelUsage.cs @@ -0,0 +1,9 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Token usages for one model. +/// +/// The id of the model. +/// Total input tokens of this model. +/// Total output tokens from this model. +public record ApplicationModelUsage(string ModelId, int InputTokens, int OutputTokens); diff --git a/src/Cnblogs.DashScope.Core/ApplicationOutput.cs b/src/Cnblogs.DashScope.Core/ApplicationOutput.cs new file mode 100644 index 0000000..258bd60 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationOutput.cs @@ -0,0 +1,16 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// The output of application call. +/// +/// Output text from application. +/// Finish reason from application. +/// Unique id of current session. +/// Thoughts from application. +/// Doc references from application output. +public record ApplicationOutput( + string Text, + string FinishReason, + string SessionId, + List? Thoughts, + List? DocReferences); diff --git a/src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs b/src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs new file mode 100644 index 0000000..0fdb33b --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs @@ -0,0 +1,24 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// The model thought output. +/// +/// The thought content of the model. +/// Type of the action. e.g. agentRag, reasoning. +/// The name of the action. +/// The action been executed. +/// The streaming result of action input. +/// The input of the action. +/// Lookup or plugin output. +/// Reasoning output when using DeepSeek-R1. +/// Arguments of the action. +public record ApplicationOutputThought( + string? Thought, + string? ActionType, + string? ActionName, + string? Action, + string? ActionInputStream, + string? ActionInput, + string? Observation, + string? ReasoningContent, + string? Arguments); diff --git a/src/Cnblogs.DashScope.Core/ApplicationParameters.cs b/src/Cnblogs.DashScope.Core/ApplicationParameters.cs new file mode 100644 index 0000000..86303b0 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationParameters.cs @@ -0,0 +1,37 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Parameters for application call. +/// +public class ApplicationParameters : IIncrementalOutputParameter, ISeedParameter, IProbabilityParameter +{ + /// + public bool? IncrementalOutput { get; set; } + + /// + /// Output format for flow application. Can be full_thoughts or agent_format. Defaults to full_thoughts. + /// + public string? FlowStreamMode { get; set; } + + /// + /// Options for RAG applications. + /// + public ApplicationRagOptions? RagOptions { get; set; } + + /// + public ulong? Seed { get; set; } + + /// + public float? TopP { get; set; } + + /// + public int? TopK { get; set; } + + /// + public float? Temperature { get; set; } + + /// + /// Controls whether output contains think block. + /// + public bool? HasThoughts { get; set; } +} diff --git a/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs new file mode 100644 index 0000000..abf0d5b --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs @@ -0,0 +1,39 @@ +using System.Text.Json; + +namespace Cnblogs.DashScope.Core; + +/// +/// Options for RAG application. +/// +public class ApplicationRagOptions +{ + /// + /// The pipelines to search from. + /// + public IEnumerable? PipelineIds { get; set; } + + /// + /// The ids of file to reference from. + /// + public IEnumerable? FileIds { get; set; } + + /// + /// Metadata filter for non-structured files. + /// + public JsonElement? MetadataFilter { get; set; } + + /// + /// Tag filter for non-structured files. + /// + public IEnumerable? Tags { get; set; } + + /// + /// Filter for structured files. + /// + public JsonElement? StructuredFilter { get; set; } + + /// + /// File ids for current session. + /// + public IEnumerable? SessionFileIds { get; set; } +} diff --git a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs new file mode 100644 index 0000000..6533a30 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs @@ -0,0 +1,17 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Request body for an application all. +/// +public class ApplicationRequest +{ + /// + /// Content of this call. + /// + public required ApplicationInput Input { get; init; } + + /// + /// Optional configurations. + /// + public required ApplicationParameters? Parameters { get; init; } +} diff --git a/src/Cnblogs.DashScope.Core/ApplicationResponse.cs b/src/Cnblogs.DashScope.Core/ApplicationResponse.cs new file mode 100644 index 0000000..7b054bc --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationResponse.cs @@ -0,0 +1,16 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Response of application call. +/// +/// Unique id of this request. +/// Error code. Null when request is successful. +/// Error message. Null when request is successful. +/// The output of application call. +/// Token usage of this application call. +public record ApplicationResponse( + string RequestId, + string? Code, + string? Message, + ApplicationOutput Output, + ApplicationUsage Usage); diff --git a/src/Cnblogs.DashScope.Core/ApplicationUsage.cs b/src/Cnblogs.DashScope.Core/ApplicationUsage.cs new file mode 100644 index 0000000..02aa0c1 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/ApplicationUsage.cs @@ -0,0 +1,7 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Total token usages of this application call. +/// +/// All models been used and their token usages. +public record ApplicationUsage(List Models); diff --git a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs index 9784516..43eebf4 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs @@ -35,6 +35,26 @@ public DashScopeClientCore(HttpClient httpClient) /// public Uri? BaseAddress => _httpClient.BaseAddress; + /// + public async Task GetApplicationResponseAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default) + { + var request = BuildRequest(HttpMethod.Post, ApiLinks.Application(applicationId), input); + return (await SendAsync(request, cancellationToken))!; + } + + /// + public IAsyncEnumerable GetApplicationResponseStreamAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default) + { + var request = BuildSseRequest(HttpMethod.Post, ApiLinks.Application(applicationId), input); + return StreamAsync(request, cancellationToken); + } + /// public async Task> GetTextCompletionAsync( ModelRequest input, diff --git a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs index 3c32291..203e646 100644 --- a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs +++ b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs @@ -10,6 +10,30 @@ public interface IDashScopeClient /// Uri? BaseAddress { get; } + /// + /// Make a call to custom application. + /// + /// Name of the application. + /// The request body. + /// The cancellation token to use. + /// + Task GetApplicationResponseAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default); + + /// + /// Make a call to custom application. + /// + /// Name of the application. + /// The request body. + /// The cancellation token to use. + /// + IAsyncEnumerable GetApplicationResponseStreamAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default); + /// /// Return textual completions as configured for a given prompt. /// diff --git a/src/Cnblogs.DashScope.Core/Internals/ApiLinks.cs b/src/Cnblogs.DashScope.Core/Internals/ApiLinks.cs index 22cc689..d098719 100644 --- a/src/Cnblogs.DashScope.Core/Internals/ApiLinks.cs +++ b/src/Cnblogs.DashScope.Core/Internals/ApiLinks.cs @@ -11,4 +11,5 @@ internal static class ApiLinks public const string Tasks = "tasks/"; public const string Tokenizer = "tokenizer"; public const string Files = "/compatible-mode/v1/files"; + public static string Application(string applicationId) => $"apps/{applicationId}/completion"; } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs new file mode 100644 index 0000000..1e83f0d --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs @@ -0,0 +1,26 @@ +using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using FluentAssertions; +using NSubstitute; + +namespace Cnblogs.DashScope.Sdk.UnitTests; + +public class ApplicationSerializationTests +{ + [Fact] + public async Task SingleCompletion_TextNoSse_SuccessAsync() + { + // Arrange + const bool sse = false; + var testCase = Snapshots.Application.SinglePrompt; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var response = await client.GetApplicationResponseAsync("anyId", testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + response.Should().BeEquivalentTo(testCase.ResponseModel); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj index 0c74f01..3f82c79 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj @@ -10,8 +10,8 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.body.json new file mode 100644 index 0000000..fc5092e --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.body.json @@ -0,0 +1,15 @@ +{ + "input": { + "prompt": "总结xUnit Test Patterns中的内容" + }, + "parameters": { + "top_k": 100, + "top_p": 0.8, + "seed": 1234, + "temperature": 0.85, + "rag_options": { + "pipeline_ids": ["thie5bysoj"], + "file_ids": ["file_d129d632800c45aa9e7421b30561f447_10207234"] + } + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.header.txt new file mode 100644 index 0000000..ef611ed --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.header.txt @@ -0,0 +1,9 @@ +POST /api/v1/apps/5ccc140108fd4b2ea5e6101fbada7583/completion HTTP/1.1 +Content-Type: application/json +Accept: */* +Cache-Control: no-cache +Postman-Token: 64f6ef44-2032-4b11-a8cb-f88353690719 +Host: dashscope.aliyuncs.com +Accept-Encoding: gzip, deflate, br +Connection: keep-alive +Content-Length: 446 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.body.txt new file mode 100644 index 0000000..1d4bb11 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"thoughts":[{"action_input_stream":"{}","action_type":"agentRag","observation":"[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]","action_name":"知识检索","action":"rag","arguments":"{}"},{"action_input_stream":"{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}","action_type":"api","observation":"[]","action_name":"长期记忆检索","action":"memory","arguments":"{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}"}],"finish_reason":"stop","session_id":"b7250cba47db463ca851dfb4088e71d8","text":"xUnit Test Patterns 提供了一套全面的指南,用于改进测试自动化和重构测试代码。以下是根据提供的文档内容总结的关键点:\n\n1. 测试自动化的目标包括帮助提高产品质量、帮助我们理解被测系统(SUT)、减少(并且不引入)风险、易于运行、编写和维护[4]。\n2. 在管理共享fixture方面,文档讨论了访问共享fixture以及触发共享fixture构造的方法[2]。\n3. 关于结果验证,文档提供了自我检查测试的方法,验证状态或行为,使用内置断言进行状态验证,以及验证直接输出和替代路径[2]。\n4. 当涉及到数据库时,文档提到了与数据库相关的测试问题、没有数据库的测试、数据库测试、存储过程测试、数据访问层测试,并强调确保开发者独立性[3]。\n5. 文档还涵盖了测试方法组织策略、测试命名约定、测试套件组织、运行测试组或单个测试、测试代码重用、测试文件组织等内容[5]。\n\n这些模式和实践旨在解决测试中的常见问题,如高测试维护成本、不可测试代码最小化、防止生产代码中的错误测试等[1]。通过应用这些模式,开发者可以创建更高效、更易于维护的自动化测试。","doc_references":[{"images":["http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648","http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302"],"doc_name":"xUnit Test Patterns","text":"【文档名】:xUnit Test Patterns\n【标题】:Visual Summary of the Pattern Language\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\n","index_id":"1","title":"Visual Summary of the Pattern Language","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"doc_name":"xUnit Test Patterns","text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"doc_name":"xUnit Test Patterns","text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"doc_name":"xUnit Test Patterns","text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"doc_name":"xUnit Test Patterns","text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n","index_id":"5","title":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"output_tokens":290,"model_id":"qwen-plus","input_tokens":2591}]},"request_id":"c127bd40-180c-9cfa-b991-f875edd8c310"} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.header.txt new file mode 100644 index 0000000..66978ab --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding +content-type: application/json +x-request-id: c127bd40-180c-9cfa-b991-f875edd8c310 +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 14424 +req-arrive-time: 1742051106547 +resp-start-time: 1742051120971 +x-envoy-upstream-service-time: 14414 +content-encoding: gzip +date: Sat, 15 Mar 2025 15:05:20 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs index fec5a40..5c87619 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs @@ -105,6 +105,105 @@ public static readonly }); } + public static class Application + { + public static readonly RequestSnapshot SinglePrompt = + new( + "application-single-generation-text", + new ApplicationRequest() + { + Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["thie5bysoj"], + FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] + } + } + }, + new ApplicationResponse( + "c127bd40-180c-9cfa-b991-f875edd8c310", + null, + null, + new ApplicationOutput( + "xUnit Test Patterns 提供了一套全面的指南,用于改进测试自动化和重构测试代码。以下是根据提供的文档内容总结的关键点:\n\n1. 测试自动化的目标包括帮助提高产品质量、帮助我们理解被测系统(SUT)、减少(并且不引入)风险、易于运行、编写和维护[4]。\n2. 在管理共享fixture方面,文档讨论了访问共享fixture以及触发共享fixture构造的方法[2]。\n3. 关于结果验证,文档提供了自我检查测试的方法,验证状态或行为,使用内置断言进行状态验证,以及验证直接输出和替代路径[2]。\n4. 当涉及到数据库时,文档提到了与数据库相关的测试问题、没有数据库的测试、数据库测试、存储过程测试、数据访问层测试,并强调确保开发者独立性[3]。\n5. 文档还涵盖了测试方法组织策略、测试命名约定、测试套件组织、运行测试组或单个测试、测试代码重用、测试文件组织等内容[5]。\n\n这些模式和实践旨在解决测试中的常见问题,如高测试维护成本、不可测试代码最小化、防止生产代码中的错误测试等[1]。通过应用这些模式,开发者可以创建更高效、更易于维护的自动化测试。", + "stop", + "b7250cba47db463ca851dfb4088e71d8", + [ + new ApplicationOutputThought( + null, + "agentRag", + "知识检索", + "rag", + "{}", + null, + "[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]", + null, + "{}"), + new ApplicationOutputThought( + null, + "api", + "长期记忆检索", + "memory", + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}", + null, + "[]", + null, + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}") + ], + [ + new ApplicationDocReference( + "1", + "Visual Summary of the Pattern Language", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:Visual Summary of the Pattern Language\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\n", + [ + "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648", + "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302" + ], + null), + new ApplicationDocReference( + "2", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", + [], + null), + new ApplicationDocReference( + "3", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", + [], + null), + new ApplicationDocReference( + "4", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", + [], + null), + new ApplicationDocReference( + "5", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n", + [], + null) + ]), + new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 2591, 290)]))); + } + public static class TextGeneration { public static class TextFormat From 0ff8223b9775610280406f0bd1241ac4cc62b588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 16:59:54 +0800 Subject: [PATCH 04/35] feat: add single prompt sse tests --- .../ApplicationOutputThought.cs | 4 +- .../ApplicationResponse.cs | 4 - .../ApplicationSerializationTests.cs | 43 +- ...ngle-generation-text-sse.request.body.json | 16 + ...gle-generation-text-sse.request.header.txt | 8 + ...ngle-generation-text-sse.response.body.txt | 325 +++ ...le-generation-text-sse.response.header.txt | 14 + ...-text-with-thought-nosse.request.body.json | 16 + ...text-with-thought-nosse.request.header.txt | 8 + ...-text-with-thought-nosse.response.body.txt | 1 + ...ext-with-thought-nosse.response.header.txt | 15 + .../Utils/Snapshots.Application.cs | 217 ++ .../Utils/Snapshots.Error.cs | 105 + .../Utils/Snapshots.MultimodalGeneration.cs | 517 +++++ .../Utils/Snapshots.Tasks.cs | 379 ++++ .../Utils/Snapshots.TextEmbedding.cs | 65 + .../Utils/Snapshots.TextGeneration.cs | 614 ++++++ .../Utils/Snapshots.cs | 1751 +---------------- 18 files changed, 2345 insertions(+), 1757 deletions(-) create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Error.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Tasks.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextEmbedding.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs diff --git a/src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs b/src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs index 0fdb33b..b4bf55f 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationOutputThought.cs @@ -10,7 +10,7 @@ /// The streaming result of action input. /// The input of the action. /// Lookup or plugin output. -/// Reasoning output when using DeepSeek-R1. +/// Reasoning output when using DeepSeek-R1. /// Arguments of the action. public record ApplicationOutputThought( string? Thought, @@ -20,5 +20,5 @@ public record ApplicationOutputThought( string? ActionInputStream, string? ActionInput, string? Observation, - string? ReasoningContent, + string? Response, string? Arguments); diff --git a/src/Cnblogs.DashScope.Core/ApplicationResponse.cs b/src/Cnblogs.DashScope.Core/ApplicationResponse.cs index 7b054bc..2089940 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationResponse.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationResponse.cs @@ -4,13 +4,9 @@ /// Response of application call. /// /// Unique id of this request. -/// Error code. Null when request is successful. -/// Error message. Null when request is successful. /// The output of application call. /// Token usage of this application call. public record ApplicationResponse( string RequestId, - string? Code, - string? Message, ApplicationOutput Output, ApplicationUsage Usage); diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs index 1e83f0d..9b06b37 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs @@ -11,7 +11,7 @@ public async Task SingleCompletion_TextNoSse_SuccessAsync() { // Arrange const bool sse = false; - var testCase = Snapshots.Application.SinglePrompt; + var testCase = Snapshots.Application.SinglePromptNoSse; var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); // Act @@ -23,4 +23,45 @@ public async Task SingleCompletion_TextNoSse_SuccessAsync() Arg.Any()); response.Should().BeEquivalentTo(testCase.ResponseModel); } + + [Fact] + public async Task SingleCompletion_ThoughtNoSse_SuccessAsync() + { + // Arrange + const bool sse = false; + var testCase = Snapshots.Application.SinglePromptWithThoughtsNoSse; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var response = await client.GetApplicationResponseAsync("anyId", testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + response.Should().BeEquivalentTo(testCase.ResponseModel); + } + + [Fact] + public async Task SingleCompletion_TextSse_SuccessAsync() + { + // Arrange + const bool sse = true; + var testCase = Snapshots.Application.SinglePromptSse; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var outputs = await client.GetApplicationResponseStreamAsync("anyId", testCase.RequestModel).ToListAsync(); + var text = string.Join(string.Empty, outputs.Select(o => o.Output.Text)); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + outputs.SkipLast(1).Should().AllSatisfy(x => x.Output.FinishReason.Should().Be("null")); + outputs.Last().Should().BeEquivalentTo( + testCase.ResponseModel, + o => o.Excluding(y => y.Output.Text).Excluding(x => x.Output.Thoughts)); + text.Should().Be(testCase.ResponseModel.Output.Text); + } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.body.json new file mode 100644 index 0000000..b3d4bec --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.body.json @@ -0,0 +1,16 @@ +{ + "input": { + "prompt": "总结xUnit Test Patterns中的内容" + }, + "parameters": { + "incremental_output": true, + "top_k": 100, + "top_p": 0.8, + "seed": 1234, + "temperature": 0.85, + "rag_options": { + "pipeline_ids": ["thie5bysoj"], + "tags": ["xUnit"] + } + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.header.txt new file mode 100644 index 0000000..85f63a1 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/apps/010aa085cc9943268731861c9511bb0c/completion 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: 364 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.body.txt new file mode 100644 index 0000000..012292e --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.body.txt @@ -0,0 +1,325 @@ +id:1 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"x"},"usage":{"models":[{"input_tokens":2304,"output_tokens":1,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:2 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"Unit"},"usage":{"models":[{"input_tokens":2304,"output_tokens":2,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:3 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":" Test"},"usage":{"models":[{"input_tokens":2304,"output_tokens":3,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:4 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":" Patterns这本书讨论了"},"usage":{"models":[{"input_tokens":2304,"output_tokens":7,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:5 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"测试自动化的目标,"},"usage":{"models":[{"input_tokens":2304,"output_tokens":11,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:6 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"指出测试应该帮助"},"usage":{"models":[{"input_tokens":2304,"output_tokens":15,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:7 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"我们提高质量"},"usage":{"models":[{"input_tokens":2304,"output_tokens":18,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:8 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"[4],理解","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":27,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:10 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"被测系统(S","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":31,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:11 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"UT),减少(","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":35,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:12 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"而不是引入)风险","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":39,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:13 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":",并且应该易于","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":43,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:14 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"运行、编写和","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":47,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:15 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"维护。书中还","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":51,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:16 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"提到了一些关于","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":55,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:17 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"测试哲学的内容,","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":59,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:18 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"强调了为什么哲学","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":63,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:19 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"对于测试来说是","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":67,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:20 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"重要的。\n\n此外,","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":71,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:21 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"该书涵盖了如何","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":75,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:22 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"管理共享的测试","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":79,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:23 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"装置以及访问这些","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":83,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:24 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"装置的方法[2],并说明","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":95,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:27 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"了触发共享装置","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":99,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:28 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"构建的过程。在","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":103,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:29 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"结果验证方面,","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":107,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:30 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"书中区分了状态","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":111,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:31 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"验证与行为验证","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":115,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:32 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":",并介绍了使用内置","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":119,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:33 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"断言、增量","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":123,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:34 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"断言等技术","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":127,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:35 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"来减少测试代码","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":131,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:36 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"重复性的策略。\n\n","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":135,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:37 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"书中也探讨了","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":139,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:38 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"数据库相关的测试议题","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":143,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:39 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":",包括没有数据库","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":147,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:40 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"的情况下进行测试的方法","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":151,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:41 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":",测试存储过程","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":155,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:42 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":",数据访问层","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":159,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:43 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"的测试,以及","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":163,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:44 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"确保开发者独立性","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":167,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:45 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"的同时进行数据库测试","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":171,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:46 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"的重要性[","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":175,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:47 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"3]","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":179,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:48 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"。\n\n最后,在组织","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":183,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:49 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"测试用例类","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":187,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:50 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"方面,书中提出了","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":191,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:51 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"按类、特性","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":195,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:52 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"或装置创建测试","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":199,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:53 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"用例类的不同","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":203,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:54 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"策略,并讨论了","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":207,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:55 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"选择测试方法组织","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":211,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:56 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"策略、命名约定","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":215,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:57 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"、组织测试套","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":219,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:58 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"件、运行测试","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":223,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:59 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"组或单一测试","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":227,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:60 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"的方式,以及测试","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":231,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:61 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"代码重用的位置","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":235,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:62 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"等问题[","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":239,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:63 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"5]","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n","index_id":"5","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":243,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:64 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"null","text":"。","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n","index_id":"5","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":244,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + +id:65 +event:result +:HTTP_STATUS/200 +data:{"output":{"session_id":"069db8223d514dab91185954dc5108de","finish_reason":"stop","text":"","doc_references":[{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n","index_id":"2","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n","index_id":"3","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n","index_id":"4","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"},{"images":[],"text":"【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n","index_id":"5","title":"xUnit Test Patterns","doc_name":"xUnit Test Patterns","doc_id":"file_d129d632800c45aa9e7421b30561f447_10207234"}]},"usage":{"models":[{"input_tokens":2304,"output_tokens":244,"model_id":"qwen-max-latest"}]},"request_id":"44862941-b743-9332-b49f-5f3db75a4873"} + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.header.txt new file mode 100644 index 0000000..4741d69 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.header.txt @@ -0,0 +1,14 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers +x-request-id: fec856c6-c146-99bc-940c-fd6c36939a16 +content-type: text/event-stream;charset=UTF-8 +x-dashscope-call-gateway: true +x-dashscope-timeout: 180 +x-dashscope-finished: false +req-cost-time: 1755 +req-arrive-time: 1742113457368 +resp-start-time: 1742113459124 +x-envoy-upstream-service-time: 1744 +date: Sun, 16 Mar 2025 08:24:18 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json new file mode 100644 index 0000000..dad1501 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json @@ -0,0 +1,16 @@ +{ + "input": { + "prompt": "总结xUnit Test Patterns中的内容" + }, + "parameters": { + "has_thoughts": true, + "top_k": 100, + "top_p": 0.8, + "seed": 1234, + "temperature": 0.85, + "rag_options": { + "pipeline_ids": ["thie5bysoj"], + "file_ids": ["file_d129d632800c45aa9e7421b30561f447_10207234"] + } + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt new file mode 100644 index 0000000..01c9f0f --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/apps/010aa085cc9943268731861c9511bb0c/completion 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: 403 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt new file mode 100644 index 0000000..1dab922 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"thoughts":[{"action_input_stream":"{}","action_type":"agentRag","observation":"[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742716762&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=4CddPVeeyxgrXe5axUspV6zXnS8%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742716762&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=hRkFcnwAiV7LSHw69WvJJ6fXEV0%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]","action_name":"知识检索","action":"rag","arguments":"{}"},{"thought":"好的,我现在需要总结用户提供的xUnit Test Patterns中的内容。首先,用户给了几个文档片段,每个片段都来自同一本书的不同部分。我需要仔细分析这些片段,看看里面提到的关键点和主题。\n\n第一个文档提到了“Visual Summary of the Pattern Language”,里面有几个关键点,比如Minimize Untestable Code,Buggy Tests,Production Bugs,还有测试维护成本高的问题。可能这本书在讲如何设计和管理单元测试的模式,避免常见的问题,比如不可测试的代码和测试逻辑混入生产环境。\n\n第二个文档片段讲的是“Managing Shared Fixtures”和结果验证(Result Verification)。这里提到共享夹具的管理、触发构建,以及如何验证测试结果,包括状态验证和行为验证,还有减少测试代码重复的方法,比如使用Expected Objects和Custom Assertions。这说明书中详细讨论了测试夹具的设计和如何有效验证测试结果,避免重复代码。\n\n第三个文档涉及数据库测试的问题,比如如何测试数据访问层、存储过程,以及确保开发者独立性的策略。这部分可能讨论在测试中使用数据库的挑战和解决方案,例如是否使用数据库进行测试,或者如何隔离测试以避免依赖。\n\n第四个文档提到了测试自动化的目标和哲学,包括测试的经济性、提高质量、理解系统、降低风险、易于运行和维护等。这说明书中不仅提供技术模式,还强调测试策略和哲学的重要性,指导如何有效实施自动化测试。\n\n第五个文档讨论了测试用例的组织策略,比如按类、功能或夹具组织测试用例类,命名约定,测试套件的管理,以及测试代码的重用方法。这部分可能涉及如何结构化测试代码,提高可维护性和可读性。\n\n综合这些片段,xUnit Test Patterns似乎是一本关于单元测试设计和最佳实践的指南,涵盖测试模式、夹具管理、结果验证、数据库测试、测试自动化策略和测试代码组织。重点在于如何编写可维护、可靠且高效的测试,避免常见陷阱,如不可测试的代码、测试逻辑污染生产代码、高维护成本等。书中可能还讨论了如何在不同情境下选择适当的测试策略,例如是否使用共享夹具,如何处理数据库依赖,以及如何组织测试代码结构以提高复用性。\n\n现在需要将这些分析整理成一个简明扼要的总结,突出主要主题和关键点,确保涵盖各个文档片段提到的内容,并指出这本书的整体目的和结构。可能需要分点说明,让用户清晰了解书中的核心内容。","action_type":"reasoning","response":"好的,我现在需要总结用户提供的xUnit Test Patterns中的内容。首先,用户给了几个文档片段,每个片段都来自同一本书的不同部分。我需要仔细分析这些片段,看看里面提到的关键点和主题。\n\n第一个文档提到了“Visual Summary of the Pattern Language”,里面有几个关键点,比如Minimize Untestable Code,Buggy Tests,Production Bugs,还有测试维护成本高的问题。可能这本书在讲如何设计和管理单元测试的模式,避免常见的问题,比如不可测试的代码和测试逻辑混入生产环境。\n\n第二个文档片段讲的是“Managing Shared Fixtures”和结果验证(Result Verification)。这里提到共享夹具的管理、触发构建,以及如何验证测试结果,包括状态验证和行为验证,还有减少测试代码重复的方法,比如使用Expected Objects和Custom Assertions。这说明书中详细讨论了测试夹具的设计和如何有效验证测试结果,避免重复代码。\n\n第三个文档涉及数据库测试的问题,比如如何测试数据访问层、存储过程,以及确保开发者独立性的策略。这部分可能讨论在测试中使用数据库的挑战和解决方案,例如是否使用数据库进行测试,或者如何隔离测试以避免依赖。\n\n第四个文档提到了测试自动化的目标和哲学,包括测试的经济性、提高质量、理解系统、降低风险、易于运行和维护等。这说明书中不仅提供技术模式,还强调测试策略和哲学的重要性,指导如何有效实施自动化测试。\n\n第五个文档讨论了测试用例的组织策略,比如按类、功能或夹具组织测试用例类,命名约定,测试套件的管理,以及测试代码的重用方法。这部分可能涉及如何结构化测试代码,提高可维护性和可读性。\n\n综合这些片段,xUnit Test Patterns似乎是一本关于单元测试设计和最佳实践的指南,涵盖测试模式、夹具管理、结果验证、数据库测试、测试自动化策略和测试代码组织。重点在于如何编写可维护、可靠且高效的测试,避免常见陷阱,如不可测试的代码、测试逻辑污染生产代码、高维护成本等。书中可能还讨论了如何在不同情境下选择适当的测试策略,例如是否使用共享夹具,如何处理数据库依赖,以及如何组织测试代码结构以提高复用性。\n\n现在需要将这些分析整理成一个简明扼要的总结,突出主要主题和关键点,确保涵盖各个文档片段提到的内容,并指出这本书的整体目的和结构。可能需要分点说明,让用户清晰了解书中的核心内容。","action_name":"思考过程","action":"reasoning"}],"finish_reason":"stop","session_id":"9d81b84e95f844c29ee825ad8bb647bb","text":"《xUnit Test Patterns》是一本系统介绍单元测试模式与最佳实践的指南,主要帮助开发者设计可维护、高效且可靠的自动化测试。以下是其核心内容的总结:\n\n---\n\n### **核心主题与内容**\n1. **测试模式与反模式**\n - **关键模式**:如共享夹具管理(Shared Fixtures)、自定义断言(Custom Assertions)、预期对象(Expected Objects)等,用于解决测试代码重复、依赖管理等问题。\n - **反模式与问题**:如不可测试代码(Untestable Code)、测试逻辑混入生产代码(Test Logic in Production)、高维护成本(High Test Maintenance Cost)等,分析其成因与规避策略。\n\n2. **测试夹具管理**\n - **共享夹具**:如何构造、触发和访问共享测试环境(如数据库连接),避免测试间的副作用。\n - **数据库测试**:讨论是否依赖数据库进行测试、如何测试数据访问层、存储过程,以及确保开发者独立性的策略(如使用测试替身)。\n\n3. **测试验证策略**\n - **状态验证**:通过断言检查系统状态(如使用内置断言、Delta断言)。\n - **行为验证**:验证系统是否按预期调用方法(如模拟对象、过程式验证)。\n - **减少代码重复**:通过自定义断言、预期对象和验证方法统一结果检查逻辑。\n\n4. **测试自动化哲学与目标**\n - **目标**:提升代码质量、降低风险、易于编写和维护测试。\n - **经济性**:平衡测试投入与收益,优先覆盖关键路径(Happy Path)和替代路径(Alternative Paths)。\n\n5. **测试代码组织**\n - **结构化策略**:按类(Testcase Class per Class)、功能(Testcase Class per Feature)或夹具(Testcase Class per Fixture)组织测试用例。\n - **命名与套件管理**:使用清晰命名约定、分组测试套件(Test Suites)和依赖管理。\n\n6. **测试维护与演进**\n - **最小化维护成本**:通过模式(如测试工具方法、继承复用)适应系统变化。\n - **自检测试(Built-in Self-Test)**:确保测试本身的可信性。\n\n---\n\n### **书籍结构特点**\n- **问题驱动**:每章围绕具体问题(如“如何处理共享夹具?”)展开,提供模式、替代方案和权衡。\n- **视觉化总结**:通过图表展示模式间的关系,帮助读者理解复杂概念。\n- **实践导向**:结合代码示例与真实场景,指导如何应用模式解决测试中的常见痛点。\n\n---\n\n### **适用场景**\n- 开发中遇到测试代码重复、脆弱测试(Fragile Tests)或高维护成本时。\n- 需要设计复杂测试场景(如数据库交互、异步行为)时。\n- 团队希望建立统一的测试实践与规范时。\n\n通过遵循书中模式,开发者能构建更健壮、可维护的测试体系,最终提升软件质量和开发效率。"},"usage":{"models":[{"output_tokens":1126,"model_id":"deepseek-r1","input_tokens":1129}]},"request_id":"b5819020-e5aa-9481-8c9d-e11797f191d8"} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt new file mode 100644 index 0000000..24f9fde --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding +content-type: application/json +x-request-id: b5819020-e5aa-9481-8c9d-e11797f191d8 +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 43838 +req-arrive-time: 1742111961733 +resp-start-time: 1742112005571 +x-envoy-upstream-service-time: 43826 +content-encoding: gzip +date: Sun, 16 Mar 2025 08:00:05 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs new file mode 100644 index 0000000..f26b007 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs @@ -0,0 +1,217 @@ +using Cnblogs.DashScope.Core; + +namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; + +public static partial class Snapshots +{ + public static class Application + { + public static readonly RequestSnapshot SinglePromptNoSse = + new( + "application-single-generation-text", + new ApplicationRequest() + { + Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["thie5bysoj"], + FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] + } + } + }, + new ApplicationResponse( + "c127bd40-180c-9cfa-b991-f875edd8c310", + new ApplicationOutput( + "xUnit Test Patterns 提供了一套全面的指南,用于改进测试自动化和重构测试代码。以下是根据提供的文档内容总结的关键点:\n\n1. 测试自动化的目标包括帮助提高产品质量、帮助我们理解被测系统(SUT)、减少(并且不引入)风险、易于运行、编写和维护[4]。\n2. 在管理共享fixture方面,文档讨论了访问共享fixture以及触发共享fixture构造的方法[2]。\n3. 关于结果验证,文档提供了自我检查测试的方法,验证状态或行为,使用内置断言进行状态验证,以及验证直接输出和替代路径[2]。\n4. 当涉及到数据库时,文档提到了与数据库相关的测试问题、没有数据库的测试、数据库测试、存储过程测试、数据访问层测试,并强调确保开发者独立性[3]。\n5. 文档还涵盖了测试方法组织策略、测试命名约定、测试套件组织、运行测试组或单个测试、测试代码重用、测试文件组织等内容[5]。\n\n这些模式和实践旨在解决测试中的常见问题,如高测试维护成本、不可测试代码最小化、防止生产代码中的错误测试等[1]。通过应用这些模式,开发者可以创建更高效、更易于维护的自动化测试。", + "stop", + "b7250cba47db463ca851dfb4088e71d8", + [ + new ApplicationOutputThought( + null, + "agentRag", + "知识检索", + "rag", + "{}", + null, + "[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]", + null, + "{}"), + new ApplicationOutputThought( + null, + "api", + "长期记忆检索", + "memory", + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}", + null, + "[]", + null, + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}") + ], + [ + new ApplicationDocReference( + "1", + "Visual Summary of the Pattern Language", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:Visual Summary of the Pattern Language\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\n", + [ + "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648", + "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302" + ], + null), + new ApplicationDocReference( + "2", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", + [], + null), + new ApplicationDocReference( + "3", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", + [], + null), + new ApplicationDocReference( + "4", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", + [], + null), + new ApplicationDocReference( + "5", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n", + [], + null) + ]), + new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 2591, 290)]))); + + public static readonly RequestSnapshot SinglePromptSse = + new( + "application-single-generation-text", + new ApplicationRequest() + { + Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + IncrementalOutput = true, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["thie5bysoj"], + Tags = ["xUnit"] + } + } + }, + new ApplicationResponse( + "44862941-b743-9332-b49f-5f3db75a4873", + new ApplicationOutput( + "xUnit Test Patterns这本书讨论了测试自动化的目标,指出测试应该帮助我们提高质量[4],理解被测系统(SUT),减少(而不是引入)风险,并且应该易于运行、编写和维护。书中还提到了一些关于测试哲学的内容,强调了为什么哲学对于测试来说是重要的。\n\n此外,该书涵盖了如何管理共享的测试装置以及访问这些装置的方法[2],并说明了触发共享装置构建的过程。在结果验证方面,书中区分了状态验证与行为验证,并介绍了使用内置断言、增量断言等技术来减少测试代码重复性的策略。\n\n书中也探讨了数据库相关的测试议题,包括没有数据库的情况下进行测试的方法,测试存储过程,数据访问层的测试,以及确保开发者独立性的同时进行数据库测试的重要性[3]。\n\n最后,在组织测试用例类方面,书中提出了按类、特性或装置创建测试用例类的不同策略,并讨论了选择测试方法组织策略、命名约定、组织测试套件、运行测试组或单一测试的方式,以及测试代码重用的位置等问题[5]。", + "stop", + "069db8223d514dab91185954dc5108de", + null, + [ + new ApplicationDocReference( + "2", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", + [], + null), + new ApplicationDocReference( + "3", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", + [], + null), + new ApplicationDocReference( + "4", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", + [], + null), + new ApplicationDocReference( + "5", + "xUnit Test Patterns", + "file_d129d632800c45aa9e7421b30561f447_10207234", + "xUnit Test Patterns", + "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n", + [], + null), + ]), + new ApplicationUsage([new ApplicationModelUsage("qwen-max-latest", 2304, 244)]))); + + public static readonly RequestSnapshot SinglePromptWithThoughtsNoSse = + new( + "application-single-generation-text-with-thought", + new ApplicationRequest() + { + Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["thie5bysoj"], + FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] + }, + HasThoughts = true + } + }, + new ApplicationResponse( + "b5819020-e5aa-9481-8c9d-e11797f191d8", + new ApplicationOutput( + "《xUnit Test Patterns》是一本系统介绍单元测试模式与最佳实践的指南,主要帮助开发者设计可维护、高效且可靠的自动化测试。以下是其核心内容的总结:\n\n---\n\n### **核心主题与内容**\n1. **测试模式与反模式**\n - **关键模式**:如共享夹具管理(Shared Fixtures)、自定义断言(Custom Assertions)、预期对象(Expected Objects)等,用于解决测试代码重复、依赖管理等问题。\n - **反模式与问题**:如不可测试代码(Untestable Code)、测试逻辑混入生产代码(Test Logic in Production)、高维护成本(High Test Maintenance Cost)等,分析其成因与规避策略。\n\n2. **测试夹具管理**\n - **共享夹具**:如何构造、触发和访问共享测试环境(如数据库连接),避免测试间的副作用。\n - **数据库测试**:讨论是否依赖数据库进行测试、如何测试数据访问层、存储过程,以及确保开发者独立性的策略(如使用测试替身)。\n\n3. **测试验证策略**\n - **状态验证**:通过断言检查系统状态(如使用内置断言、Delta断言)。\n - **行为验证**:验证系统是否按预期调用方法(如模拟对象、过程式验证)。\n - **减少代码重复**:通过自定义断言、预期对象和验证方法统一结果检查逻辑。\n\n4. **测试自动化哲学与目标**\n - **目标**:提升代码质量、降低风险、易于编写和维护测试。\n - **经济性**:平衡测试投入与收益,优先覆盖关键路径(Happy Path)和替代路径(Alternative Paths)。\n\n5. **测试代码组织**\n - **结构化策略**:按类(Testcase Class per Class)、功能(Testcase Class per Feature)或夹具(Testcase Class per Fixture)组织测试用例。\n - **命名与套件管理**:使用清晰命名约定、分组测试套件(Test Suites)和依赖管理。\n\n6. **测试维护与演进**\n - **最小化维护成本**:通过模式(如测试工具方法、继承复用)适应系统变化。\n - **自检测试(Built-in Self-Test)**:确保测试本身的可信性。\n\n---\n\n### **书籍结构特点**\n- **问题驱动**:每章围绕具体问题(如“如何处理共享夹具?”)展开,提供模式、替代方案和权衡。\n- **视觉化总结**:通过图表展示模式间的关系,帮助读者理解复杂概念。\n- **实践导向**:结合代码示例与真实场景,指导如何应用模式解决测试中的常见痛点。\n\n---\n\n### **适用场景**\n- 开发中遇到测试代码重复、脆弱测试(Fragile Tests)或高维护成本时。\n- 需要设计复杂测试场景(如数据库交互、异步行为)时。\n- 团队希望建立统一的测试实践与规范时。\n\n通过遵循书中模式,开发者能构建更健壮、可维护的测试体系,最终提升软件质量和开发效率。", + "stop", + "9d81b84e95f844c29ee825ad8bb647bb", + [ + new ApplicationOutputThought( + null, + "agentRag", + "知识检索", + "rag", + "{}", + null, + "[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742716762&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=4CddPVeeyxgrXe5axUspV6zXnS8%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742716762&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=hRkFcnwAiV7LSHw69WvJJ6fXEV0%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]", + null, + "{}"), + new ApplicationOutputThought( + "好的,我现在需要总结用户提供的xUnit Test Patterns中的内容。首先,用户给了几个文档片段,每个片段都来自同一本书的不同部分。我需要仔细分析这些片段,看看里面提到的关键点和主题。\n\n第一个文档提到了“Visual Summary of the Pattern Language”,里面有几个关键点,比如Minimize Untestable Code,Buggy Tests,Production Bugs,还有测试维护成本高的问题。可能这本书在讲如何设计和管理单元测试的模式,避免常见的问题,比如不可测试的代码和测试逻辑混入生产环境。\n\n第二个文档片段讲的是“Managing Shared Fixtures”和结果验证(Result Verification)。这里提到共享夹具的管理、触发构建,以及如何验证测试结果,包括状态验证和行为验证,还有减少测试代码重复的方法,比如使用Expected Objects和Custom Assertions。这说明书中详细讨论了测试夹具的设计和如何有效验证测试结果,避免重复代码。\n\n第三个文档涉及数据库测试的问题,比如如何测试数据访问层、存储过程,以及确保开发者独立性的策略。这部分可能讨论在测试中使用数据库的挑战和解决方案,例如是否使用数据库进行测试,或者如何隔离测试以避免依赖。\n\n第四个文档提到了测试自动化的目标和哲学,包括测试的经济性、提高质量、理解系统、降低风险、易于运行和维护等。这说明书中不仅提供技术模式,还强调测试策略和哲学的重要性,指导如何有效实施自动化测试。\n\n第五个文档讨论了测试用例的组织策略,比如按类、功能或夹具组织测试用例类,命名约定,测试套件的管理,以及测试代码的重用方法。这部分可能涉及如何结构化测试代码,提高可维护性和可读性。\n\n综合这些片段,xUnit Test Patterns似乎是一本关于单元测试设计和最佳实践的指南,涵盖测试模式、夹具管理、结果验证、数据库测试、测试自动化策略和测试代码组织。重点在于如何编写可维护、可靠且高效的测试,避免常见陷阱,如不可测试的代码、测试逻辑污染生产代码、高维护成本等。书中可能还讨论了如何在不同情境下选择适当的测试策略,例如是否使用共享夹具,如何处理数据库依赖,以及如何组织测试代码结构以提高复用性。\n\n现在需要将这些分析整理成一个简明扼要的总结,突出主要主题和关键点,确保涵盖各个文档片段提到的内容,并指出这本书的整体目的和结构。可能需要分点说明,让用户清晰了解书中的核心内容。", + "reasoning", + "思考过程", + "reasoning", + null, + null, + null, + "好的,我现在需要总结用户提供的xUnit Test Patterns中的内容。首先,用户给了几个文档片段,每个片段都来自同一本书的不同部分。我需要仔细分析这些片段,看看里面提到的关键点和主题。\n\n第一个文档提到了“Visual Summary of the Pattern Language”,里面有几个关键点,比如Minimize Untestable Code,Buggy Tests,Production Bugs,还有测试维护成本高的问题。可能这本书在讲如何设计和管理单元测试的模式,避免常见的问题,比如不可测试的代码和测试逻辑混入生产环境。\n\n第二个文档片段讲的是“Managing Shared Fixtures”和结果验证(Result Verification)。这里提到共享夹具的管理、触发构建,以及如何验证测试结果,包括状态验证和行为验证,还有减少测试代码重复的方法,比如使用Expected Objects和Custom Assertions。这说明书中详细讨论了测试夹具的设计和如何有效验证测试结果,避免重复代码。\n\n第三个文档涉及数据库测试的问题,比如如何测试数据访问层、存储过程,以及确保开发者独立性的策略。这部分可能讨论在测试中使用数据库的挑战和解决方案,例如是否使用数据库进行测试,或者如何隔离测试以避免依赖。\n\n第四个文档提到了测试自动化的目标和哲学,包括测试的经济性、提高质量、理解系统、降低风险、易于运行和维护等。这说明书中不仅提供技术模式,还强调测试策略和哲学的重要性,指导如何有效实施自动化测试。\n\n第五个文档讨论了测试用例的组织策略,比如按类、功能或夹具组织测试用例类,命名约定,测试套件的管理,以及测试代码的重用方法。这部分可能涉及如何结构化测试代码,提高可维护性和可读性。\n\n综合这些片段,xUnit Test Patterns似乎是一本关于单元测试设计和最佳实践的指南,涵盖测试模式、夹具管理、结果验证、数据库测试、测试自动化策略和测试代码组织。重点在于如何编写可维护、可靠且高效的测试,避免常见陷阱,如不可测试的代码、测试逻辑污染生产代码、高维护成本等。书中可能还讨论了如何在不同情境下选择适当的测试策略,例如是否使用共享夹具,如何处理数据库依赖,以及如何组织测试代码结构以提高复用性。\n\n现在需要将这些分析整理成一个简明扼要的总结,突出主要主题和关键点,确保涵盖各个文档片段提到的内容,并指出这本书的整体目的和结构。可能需要分点说明,让用户清晰了解书中的核心内容。", + null) + ], + null), + new ApplicationUsage([new ApplicationModelUsage("deepseek-r1", 1129, 1126)]))); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Error.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Error.cs new file mode 100644 index 0000000..eb4ea63 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Error.cs @@ -0,0 +1,105 @@ +using Cnblogs.DashScope.Core; + +namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; + +public static partial class Snapshots +{ + public static class Error + { + public static readonly + RequestSnapshot, DashScopeError> + AuthError = new( + "auth-error", + new ModelRequest + { + Model = "qwen-max", + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, + Parameters = new TextGenerationParameters + { + ResultFormat = "text", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new int[][] { [37763, 367] }, + EnableSearch = false, + IncrementalOutput = false + } + }, + new DashScopeError + { + Code = "InvalidApiKey", + Message = "Invalid API-key provided.", + RequestId = "a1c0561c-1dfe-98a6-a62f-983577b8bc5e" + }); + + public static readonly + RequestSnapshot, DashScopeError> + ParameterError = new( + "parameter-error", + new ModelRequest + { + Model = "qwen-max", + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, + Parameters = new TextGenerationParameters + { + ResultFormat = "text", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new int[][] { [37763, 367] }, + EnableSearch = false, + IncrementalOutput = false + } + }, + new DashScopeError + { + Code = "InvalidParameter", + Message = "Role must be user or assistant and Content length must be greater than 0", + RequestId = "a5898c04-d210-901b-965f-e4bd90478805" + }); + + public static readonly + RequestSnapshot, DashScopeError> + ParameterErrorSse = new( + "parameter-error", + new ModelRequest + { + Model = "qwen-max", + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, + Parameters = new TextGenerationParameters + { + ResultFormat = "text", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new int[][] { [37763, 367] }, + EnableSearch = false, + IncrementalOutput = true + } + }, + new DashScopeError + { + Code = "InvalidParameter", + Message = "Role must be user or assistant and Content length must be greater than 0", + RequestId = "7671ecd8-93cc-9ee9-bc89-739f0fd8b809" + }); + + public static readonly RequestSnapshot UploadErrorNoSse = new( + "upload-file-error", + new DashScopeError + { + Code = "invalid_request_error", + Message = "'purpose' must be 'file-extract'", + RequestId = string.Empty + }); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs new file mode 100644 index 0000000..1ec249a --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs @@ -0,0 +1,517 @@ +using Cnblogs.DashScope.Core; + +namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; + +public static partial class Snapshots +{ + public static class MultimodalGeneration + { + public static readonly RequestSnapshot, + ModelResponse> VlNoSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + [ + 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 + { + Seed = 1234, + TopK = 100, + TopP = 0.81f, + Temperature = 1.1f, + VlHighResolutionImages = true, + RepetitionPenalty = 1.3f, + PresencePenalty = 1.2f, + MaxTokens = 120, + Stop = "你好" + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent("海滩。") + ])) + ]), + RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", + Usage = new MultimodalTokenUsage + { + OutputTokens = 3, + InputTokens = 3613, + ImageTokens = 3577 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> VlChatClientNoSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + [ + MultimodalMessage.User( + [ + MultimodalMessageContent.ImageContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + ]) + ] + }, + Parameters = new MultimodalParameters + { + Seed = 1234, + TopK = 100, + TopP = 0.81f, + Temperature = 1.1f, + RepetitionPenalty = 1.3f, + PresencePenalty = 1.2f, + MaxTokens = 120, + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent("海滩。") + ])) + ]), + RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", + Usage = new MultimodalTokenUsage + { + OutputTokens = 3, + InputTokens = 3613, + ImageTokens = 3577 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> VlSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + [ + 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 + { + IncrementalOutput = true, + Seed = 1234, + TopK = 100, + TopP = 0.81f + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") + ])) + ]), + RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", + Usage = new MultimodalTokenUsage + { + OutputTokens = 85, + InputTokens = 1283, + ImageTokens = 1247 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> VlChatClientSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + [ + MultimodalMessage.User( + [ + MultimodalMessageContent.ImageContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + ]) + ] + }, + Parameters = new MultimodalParameters + { + IncrementalOutput = true, + Seed = 1234, + TopK = 100, + TopP = 0.81f, + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") + ])) + ]), + RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", + Usage = new MultimodalTokenUsage + { + 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 ModelRequest + { + Model = "qwen-audio-turbo", + Input = new MultimodalInput + { + Messages = + [ + 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 + { + Seed = 1234, + TopK = 100, + TopP = 0.81f + } + }, + new ModelResponse + { + RequestId = "6b6738bd-dd9d-9e78-958b-02574acbda44", + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent( + "这段音频在说中文,内容是\"没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网\"。") + ])) + ]), + Usage = new MultimodalTokenUsage + { + InputTokens = 786, + OutputTokens = 38, + AudioTokens = 752 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + AudioSse = new( + "multimodal-generation-audio", + new ModelRequest + { + Model = "qwen-audio-turbo", + Input = new MultimodalInput + { + Messages = + [ + 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 + { + Seed = 1234, + TopK = 100, + TopP = 0.81f, + IncrementalOutput = true + } + }, + new ModelResponse + { + RequestId = "bb6ab962-af57-99f1-9af8-eb7016ebc18e", + Output = new MultimodalOutput( + [ + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + [ + MultimodalMessageContent.TextContent("第一句话说了没有我互联网。") + ])) + ]), + 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 + } + }); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Tasks.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Tasks.cs new file mode 100644 index 0000000..90b68ff --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Tasks.cs @@ -0,0 +1,379 @@ +using Cnblogs.DashScope.Core; + +namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; + +public static partial class Snapshots +{ + public static class Tasks + { + public static readonly RequestSnapshot> + Unknown = new( + "get-task-unknown", + new DashScopeTask( + "85c25460-6440-91a7-b14e-2978fe60bd0f", + new BatchGetEmbeddingsOutput { TaskId = "1111", TaskStatus = DashScopeTaskStatus.Unknown })); + + public static readonly RequestSnapshot> + BatchEmbeddingSuccess = new( + "get-task-batch-text-embedding-success", + new DashScopeTask( + "0b2ebeda-a91b-948f-986a-d395cbf1d0e1", + new BatchGetEmbeddingsOutput + { + TaskId = "7408ef3d-a0be-4379-9e72-a6e95a569483", + TaskStatus = DashScopeTaskStatus.Succeeded, + Url = + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/5fc5c860/2024-11-25/c6c4456e-3c66-42ba-a52a-a16c58dda4d6_output_1732514147173.txt.gz?Expires=1732773347&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=perMNS1RdHHroUn2YnXxzTmOZtg%3D", + SubmitTime = new DateTime(2024, 11, 25, 13, 55, 46, 536), + ScheduledTime = new DateTime(2024, 11, 25, 13, 55, 46, 557), + EndTime = new DateTime(2024, 11, 25, 13, 55, 47, 446) + }, + new TextEmbeddingTokenUsage(28))); + + public static readonly RequestSnapshot> + ImageSynthesisRunning = + new( + "get-task-running", + new DashScopeTask( + "edbd4e81-d37b-97f1-9857-d7394829dd0f", + 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 DashScopeTaskMetrics(4, 0, 0) + })); + + public static readonly RequestSnapshot> + ImageSynthesisSuccess = new( + "get-task-image-synthesis-success", + new DashScopeTask( + "6662e925-4846-9afe-a3af-0d131805d378", + new ImageSynthesisOutput + { + TaskId = "9e2b6ef6-285d-4efa-8651-4dbda7d571fa", + TaskStatus = DashScopeTaskStatus.Succeeded, + SubmitTime = new DateTime(2024, 3, 1, 17, 38, 24, 817), + ScheduledTime = new DateTime(2024, 3, 1, 17, 38, 24, 831), + EndTime = new DateTime(2024, 3, 1, 17, 38, 55, 565), + Results = + [ + new ImageSynthesisResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/1d/d4/20240301/8d820c8d/4c48fa53-2907-499b-b9ac-76477fe8d299-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=bEfLmd%2BarXgZyhxcVYOWs%2BovJb8%3D"), + new ImageSynthesisResult( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=fdPScmRkIXyH3TSaSaWwvVjxREQ%3D"), + new ImageSynthesisResult( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/0f/20240301/3ab595ad/ecfe06b3-b91c-4950-a932-49ea1619a1f9-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=gNuVAt8iy4X8Nl2l3K4Gu4f0ydw%3D"), + new ImageSynthesisResult( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/3d/20240301/3ab595ad/3fca748e-d491-458a-bb72-73649af33209-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=Mx5TueC9I9yfDno9rjzi48opHtM%3D") + ], + TaskMetrics = new DashScopeTaskMetrics(4, 4, 0) + }, + new ImageSynthesisUsage(4))); + + public static readonly RequestSnapshot> + ImageGenerationSuccess = new( + "get-task-image-generation-success", + new DashScopeTask( + "f927c766-5079-90f8-9354-6a87d2167897", + new ImageGenerationOutput + { + TaskId = "c4f94e00-5899-431b-9579-eb1ebe686379", + TaskStatus = DashScopeTaskStatus.Succeeded, + SubmitTime = new DateTime(2024, 3, 2, 22, 22, 13, 026), + ScheduledTime = new DateTime(2024, 3, 2, 22, 22, 13, 051), + EndTime = new DateTime(2024, 3, 2, 22, 22, 21), + StartTime = new DateTime(2024, 3, 2, 22, 22, 13), + StyleIndex = 3, + ErrorCode = 0, + ErrorMessage = "Success", + Results = + [ + new ImageGenerationResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-03-02/ac5d435a-9ea9-4287-8666-e1be7bbba943/20240302222213528791_style3_jxdf6o4zwy.jpg?Expires=1709475741&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=LM26fy1Pk8rCfPzihzpUqa3Vst8%3D") + ] + }, + new ImageGenerationUsage(1))); + + public static readonly RequestSnapshot> + BackgroundGenerationSuccess = new( + "get-task-background-generation-success", + new DashScopeTask( + "8b22164d-c784-9a31-bda3-3c26259d4213", + new BackgroundGenerationOutput + { + TaskId = "b2e98d78-c79b-431c-b2d7-c7bcd54465da", + TaskStatus = DashScopeTaskStatus.Succeeded, + SubmitTime = new DateTime(2024, 3, 4, 10, 8, 57, 333), + ScheduledTime = new DateTime(2024, 3, 4, 10, 8, 57, 363), + EndTime = new DateTime(2024, 3, 4, 10, 9, 7, 727), + Results = + [ + new BackgroundGenerationResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_0_02dc0bba-8b1d-4648-8b95-eb2b92fe715d.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=OYstgSxWOl%2FOxYTLa2Mx3bi2RWw%3D"), + new BackgroundGenerationResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_1_e1af86ec-152a-4ebe-b2a0-b40a592043b2.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=p0UXTUdXfp0tFlt0K5tDsA%2Fxl1M%3D") + ], + TaskMetrics = new DashScopeTaskMetrics(2, 2, 0), + TextResults = + new BackgroundGenerationTextResult( + [ + new BackgroundGenerationTextResultUrl( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_0_4645005c-713d-4e92-9629-b12cbe5f3671.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=kmZGXc2s8P4uI%2BVrADITyrPz82U%3D"), + new BackgroundGenerationTextResultUrl( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_1_b1979b75-c553-4d9b-9c9f-80f401a0d124.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=cb1Qg%2FkIuZyI7XQqWHjP712N0ak%3D") + ], + [ + new BackgroundGenerationTextResultParams( + 0, + [ + new BackgroundGenerationTextResultLayer( + 0, + "text_mask", + 0, + 0, + 1024, + 257, + Color: "#521b08", + Opacity: 0.8f, + Radius: 0, + Gradient: new BackgroundGenerationTextResultGradient( + "linear", + "pixels", + [ + new BackgroundGenerationTextResultGradientColorStop( + "#521b0800", + 0), + new BackgroundGenerationTextResultGradientColorStop( + "#521b08ff", + 1) + ]) + { + Coords = new Dictionary + { + { "y1", 257 }, + { "x1", 0 }, + { "y2", 0 }, + { "x2", 0 } + } + }), + new BackgroundGenerationTextResultLayer( + 1, + "text", + 25, + 319, + 385, + 77, + SubType: "Title", + FontWeight: "Regular", + FontSize: 67, + Content: "分享好时光", + FontUnderLine: false, + LineHeight: 1f, + FontItalic: false, + FontColor: "#e6baa7", + TextShadow: "1px 0px #80808080", + TextStroke: "1px #fffffff0", + FontFamily: "站酷文艺体", + Alignment: "center", + FontLineThrough: false, + Direction: "horizontal", + Opacity: 1f), + new BackgroundGenerationTextResultLayer( + 2, + "text_mask", + 118, + 395, + 233, + 50, + Color: "#e6baa7", + Opacity: 1f, + Radius: 37, + BoxShadow: "2px 1px #80808080", + Gradient: new BackgroundGenerationTextResultGradient( + "linear", + "pixels", + [ + new BackgroundGenerationTextResultGradientColorStop( + "#e6baa7ff", + 0), + new BackgroundGenerationTextResultGradientColorStop( + "#e6baa7ff", + 1) + ]) + { + Coords = new Dictionary + { + { "y1", 0 }, + { "x1", 0 }, + { "y2", 50 }, + { "x2", 0 } + } + }), + new BackgroundGenerationTextResultLayer( + 3, + "text", + 118, + 395, + 233, + 50, + FontWeight: "Medium", + FontSize: 27, + Content: "只为不一样的你", + FontUnderLine: false, + LineHeight: 1f, + FontItalic: false, + SubType: "SubTitle", + FontColor: "#223629", + TextShadow: null, + FontFamily: "阿里巴巴普惠体", + Alignment: "center", + Opacity: 1f, + FontLineThrough: false, + Direction: "horizontal") + ]), + new BackgroundGenerationTextResultParams( + 1, + [ + new BackgroundGenerationTextResultLayer( + 0, + "text_mask", + 0, + 0, + 1024, + 257, + Color: "#efeae4", + Gradient: new BackgroundGenerationTextResultGradient( + "linear", + "pixels", + [ + new BackgroundGenerationTextResultGradientColorStop( + "#efeae400", + 0), + new BackgroundGenerationTextResultGradientColorStop( + "#efeae4ff", + 1) + ]) + { + Coords = new Dictionary + { + { "y1", 257 }, + { "x1", 0 }, + { "y2", 0 }, + { "x2", 0 } + } + }, + Opacity: 0.8f, + Radius: 0), + new BackgroundGenerationTextResultLayer( + 1, + "text", + 25, + 319, + 385, + 77, + SubType: "Title", + Content: "分享好时光", + FontWeight: "Regular", + FontSize: 67, + FontUnderLine: false, + LineHeight: 1f, + FontItalic: false, + FontColor: "#421f12", + TextStroke: "1px #fffffff0", + TextShadow: "0px 2px #80808080", + FontFamily: "钉钉进步体", + Alignment: "center", + Opacity: 1f, + FontLineThrough: false, + Direction: "horizontal"), + new BackgroundGenerationTextResultLayer( + 2, + "text_mask", + 118, + 395, + 233, + 50, + Color: "#421f12", + Gradient: new BackgroundGenerationTextResultGradient( + "linear", + "pixels", + [ + new BackgroundGenerationTextResultGradientColorStop( + "#421f12ff", + 0), + new BackgroundGenerationTextResultGradientColorStop( + "#421f12ff", + 1) + ]) + { + Coords = new Dictionary + { + { "y1", 0 }, + { "x1", 0 }, + { "y2", 50 }, + { "x2", 0 } + } + }, + Opacity: 1f, + Radius: 37, + BoxShadow: "0px 0px #80808080"), + new BackgroundGenerationTextResultLayer( + 3, + "text", + 118, + 395, + 233, + 50, + FontWeight: "Regular", + FontSize: 27, + Content: "只为不一样的你", + FontUnderLine: false, + LineHeight: 1, + FontItalic: false, + SubType: "SubTitle", + FontColor: "#f1eeec", + TextShadow: null, + FontFamily: "阿里巴巴普惠体", + Alignment: "center", + Opacity: 1, + FontLineThrough: false, + Direction: "horizontal") + ]) + ]) + }, + new BackgroundGenerationUsage(2))); + + public static readonly RequestSnapshot CancelCompletedTask = new( + "cancel-completed-task", + new DashScopeTaskOperationResponse( + "4d496c94-1389-9ca9-a92a-3e732f675686", + "UnsupportedOperation", + "Failed to cancel the task, please confirm if the task is in PENDING status.")); + + public static readonly RequestSnapshot ListTasks = new( + "list-task", + new DashScopeTaskList( + "fcb29ae5-a352-9e7b-901c-e53525376cde", + [ + new DashScopeTaskListItem( + "42677", + "1493478651020171", + "1493478651020171", + 1709260684485, + 1709260684527, + 1709260685184, + "cn-beijing", + "db5ce040-4548-9919-9a75-3385ee152335", + DashScopeTaskStatus.Succeeded, + "6075262c-b56d-4968-9abf-2a9784a90f3e", + "apikey:v1:embeddings:text-embedding:text-embedding:text-embedding-async-v2", + "text-embedding-async-v2") + ], + 1, + 1, + 1, + 10)); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextEmbedding.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextEmbedding.cs new file mode 100644 index 0000000..bbfa68f --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextEmbedding.cs @@ -0,0 +1,65 @@ +using Cnblogs.DashScope.Core; + +namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; + +public static partial class Snapshots +{ + public static class TextEmbedding + { + public static readonly RequestSnapshot, + ModelResponse> NoSse = new( + "text-embedding", + new ModelRequest + { + Input = new TextEmbeddingInput { Texts = ["代码改变世界"] }, + Model = "text-embedding-v2", + Parameters = new TextEmbeddingParameters { TextType = "query" } + }, + new ModelResponse + { + Output = new TextEmbeddingOutput([new TextEmbeddingItem(0, [])]), + RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", + Usage = new TextEmbeddingTokenUsage(3) + }); + + public static readonly RequestSnapshot, + ModelResponse> EmbeddingClientNoSse = new( + "text-embedding", + new ModelRequest + { + Input = new TextEmbeddingInput { Texts = ["代码改变世界"] }, + Model = "text-embedding-v3", + Parameters = new TextEmbeddingParameters { Dimension = 1024 } + }, + new ModelResponse + { + Output = new TextEmbeddingOutput([new TextEmbeddingItem(0, [])]), + RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", + Usage = new TextEmbeddingTokenUsage(3) + }); + + public static readonly + RequestSnapshot, + ModelResponse> BatchNoSse = new( + "batch-text-embedding", + new ModelRequest + { + Input = new BatchGetEmbeddingsInput + { + Url = + "https://modelscope.oss-cn-beijing.aliyuncs.com/resource/text_embedding_file.txt" + }, + Model = "text-embedding-async-v2", + Parameters = new BatchGetEmbeddingsParameters { TextType = "query" } + }, + new ModelResponse + { + RequestId = "db5ce040-4548-9919-9a75-3385ee152335", + Output = new BatchGetEmbeddingsOutput + { + TaskId = "6075262c-b56d-4968-9abf-2a9784a90f3e", + TaskStatus = DashScopeTaskStatus.Pending + } + }); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs new file mode 100644 index 0000000..6f8fe94 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs @@ -0,0 +1,614 @@ +using Cnblogs.DashScope.Core; +using Json.Schema; +using Json.Schema.Generation; + +namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; + +public static partial class Snapshots +{ + public static class TextGeneration + { + public static class TextFormat + { + public static readonly RequestSnapshot, + ModelResponse> + SinglePrompt = new( + "single-generation-text", + new ModelRequest + { + Model = "qwen-max", + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, + Parameters = new TextGenerationParameters + { + ResultFormat = "text", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new int[][] { [37763, 367] }, + EnableSearch = false, + IncrementalOutput = false + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + FinishReason = "stop", Text = "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下两个一相加的结果都是二。" + }, + RequestId = "4ef2ed16-4dc3-9083-a723-fb2e80c84d3b", + Usage = new TextGenerationTokenUsage + { + InputTokens = 8, + OutputTokens = 35, + TotalTokens = 43 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + SinglePromptIncremental = new( + "single-generation-text", + new ModelRequest + { + Model = "qwen-max", + Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, + Parameters = new TextGenerationParameters + { + ResultFormat = "text", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new int[][] { [37763, 367] }, + EnableSearch = false, + IncrementalOutput = true + } + }, + new ModelResponse + { + Output = new TextGenerationOutput { FinishReason = "stop", Text = "1+1等于2。" }, + RequestId = "5b441aa7-0b9c-9fbc-ae0a-e2b212b71eac", + Usage = new TextGenerationTokenUsage + { + InputTokens = 16, + OutputTokens = 6, + TotalTokens = 22 + } + }); + } + + public static class MessageFormat + { + public static readonly RequestSnapshot, + ModelResponse> + SingleMessage = new( + "single-generation-message", + new ModelRequest + { + Model = "qwen-max", + Input = + new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + 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 + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") + } + ] + }, + RequestId = "e764bfe3-c0b7-97a0-ae57-cd99e1580960", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 47, + OutputTokens = 39, + InputTokens = 8 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + SingleChatClientMessage = new( + "single-generation-message", + new ModelRequest + { + Model = "qwen-max", + Input = + new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + Parameters = new TextGenerationParameters + { + ResultFormat = "message", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + ToolChoice = ToolChoice.AutoChoice + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") + } + ] + }, + RequestId = "e764bfe3-c0b7-97a0-ae57-cd99e1580960", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 47, + OutputTokens = 39, + InputTokens = 8 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + SingleMessageJson = new( + "single-generation-message-json", + new ModelRequest + { + Model = "qwen-max", + Input = + new TextGenerationInput { Messages = [TextChatMessage.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 = TextChatMessage.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 ModelRequest + { + Model = "qwen-max", + Input = + new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + 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 = true + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") + } + ] + }, + RequestId = "d272255f-82d7-9cc7-93c5-17ff77024349", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 48, + OutputTokens = 40, + InputTokens = 8 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + SingleMessageChatClientIncremental = new( + "single-generation-message", + new ModelRequest + { + Model = "qwen-max", + Input = + new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + Parameters = new TextGenerationParameters + { + ResultFormat = "message", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + Temperature = 0.85f, + Stop = new[] { "你好" }, + IncrementalOutput = true, + ToolChoice = ToolChoice.AutoChoice + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") + } + ] + }, + RequestId = "d272255f-82d7-9cc7-93c5-17ff77024349", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 48, + OutputTokens = 40, + InputTokens = 8 + } + }); + + public static readonly + RequestSnapshot, + ModelResponse> SingleMessageWithTools = + new( + "single-generation-message-with-tools", + new ModelRequest + { + Model = "qwen-max", + Input = new TextGenerationInput { Messages = [TextChatMessage.User("杭州现在的天气如何?")] }, + Parameters = new TextGenerationParameters() + { + ResultFormat = "message", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + PresencePenalty = 1.2f, + Temperature = 0.85f, + Stop = new TextGenerationStop("你好"), + EnableSearch = false, + IncrementalOutput = false, + Tools = + [ + new ToolDefinition( + "function", + new FunctionDefinition( + "get_current_weather", + "获取现在的天气", + new JsonSchemaBuilder().FromType( + new SchemaGeneratorConfiguration + { + PropertyNameResolver = PropertyNameResolvers.LowerSnakeCase + }) + .Build())) + ], + ToolChoice = ToolChoice.FunctionChoice("get_current_weather") + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + string.Empty, + toolCalls: + [ + new ToolCall( + "call_cec4c19d27624537b583af", + ToolTypes.Function, + 0, + new FunctionCall( + "get_current_weather", + """{"location": "浙江省杭州市"}""")) + ]) + } + ] + }, + RequestId = "67300049-c108-9987-b1c1-8e0ee2de6b5d", + Usage = new TextGenerationTokenUsage + { + InputTokens = 211, + OutputTokens = 8, + TotalTokens = 219 + } + }); + + public static readonly + RequestSnapshot, + ModelResponse> SingleMessageChatClientWithTools = + new( + "single-generation-message-with-tools", + new ModelRequest + { + Model = "qwen-max", + Input = new TextGenerationInput { Messages = [TextChatMessage.User("杭州现在的天气如何?")] }, + Parameters = new TextGenerationParameters() + { + ResultFormat = "message", + Seed = 1234, + MaxTokens = 1500, + TopP = 0.8f, + TopK = 100, + RepetitionPenalty = 1.1f, + PresencePenalty = 1.2f, + Temperature = 0.85f, + Tools = + [ + new ToolDefinition( + "function", + new FunctionDefinition( + "get_current_weather", + "获取现在的天气", + new JsonSchemaBuilder().FromType( + new SchemaGeneratorConfiguration + { + PropertyNameResolver = PropertyNameResolvers.LowerSnakeCase + }) + .Build())) + ], + ToolChoice = ToolChoice.FunctionChoice("get_current_weather") + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + string.Empty, + toolCalls: + [ + new ToolCall( + "call_cec4c19d27624537b583af", + ToolTypes.Function, + 0, + new FunctionCall( + "get_current_weather", + """{"location": "浙江省杭州市"}""")) + ]) + } + ] + }, + RequestId = "67300049-c108-9987-b1c1-8e0ee2de6b5d", + Usage = new TextGenerationTokenUsage + { + InputTokens = 211, + OutputTokens = 8, + TotalTokens = 219 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + ConversationPartialMessageNoSse = new( + "conversation-generation-message-partial", + new ModelRequest() + { + Model = "qwen-max", + Input = new TextGenerationInput() + { + Messages = + [ + TextChatMessage.User("请对“春天来了,大地”这句话进行续写,来表达春天的美好和作者的喜悦之情"), + TextChatMessage.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 = + TextChatMessage.Assistant( + "仿佛从漫长的冬眠中苏醒过来,万物复苏。嫩绿的小草悄悄地探出了头,争先恐后地想要沐浴在温暖的阳光下;五彩斑斓的花朵也不甘示弱,竞相绽放着自己最美丽的姿态,将田野、山林装扮得分外妖娆。微风轻轻吹过,带来了泥土的气息与花香混合的独特香味,让人心旷神怡。小鸟们开始忙碌起来,在枝头欢快地歌唱,似乎也在庆祝这个充满希望的新季节的到来。这一切美好景象不仅让人感受到了大自然的魅力所在,更激发了人们对生活无限热爱和向往的心情。") + } + ] + }, + Usage = new TextGenerationTokenUsage() + { + TotalTokens = 165, + OutputTokens = 131, + InputTokens = 34 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + ConversationMessageIncremental = new( + "conversation-generation-message", + new ModelRequest + { + Model = "qwen-max", + Input = + new TextGenerationInput + { + Messages = + [ + TextChatMessage.User("现在请你记住一个数字,42"), + TextChatMessage.Assistant("好的,我已经记住了这个数字。"), + TextChatMessage.User("请问我刚才提到的数字是多少?") + ] + }, + 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 = true + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", Message = TextChatMessage.Assistant("您刚才提到的数字是42。") + } + ] + }, + RequestId = "9188e907-56c2-9849-97f6-23f130f7fed7", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 33, + OutputTokens = 9, + InputTokens = 24 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + ConversationMessageWithFilesIncremental = new( + "conversation-generation-message-with-files", + new ModelRequest + { + Model = "qwen-long", + Input = + new TextGenerationInput + { + Messages = + [ + TextChatMessage.File( + ["file-fe-WTTG89tIUTd4ByqP3K48R3bn", "file-fe-l92iyRvJm9vHCCfonLckf1o2"]), + TextChatMessage.User("这两个文件是相同的吗?") + ] + }, + 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 = true + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "你上传的两个文件并不相同。第一个文件`test1.txt`包含两行文本,每行都是“测试”。而第二个文件`test2.txt`只有一行文本,“测试2”。尽管它们都含有“测试”这个词,但具体内容和结构不同。") + } + ] + }, + RequestId = "7865ae43-8379-9c79-bef6-95050868bc52", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 115, + OutputTokens = 57, + InputTokens = 58 + } + }); + } + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs index 5c87619..ab61622 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs @@ -1,1385 +1,9 @@ using Cnblogs.DashScope.Core; -using Json.Schema; -using Json.Schema.Generation; namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; -public static class Snapshots +public static partial class Snapshots { - public static class Error - { - public static readonly - RequestSnapshot, DashScopeError> - AuthError = new( - "auth-error", - new ModelRequest - { - Model = "qwen-max", - Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, - Parameters = new TextGenerationParameters - { - ResultFormat = "text", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, - EnableSearch = false, - IncrementalOutput = false - } - }, - new DashScopeError - { - Code = "InvalidApiKey", - Message = "Invalid API-key provided.", - RequestId = "a1c0561c-1dfe-98a6-a62f-983577b8bc5e" - }); - - public static readonly - RequestSnapshot, DashScopeError> - ParameterError = new( - "parameter-error", - new ModelRequest - { - Model = "qwen-max", - Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, - Parameters = new TextGenerationParameters - { - ResultFormat = "text", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, - EnableSearch = false, - IncrementalOutput = false - } - }, - new DashScopeError - { - Code = "InvalidParameter", - Message = "Role must be user or assistant and Content length must be greater than 0", - RequestId = "a5898c04-d210-901b-965f-e4bd90478805" - }); - - public static readonly - RequestSnapshot, DashScopeError> - ParameterErrorSse = new( - "parameter-error", - new ModelRequest - { - Model = "qwen-max", - Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, - Parameters = new TextGenerationParameters - { - ResultFormat = "text", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, - EnableSearch = false, - IncrementalOutput = true - } - }, - new DashScopeError - { - Code = "InvalidParameter", - Message = "Role must be user or assistant and Content length must be greater than 0", - RequestId = "7671ecd8-93cc-9ee9-bc89-739f0fd8b809" - }); - - public static readonly RequestSnapshot UploadErrorNoSse = new( - "upload-file-error", - new DashScopeError - { - Code = "invalid_request_error", - Message = "'purpose' must be 'file-extract'", - RequestId = string.Empty - }); - } - - public static class Application - { - public static readonly RequestSnapshot SinglePrompt = - new( - "application-single-generation-text", - new ApplicationRequest() - { - Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, - Parameters = new ApplicationParameters() - { - TopK = 100, - TopP = 0.8f, - Seed = 1234, - Temperature = 0.85f, - RagOptions = new ApplicationRagOptions() - { - PipelineIds = ["thie5bysoj"], - FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] - } - } - }, - new ApplicationResponse( - "c127bd40-180c-9cfa-b991-f875edd8c310", - null, - null, - new ApplicationOutput( - "xUnit Test Patterns 提供了一套全面的指南,用于改进测试自动化和重构测试代码。以下是根据提供的文档内容总结的关键点:\n\n1. 测试自动化的目标包括帮助提高产品质量、帮助我们理解被测系统(SUT)、减少(并且不引入)风险、易于运行、编写和维护[4]。\n2. 在管理共享fixture方面,文档讨论了访问共享fixture以及触发共享fixture构造的方法[2]。\n3. 关于结果验证,文档提供了自我检查测试的方法,验证状态或行为,使用内置断言进行状态验证,以及验证直接输出和替代路径[2]。\n4. 当涉及到数据库时,文档提到了与数据库相关的测试问题、没有数据库的测试、数据库测试、存储过程测试、数据访问层测试,并强调确保开发者独立性[3]。\n5. 文档还涵盖了测试方法组织策略、测试命名约定、测试套件组织、运行测试组或单个测试、测试代码重用、测试文件组织等内容[5]。\n\n这些模式和实践旨在解决测试中的常见问题,如高测试维护成本、不可测试代码最小化、防止生产代码中的错误测试等[1]。通过应用这些模式,开发者可以创建更高效、更易于维护的自动化测试。", - "stop", - "b7250cba47db463ca851dfb4088e71d8", - [ - new ApplicationOutputThought( - null, - "agentRag", - "知识检索", - "rag", - "{}", - null, - "[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]", - null, - "{}"), - new ApplicationOutputThought( - null, - "api", - "长期记忆检索", - "memory", - "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}", - null, - "[]", - null, - "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}") - ], - [ - new ApplicationDocReference( - "1", - "Visual Summary of the Pattern Language", - "file_d129d632800c45aa9e7421b30561f447_10207234", - "xUnit Test Patterns", - "【文档名】:xUnit Test Patterns\n【标题】:Visual Summary of the Pattern Language\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\n", - [ - "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648", - "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302" - ], - null), - new ApplicationDocReference( - "2", - "xUnit Test Patterns", - "file_d129d632800c45aa9e7421b30561f447_10207234", - "xUnit Test Patterns", - "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", - [], - null), - new ApplicationDocReference( - "3", - "xUnit Test Patterns", - "file_d129d632800c45aa9e7421b30561f447_10207234", - "xUnit Test Patterns", - "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", - [], - null), - new ApplicationDocReference( - "4", - "xUnit Test Patterns", - "file_d129d632800c45aa9e7421b30561f447_10207234", - "xUnit Test Patterns", - "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", - [], - null), - new ApplicationDocReference( - "5", - "xUnit Test Patterns", - "file_d129d632800c45aa9e7421b30561f447_10207234", - "xUnit Test Patterns", - "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n", - [], - null) - ]), - new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 2591, 290)]))); - } - - public static class TextGeneration - { - public static class TextFormat - { - public static readonly RequestSnapshot, - ModelResponse> - SinglePrompt = new( - "single-generation-text", - new ModelRequest - { - Model = "qwen-max", - Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, - Parameters = new TextGenerationParameters - { - ResultFormat = "text", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, - EnableSearch = false, - IncrementalOutput = false - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - FinishReason = "stop", Text = "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下两个一相加的结果都是二。" - }, - RequestId = "4ef2ed16-4dc3-9083-a723-fb2e80c84d3b", - Usage = new TextGenerationTokenUsage - { - InputTokens = 8, - OutputTokens = 35, - TotalTokens = 43 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - SinglePromptIncremental = new( - "single-generation-text", - new ModelRequest - { - Model = "qwen-max", - Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?" }, - Parameters = new TextGenerationParameters - { - ResultFormat = "text", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, - EnableSearch = false, - IncrementalOutput = true - } - }, - new ModelResponse - { - Output = new TextGenerationOutput { FinishReason = "stop", Text = "1+1等于2。" }, - RequestId = "5b441aa7-0b9c-9fbc-ae0a-e2b212b71eac", - Usage = new TextGenerationTokenUsage - { - InputTokens = 16, - OutputTokens = 6, - TotalTokens = 22 - } - }); - } - - public static class MessageFormat - { - public static readonly RequestSnapshot, - ModelResponse> - SingleMessage = new( - "single-generation-message", - new ModelRequest - { - Model = "qwen-max", - Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, - 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 - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") - } - ] - }, - RequestId = "e764bfe3-c0b7-97a0-ae57-cd99e1580960", - Usage = new TextGenerationTokenUsage - { - TotalTokens = 47, - OutputTokens = 39, - InputTokens = 8 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - SingleChatClientMessage = new( - "single-generation-message", - new ModelRequest - { - Model = "qwen-max", - Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, - Parameters = new TextGenerationParameters - { - ResultFormat = "message", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - Temperature = 0.85f, - ToolChoice = ToolChoice.AutoChoice - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") - } - ] - }, - RequestId = "e764bfe3-c0b7-97a0-ae57-cd99e1580960", - Usage = new TextGenerationTokenUsage - { - TotalTokens = 47, - OutputTokens = 39, - InputTokens = 8 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - SingleMessageJson = new( - "single-generation-message-json", - new ModelRequest - { - Model = "qwen-max", - Input = - new TextGenerationInput { Messages = [TextChatMessage.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 = TextChatMessage.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 ModelRequest - { - Model = "qwen-max", - Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, - 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 = true - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") - } - ] - }, - RequestId = "d272255f-82d7-9cc7-93c5-17ff77024349", - Usage = new TextGenerationTokenUsage - { - TotalTokens = 48, - OutputTokens = 40, - InputTokens = 8 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - SingleMessageChatClientIncremental = new( - "single-generation-message", - new ModelRequest - { - Model = "qwen-max", - Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, - Parameters = new TextGenerationParameters - { - ResultFormat = "message", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - Temperature = 0.85f, - Stop = new[] { "你好" }, - IncrementalOutput = true, - ToolChoice = ToolChoice.AutoChoice - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") - } - ] - }, - RequestId = "d272255f-82d7-9cc7-93c5-17ff77024349", - Usage = new TextGenerationTokenUsage - { - TotalTokens = 48, - OutputTokens = 40, - InputTokens = 8 - } - }); - - public static readonly - RequestSnapshot, - ModelResponse> SingleMessageWithTools = - new( - "single-generation-message-with-tools", - new ModelRequest - { - Model = "qwen-max", - Input = new TextGenerationInput { Messages = [TextChatMessage.User("杭州现在的天气如何?")] }, - Parameters = new TextGenerationParameters() - { - ResultFormat = "message", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - PresencePenalty = 1.2f, - Temperature = 0.85f, - Stop = new TextGenerationStop("你好"), - EnableSearch = false, - IncrementalOutput = false, - Tools = - [ - new ToolDefinition( - "function", - new FunctionDefinition( - "get_current_weather", - "获取现在的天气", - new JsonSchemaBuilder().FromType( - new SchemaGeneratorConfiguration - { - PropertyNameResolver = PropertyNameResolvers.LowerSnakeCase - }) - .Build())) - ], - ToolChoice = ToolChoice.FunctionChoice("get_current_weather") - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - string.Empty, - toolCalls: - [ - new ToolCall( - "call_cec4c19d27624537b583af", - ToolTypes.Function, - 0, - new FunctionCall( - "get_current_weather", - """{"location": "浙江省杭州市"}""")) - ]) - } - ] - }, - RequestId = "67300049-c108-9987-b1c1-8e0ee2de6b5d", - Usage = new TextGenerationTokenUsage - { - InputTokens = 211, - OutputTokens = 8, - TotalTokens = 219 - } - }); - - public static readonly - RequestSnapshot, - ModelResponse> SingleMessageChatClientWithTools = - new( - "single-generation-message-with-tools", - new ModelRequest - { - Model = "qwen-max", - Input = new TextGenerationInput { Messages = [TextChatMessage.User("杭州现在的天气如何?")] }, - Parameters = new TextGenerationParameters() - { - ResultFormat = "message", - Seed = 1234, - MaxTokens = 1500, - TopP = 0.8f, - TopK = 100, - RepetitionPenalty = 1.1f, - PresencePenalty = 1.2f, - Temperature = 0.85f, - Tools = - [ - new ToolDefinition( - "function", - new FunctionDefinition( - "get_current_weather", - "获取现在的天气", - new JsonSchemaBuilder().FromType( - new SchemaGeneratorConfiguration - { - PropertyNameResolver = PropertyNameResolvers.LowerSnakeCase - }) - .Build())) - ], - ToolChoice = ToolChoice.FunctionChoice("get_current_weather") - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - string.Empty, - toolCalls: - [ - new ToolCall( - "call_cec4c19d27624537b583af", - ToolTypes.Function, - 0, - new FunctionCall( - "get_current_weather", - """{"location": "浙江省杭州市"}""")) - ]) - } - ] - }, - RequestId = "67300049-c108-9987-b1c1-8e0ee2de6b5d", - Usage = new TextGenerationTokenUsage - { - InputTokens = 211, - OutputTokens = 8, - TotalTokens = 219 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - ConversationPartialMessageNoSse = new( - "conversation-generation-message-partial", - new ModelRequest() - { - Model = "qwen-max", - Input = new TextGenerationInput() - { - Messages = - [ - TextChatMessage.User("请对“春天来了,大地”这句话进行续写,来表达春天的美好和作者的喜悦之情"), - TextChatMessage.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 = - TextChatMessage.Assistant( - "仿佛从漫长的冬眠中苏醒过来,万物复苏。嫩绿的小草悄悄地探出了头,争先恐后地想要沐浴在温暖的阳光下;五彩斑斓的花朵也不甘示弱,竞相绽放着自己最美丽的姿态,将田野、山林装扮得分外妖娆。微风轻轻吹过,带来了泥土的气息与花香混合的独特香味,让人心旷神怡。小鸟们开始忙碌起来,在枝头欢快地歌唱,似乎也在庆祝这个充满希望的新季节的到来。这一切美好景象不仅让人感受到了大自然的魅力所在,更激发了人们对生活无限热爱和向往的心情。") - } - ] - }, - Usage = new TextGenerationTokenUsage() - { - TotalTokens = 165, - OutputTokens = 131, - InputTokens = 34 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - ConversationMessageIncremental = new( - "conversation-generation-message", - new ModelRequest - { - Model = "qwen-max", - Input = - new TextGenerationInput - { - Messages = - [ - TextChatMessage.User("现在请你记住一个数字,42"), - TextChatMessage.Assistant("好的,我已经记住了这个数字。"), - TextChatMessage.User("请问我刚才提到的数字是多少?") - ] - }, - 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 = true - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", Message = TextChatMessage.Assistant("您刚才提到的数字是42。") - } - ] - }, - RequestId = "9188e907-56c2-9849-97f6-23f130f7fed7", - Usage = new TextGenerationTokenUsage - { - TotalTokens = 33, - OutputTokens = 9, - InputTokens = 24 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - ConversationMessageWithFilesIncremental = new( - "conversation-generation-message-with-files", - new ModelRequest - { - Model = "qwen-long", - Input = - new TextGenerationInput - { - Messages = - [ - TextChatMessage.File( - ["file-fe-WTTG89tIUTd4ByqP3K48R3bn", "file-fe-l92iyRvJm9vHCCfonLckf1o2"]), - TextChatMessage.User("这两个文件是相同的吗?") - ] - }, - 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 = true - } - }, - new ModelResponse - { - Output = new TextGenerationOutput - { - Choices = - [ - new TextGenerationChoice - { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "你上传的两个文件并不相同。第一个文件`test1.txt`包含两行文本,每行都是“测试”。而第二个文件`test2.txt`只有一行文本,“测试2”。尽管它们都含有“测试”这个词,但具体内容和结构不同。") - } - ] - }, - RequestId = "7865ae43-8379-9c79-bef6-95050868bc52", - Usage = new TextGenerationTokenUsage - { - TotalTokens = 115, - OutputTokens = 57, - InputTokens = 58 - } - }); - } - } - - public static class MultimodalGeneration - { - public static readonly RequestSnapshot, - ModelResponse> VlNoSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - Seed = 1234, - TopK = 100, - TopP = 0.81f, - Temperature = 1.1f, - VlHighResolutionImages = true, - RepetitionPenalty = 1.3f, - PresencePenalty = 1.2f, - MaxTokens = 120, - Stop = "你好" - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent("海滩。") - ])) - ]), - RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", - Usage = new MultimodalTokenUsage - { - OutputTokens = 3, - InputTokens = 3613, - ImageTokens = 3577 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> VlChatClientNoSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - MultimodalMessage.User( - [ - MultimodalMessageContent.ImageContent( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), - MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") - ]) - ] - }, - Parameters = new MultimodalParameters - { - Seed = 1234, - TopK = 100, - TopP = 0.81f, - Temperature = 1.1f, - RepetitionPenalty = 1.3f, - PresencePenalty = 1.2f, - MaxTokens = 120, - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent("海滩。") - ])) - ]), - RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", - Usage = new MultimodalTokenUsage - { - OutputTokens = 3, - InputTokens = 3613, - ImageTokens = 3577 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> VlSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - IncrementalOutput = true, - Seed = 1234, - TopK = 100, - TopP = 0.81f - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent( - "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") - ])) - ]), - RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", - Usage = new MultimodalTokenUsage - { - OutputTokens = 85, - InputTokens = 1283, - ImageTokens = 1247 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> VlChatClientSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - MultimodalMessage.User( - [ - MultimodalMessageContent.ImageContent( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), - MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") - ]) - ] - }, - Parameters = new MultimodalParameters - { - IncrementalOutput = true, - Seed = 1234, - TopK = 100, - TopP = 0.81f, - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent( - "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") - ])) - ]), - RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", - Usage = new MultimodalTokenUsage - { - 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 ModelRequest - { - Model = "qwen-audio-turbo", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - Seed = 1234, - TopK = 100, - TopP = 0.81f - } - }, - new ModelResponse - { - RequestId = "6b6738bd-dd9d-9e78-958b-02574acbda44", - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent( - "这段音频在说中文,内容是\"没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网\"。") - ])) - ]), - Usage = new MultimodalTokenUsage - { - InputTokens = 786, - OutputTokens = 38, - AudioTokens = 752 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - AudioSse = new( - "multimodal-generation-audio", - new ModelRequest - { - Model = "qwen-audio-turbo", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - Seed = 1234, - TopK = 100, - TopP = 0.81f, - IncrementalOutput = true - } - }, - new ModelResponse - { - RequestId = "bb6ab962-af57-99f1-9af8-eb7016ebc18e", - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent("第一句话说了没有我互联网。") - ])) - ]), - 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 - { - public static readonly RequestSnapshot, - ModelResponse> NoSse = new( - "text-embedding", - new ModelRequest - { - Input = new TextEmbeddingInput { Texts = ["代码改变世界"] }, - Model = "text-embedding-v2", - Parameters = new TextEmbeddingParameters { TextType = "query" } - }, - new ModelResponse - { - Output = new TextEmbeddingOutput([new TextEmbeddingItem(0, [])]), - RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", - Usage = new TextEmbeddingTokenUsage(3) - }); - - public static readonly RequestSnapshot, - ModelResponse> EmbeddingClientNoSse = new( - "text-embedding", - new ModelRequest - { - Input = new TextEmbeddingInput { Texts = ["代码改变世界"] }, - Model = "text-embedding-v3", - Parameters = new TextEmbeddingParameters { Dimension = 1024 } - }, - new ModelResponse - { - Output = new TextEmbeddingOutput([new TextEmbeddingItem(0, [])]), - RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", - Usage = new TextEmbeddingTokenUsage(3) - }); - - public static readonly - RequestSnapshot, - ModelResponse> BatchNoSse = new( - "batch-text-embedding", - new ModelRequest - { - Input = new BatchGetEmbeddingsInput - { - Url = - "https://modelscope.oss-cn-beijing.aliyuncs.com/resource/text_embedding_file.txt" - }, - Model = "text-embedding-async-v2", - Parameters = new BatchGetEmbeddingsParameters { TextType = "query" } - }, - new ModelResponse - { - RequestId = "db5ce040-4548-9919-9a75-3385ee152335", - Output = new BatchGetEmbeddingsOutput - { - TaskId = "6075262c-b56d-4968-9abf-2a9784a90f3e", - TaskStatus = DashScopeTaskStatus.Pending - } - }); - } - public static class Tokenization { public static readonly @@ -1400,379 +24,6 @@ public static readonly }); } - public static class Tasks - { - public static readonly RequestSnapshot> - Unknown = new( - "get-task-unknown", - new DashScopeTask( - "85c25460-6440-91a7-b14e-2978fe60bd0f", - new BatchGetEmbeddingsOutput { TaskId = "1111", TaskStatus = DashScopeTaskStatus.Unknown })); - - public static readonly RequestSnapshot> - BatchEmbeddingSuccess = new( - "get-task-batch-text-embedding-success", - new DashScopeTask( - "0b2ebeda-a91b-948f-986a-d395cbf1d0e1", - new BatchGetEmbeddingsOutput - { - TaskId = "7408ef3d-a0be-4379-9e72-a6e95a569483", - TaskStatus = DashScopeTaskStatus.Succeeded, - Url = - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/5fc5c860/2024-11-25/c6c4456e-3c66-42ba-a52a-a16c58dda4d6_output_1732514147173.txt.gz?Expires=1732773347&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=perMNS1RdHHroUn2YnXxzTmOZtg%3D", - SubmitTime = new DateTime(2024, 11, 25, 13, 55, 46, 536), - ScheduledTime = new DateTime(2024, 11, 25, 13, 55, 46, 557), - EndTime = new DateTime(2024, 11, 25, 13, 55, 47, 446) - }, - new TextEmbeddingTokenUsage(28))); - - public static readonly RequestSnapshot> - ImageSynthesisRunning = - new( - "get-task-running", - new DashScopeTask( - "edbd4e81-d37b-97f1-9857-d7394829dd0f", - 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 DashScopeTaskMetrics(4, 0, 0) - })); - - public static readonly RequestSnapshot> - ImageSynthesisSuccess = new( - "get-task-image-synthesis-success", - new DashScopeTask( - "6662e925-4846-9afe-a3af-0d131805d378", - new ImageSynthesisOutput - { - TaskId = "9e2b6ef6-285d-4efa-8651-4dbda7d571fa", - TaskStatus = DashScopeTaskStatus.Succeeded, - SubmitTime = new DateTime(2024, 3, 1, 17, 38, 24, 817), - ScheduledTime = new DateTime(2024, 3, 1, 17, 38, 24, 831), - EndTime = new DateTime(2024, 3, 1, 17, 38, 55, 565), - Results = - [ - new ImageSynthesisResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/1d/d4/20240301/8d820c8d/4c48fa53-2907-499b-b9ac-76477fe8d299-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=bEfLmd%2BarXgZyhxcVYOWs%2BovJb8%3D"), - new ImageSynthesisResult( - "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=fdPScmRkIXyH3TSaSaWwvVjxREQ%3D"), - new ImageSynthesisResult( - "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/0f/20240301/3ab595ad/ecfe06b3-b91c-4950-a932-49ea1619a1f9-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=gNuVAt8iy4X8Nl2l3K4Gu4f0ydw%3D"), - new ImageSynthesisResult( - "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/3d/20240301/3ab595ad/3fca748e-d491-458a-bb72-73649af33209-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=Mx5TueC9I9yfDno9rjzi48opHtM%3D") - ], - TaskMetrics = new DashScopeTaskMetrics(4, 4, 0) - }, - new ImageSynthesisUsage(4))); - - public static readonly RequestSnapshot> - ImageGenerationSuccess = new( - "get-task-image-generation-success", - new DashScopeTask( - "f927c766-5079-90f8-9354-6a87d2167897", - new ImageGenerationOutput - { - TaskId = "c4f94e00-5899-431b-9579-eb1ebe686379", - TaskStatus = DashScopeTaskStatus.Succeeded, - SubmitTime = new DateTime(2024, 3, 2, 22, 22, 13, 026), - ScheduledTime = new DateTime(2024, 3, 2, 22, 22, 13, 051), - EndTime = new DateTime(2024, 3, 2, 22, 22, 21), - StartTime = new DateTime(2024, 3, 2, 22, 22, 13), - StyleIndex = 3, - ErrorCode = 0, - ErrorMessage = "Success", - Results = - [ - new ImageGenerationResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-03-02/ac5d435a-9ea9-4287-8666-e1be7bbba943/20240302222213528791_style3_jxdf6o4zwy.jpg?Expires=1709475741&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=LM26fy1Pk8rCfPzihzpUqa3Vst8%3D") - ] - }, - new ImageGenerationUsage(1))); - - public static readonly RequestSnapshot> - BackgroundGenerationSuccess = new( - "get-task-background-generation-success", - new DashScopeTask( - "8b22164d-c784-9a31-bda3-3c26259d4213", - new BackgroundGenerationOutput - { - TaskId = "b2e98d78-c79b-431c-b2d7-c7bcd54465da", - TaskStatus = DashScopeTaskStatus.Succeeded, - SubmitTime = new DateTime(2024, 3, 4, 10, 8, 57, 333), - ScheduledTime = new DateTime(2024, 3, 4, 10, 8, 57, 363), - EndTime = new DateTime(2024, 3, 4, 10, 9, 7, 727), - Results = - [ - new BackgroundGenerationResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_0_02dc0bba-8b1d-4648-8b95-eb2b92fe715d.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=OYstgSxWOl%2FOxYTLa2Mx3bi2RWw%3D"), - new BackgroundGenerationResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_1_e1af86ec-152a-4ebe-b2a0-b40a592043b2.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=p0UXTUdXfp0tFlt0K5tDsA%2Fxl1M%3D") - ], - TaskMetrics = new DashScopeTaskMetrics(2, 2, 0), - TextResults = - new BackgroundGenerationTextResult( - [ - new BackgroundGenerationTextResultUrl( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_0_4645005c-713d-4e92-9629-b12cbe5f3671.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=kmZGXc2s8P4uI%2BVrADITyrPz82U%3D"), - new BackgroundGenerationTextResultUrl( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_1_b1979b75-c553-4d9b-9c9f-80f401a0d124.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=cb1Qg%2FkIuZyI7XQqWHjP712N0ak%3D") - ], - [ - new BackgroundGenerationTextResultParams( - 0, - [ - new BackgroundGenerationTextResultLayer( - 0, - "text_mask", - 0, - 0, - 1024, - 257, - Color: "#521b08", - Opacity: 0.8f, - Radius: 0, - Gradient: new BackgroundGenerationTextResultGradient( - "linear", - "pixels", - [ - new BackgroundGenerationTextResultGradientColorStop( - "#521b0800", - 0), - new BackgroundGenerationTextResultGradientColorStop( - "#521b08ff", - 1) - ]) - { - Coords = new Dictionary - { - { "y1", 257 }, - { "x1", 0 }, - { "y2", 0 }, - { "x2", 0 } - } - }), - new BackgroundGenerationTextResultLayer( - 1, - "text", - 25, - 319, - 385, - 77, - SubType: "Title", - FontWeight: "Regular", - FontSize: 67, - Content: "分享好时光", - FontUnderLine: false, - LineHeight: 1f, - FontItalic: false, - FontColor: "#e6baa7", - TextShadow: "1px 0px #80808080", - TextStroke: "1px #fffffff0", - FontFamily: "站酷文艺体", - Alignment: "center", - FontLineThrough: false, - Direction: "horizontal", - Opacity: 1f), - new BackgroundGenerationTextResultLayer( - 2, - "text_mask", - 118, - 395, - 233, - 50, - Color: "#e6baa7", - Opacity: 1f, - Radius: 37, - BoxShadow: "2px 1px #80808080", - Gradient: new BackgroundGenerationTextResultGradient( - "linear", - "pixels", - [ - new BackgroundGenerationTextResultGradientColorStop( - "#e6baa7ff", - 0), - new BackgroundGenerationTextResultGradientColorStop( - "#e6baa7ff", - 1) - ]) - { - Coords = new Dictionary - { - { "y1", 0 }, - { "x1", 0 }, - { "y2", 50 }, - { "x2", 0 } - } - }), - new BackgroundGenerationTextResultLayer( - 3, - "text", - 118, - 395, - 233, - 50, - FontWeight: "Medium", - FontSize: 27, - Content: "只为不一样的你", - FontUnderLine: false, - LineHeight: 1f, - FontItalic: false, - SubType: "SubTitle", - FontColor: "#223629", - TextShadow: null, - FontFamily: "阿里巴巴普惠体", - Alignment: "center", - Opacity: 1f, - FontLineThrough: false, - Direction: "horizontal") - ]), - new BackgroundGenerationTextResultParams( - 1, - [ - new BackgroundGenerationTextResultLayer( - 0, - "text_mask", - 0, - 0, - 1024, - 257, - Color: "#efeae4", - Gradient: new BackgroundGenerationTextResultGradient( - "linear", - "pixels", - [ - new BackgroundGenerationTextResultGradientColorStop( - "#efeae400", - 0), - new BackgroundGenerationTextResultGradientColorStop( - "#efeae4ff", - 1) - ]) - { - Coords = new Dictionary - { - { "y1", 257 }, - { "x1", 0 }, - { "y2", 0 }, - { "x2", 0 } - } - }, - Opacity: 0.8f, - Radius: 0), - new BackgroundGenerationTextResultLayer( - 1, - "text", - 25, - 319, - 385, - 77, - SubType: "Title", - Content: "分享好时光", - FontWeight: "Regular", - FontSize: 67, - FontUnderLine: false, - LineHeight: 1f, - FontItalic: false, - FontColor: "#421f12", - TextStroke: "1px #fffffff0", - TextShadow: "0px 2px #80808080", - FontFamily: "钉钉进步体", - Alignment: "center", - Opacity: 1f, - FontLineThrough: false, - Direction: "horizontal"), - new BackgroundGenerationTextResultLayer( - 2, - "text_mask", - 118, - 395, - 233, - 50, - Color: "#421f12", - Gradient: new BackgroundGenerationTextResultGradient( - "linear", - "pixels", - [ - new BackgroundGenerationTextResultGradientColorStop( - "#421f12ff", - 0), - new BackgroundGenerationTextResultGradientColorStop( - "#421f12ff", - 1) - ]) - { - Coords = new Dictionary - { - { "y1", 0 }, - { "x1", 0 }, - { "y2", 50 }, - { "x2", 0 } - } - }, - Opacity: 1f, - Radius: 37, - BoxShadow: "0px 0px #80808080"), - new BackgroundGenerationTextResultLayer( - 3, - "text", - 118, - 395, - 233, - 50, - FontWeight: "Regular", - FontSize: 27, - Content: "只为不一样的你", - FontUnderLine: false, - LineHeight: 1, - FontItalic: false, - SubType: "SubTitle", - FontColor: "#f1eeec", - TextShadow: null, - FontFamily: "阿里巴巴普惠体", - Alignment: "center", - Opacity: 1, - FontLineThrough: false, - Direction: "horizontal") - ]) - ]) - }, - new BackgroundGenerationUsage(2))); - - public static readonly RequestSnapshot CancelCompletedTask = new( - "cancel-completed-task", - new DashScopeTaskOperationResponse( - "4d496c94-1389-9ca9-a92a-3e732f675686", - "UnsupportedOperation", - "Failed to cancel the task, please confirm if the task is in PENDING status.")); - - public static readonly RequestSnapshot ListTasks = new( - "list-task", - new DashScopeTaskList( - "fcb29ae5-a352-9e7b-901c-e53525376cde", - [ - new DashScopeTaskListItem( - "42677", - "1493478651020171", - "1493478651020171", - 1709260684485, - 1709260684527, - 1709260685184, - "cn-beijing", - "db5ce040-4548-9919-9a75-3385ee152335", - DashScopeTaskStatus.Succeeded, - "6075262c-b56d-4968-9abf-2a9784a90f3e", - "apikey:v1:embeddings:text-embedding:text-embedding:text-embedding-async-v2", - "text-embedding-async-v2") - ], - 1, - 1, - 1, - 10)); - } - public static class ImageSynthesis { public static readonly From 681baa83935e48880b13a8d894f0d79ecc51c167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 19:28:34 +0800 Subject: [PATCH 05/35] test: add session id based conversation test --- .../ApplicationRagOptions.cs | 4 +- .../ApplicationSerializationTests.cs | 18 ++++++ ...eration-session-id-nosse.request.body.json | 19 ++++++ ...ration-session-id-nosse.request.header.txt | 8 +++ ...eration-session-id-nosse.response.body.txt | 1 + ...ation-session-id-nosse.response.header.txt | 15 +++++ .../Utils/Snapshots.Application.cs | 61 +++++++++++++++++-- 7 files changed, 119 insertions(+), 7 deletions(-) create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt diff --git a/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs index abf0d5b..f349c5e 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs @@ -20,7 +20,7 @@ public class ApplicationRagOptions /// /// Metadata filter for non-structured files. /// - public JsonElement? MetadataFilter { get; set; } + public Dictionary? MetadataFilter { get; set; } /// /// Tag filter for non-structured files. @@ -30,7 +30,7 @@ public class ApplicationRagOptions /// /// Filter for structured files. /// - public JsonElement? StructuredFilter { get; set; } + public Dictionary? StructuredFilter { get; set; } /// /// File ids for current session. diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs index 9b06b37..67a3866 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs @@ -64,4 +64,22 @@ public async Task SingleCompletion_TextSse_SuccessAsync() o => o.Excluding(y => y.Output.Text).Excluding(x => x.Output.Thoughts)); text.Should().Be(testCase.ResponseModel.Output.Text); } + + [Fact] + public async Task ConversationCompletion_SessionIdNoSse_SuccessAsync() + { + // Arrange + const bool sse = false; + var testCase = Snapshots.Application.ConversationSessionIdNoSse; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var response = await client.GetApplicationResponseAsync("anyId", testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + response.Should().BeEquivalentTo(testCase.ResponseModel); + } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json new file mode 100644 index 0000000..2d07b49 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json @@ -0,0 +1,19 @@ +{ + "input": { + "prompt": "总结一下第一本书的内容", + "session_id": "9995da2046a04b448dc5a562563f4835" + }, + "parameters": { + "has_thoughts": true, + "top_k": 100, + "top_p": 0.8, + "seed": 1234, + "temperature": 0.85, + "rag_options": { + "pipeline_ids": ["ll6yfcnxjg"], + "metadata_filter": { + "docType": "电子书" + } + } + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt new file mode 100644 index 0000000..55827d8 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/apps/010aa085cc9943268731861c9511bb0c/completion 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: 471 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt new file mode 100644 index 0000000..7148a90 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"thoughts":[{"action_input_stream":"{}","action_type":"agentRag","observation":"[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Refactoring a Test...xlvPARTI.The Narratives····.1Chapter 1. A Brief Tour3About This Chapter3The Simplest Test Automation Strategy ThatCould Possibly Work3Development Process4Customer Tests5Unit Tests . . .Design for TestabilityTest Organization···What's Next?Chapter 2. Test Smells . . ..·····9About This Chapter9An Introduction to Test Smells..9What's a Test Smell? . . ...10Kinds of Test Smells ...10What to Do about Smells?..11A Catalog of Smells·...12The Project Smells...12The Behavior Smells. . ...13The Code Smells..16What's Next?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_27\",\"images\":[],\"referenceIndex\":1,\"score\":0.5722247362136841,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Delegated Setup. ...411Creation Method...415Implicit Setup...424Prebuilt Fixture...429Lazy Setup...435Suite Fixture Setup ...。。。441Setup Decorator...447Chained Tests...454Chapter 21. Result Verification Patterns p·...461State Verification...462Behavior Verification...468Custom Assertion...474Delta Assertion...485Guard Assertion...490Unfinished Test Assertion...494Chapter 22. Fixture Teardown Patterns...499Garbage-Collected Teardown...500CONTENTSAutomated Teardown...503In-line Teardown...509Implicit Teardown...516Chapter 23. Test Double Patterns ...521Test Double...522Test Stub...529\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_40\",\"images\":[],\"referenceIndex\":2,\"score\":0.5684536695480347,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":3,\"score\":0.5677477717399597,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":4,\"score\":0.5674441456794739,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":5,\"score\":0.5672414302825928,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]","action_name":"知识检索","action":"rag","arguments":"{}"},{"thought":"好的,用户让我总结一下第一本书的内容,也就是《xUnit Test Patterns》。首先,我需要回顾知识库中的相关文档。用户之前已经询问过xUnit相关的书籍,现在需要更深入的信息。\n\n首先,知识库中有多个条目提到了这本书,每个条目都引用了书中的不同章节和内容。例如,文档[1]提到了测试自动化策略、开发流程、客户测试、单元测试和测试组织。文档[2]和[3]提到了具体的模式,如Delegated Setup、Creation Method、Fixture管理、测试验证模式等。文档[4]和[5]讨论了数据库测试、测试自动化路线图以及结果验证的方法。\n\n用户的问题是要总结第一本书的内容,即《xUnit Test Patterns》。根据知识库中的信息,这本书主要围绕测试模式和最佳实践展开,涵盖测试结构、组织、验证、固件管理等方面。需要将这些分散的信息整合起来,形成一个结构化的总结。\n\n接下来,我需要确定这本书的核心主题。从各个文档的正文来看,书中讨论了测试代码的坏味道(Test Smells)、重构测试代码的方法、测试自动化策略、测试固件的管理(如Setup和Teardown模式)、测试验证模式(如状态验证和行为验证)、测试替身(Test Doubles)如Test Stub等。此外,还涉及测试组织结构、测试用例类设计、数据库测试的策略和挑战。\n\n用户可能希望了解这本书的整体框架和关键点,而不仅仅是零散的章节内容。因此,总结时需要分模块或主题来组织信息,例如核心概念、测试模式、实践策略、高级主题等。同时,要突出书中的核心贡献,如对测试模式的分类和解决方案。\n\n需要注意的是,知识库中的信息可能不完整,但可以基于现有内容进行合理推断。例如,文档[1]提到了测试坏味道的分类,文档[2]和[5]详细描述了不同的测试模式和验证方法,文档[3]和[4]讨论了测试组织和数据库测试的挑战。结合这些,可以推断该书系统性地介绍了如何编写可维护、高效的测试代码,解决测试中的常见问题。\n\n最后,需要确保总结简洁明了,涵盖主要章节和关键概念,让用户快速了解这本书的价值和内容结构。可能还需要指出这本书适合的读者群体,如测试工程师、开发人员以及需要提高测试代码质量的团队。","action_type":"reasoning","response":"好的,用户让我总结一下第一本书的内容,也就是《xUnit Test Patterns》。首先,我需要回顾知识库中的相关文档。用户之前已经询问过xUnit相关的书籍,现在需要更深入的信息。\n\n首先,知识库中有多个条目提到了这本书,每个条目都引用了书中的不同章节和内容。例如,文档[1]提到了测试自动化策略、开发流程、客户测试、单元测试和测试组织。文档[2]和[3]提到了具体的模式,如Delegated Setup、Creation Method、Fixture管理、测试验证模式等。文档[4]和[5]讨论了数据库测试、测试自动化路线图以及结果验证的方法。\n\n用户的问题是要总结第一本书的内容,即《xUnit Test Patterns》。根据知识库中的信息,这本书主要围绕测试模式和最佳实践展开,涵盖测试结构、组织、验证、固件管理等方面。需要将这些分散的信息整合起来,形成一个结构化的总结。\n\n接下来,我需要确定这本书的核心主题。从各个文档的正文来看,书中讨论了测试代码的坏味道(Test Smells)、重构测试代码的方法、测试自动化策略、测试固件的管理(如Setup和Teardown模式)、测试验证模式(如状态验证和行为验证)、测试替身(Test Doubles)如Test Stub等。此外,还涉及测试组织结构、测试用例类设计、数据库测试的策略和挑战。\n\n用户可能希望了解这本书的整体框架和关键点,而不仅仅是零散的章节内容。因此,总结时需要分模块或主题来组织信息,例如核心概念、测试模式、实践策略、高级主题等。同时,要突出书中的核心贡献,如对测试模式的分类和解决方案。\n\n需要注意的是,知识库中的信息可能不完整,但可以基于现有内容进行合理推断。例如,文档[1]提到了测试坏味道的分类,文档[2]和[5]详细描述了不同的测试模式和验证方法,文档[3]和[4]讨论了测试组织和数据库测试的挑战。结合这些,可以推断该书系统性地介绍了如何编写可维护、高效的测试代码,解决测试中的常见问题。\n\n最后,需要确保总结简洁明了,涵盖主要章节和关键概念,让用户快速了解这本书的价值和内容结构。可能还需要指出这本书适合的读者群体,如测试工程师、开发人员以及需要提高测试代码质量的团队。","action_name":"思考过程","action":"reasoning"}],"finish_reason":"stop","session_id":"9995da2046a04b448dc5a562563f4835","text":"根据知识库中提供的《xUnit Test Patterns》内容片段,以下是其核心内容的总结:\n\n---\n\n### **《xUnit Test Patterns: Refactoring Test Code》核心内容**\n1. **核心目标** \n 系统化解决单元测试中的常见问题,提供可复用的测试模式,帮助编写**可维护、高效、可靠**的测试代码。\n\n2. **关键主题** \n - **测试代码重构** \n - 识别测试代码的\"坏味道\"(Test Smells),例如冗长的测试方法、重复的测试逻辑、脆弱的依赖等。\n - 提出重构策略,如使用 **Creation Method** 简化对象构造、**Implicit Setup** 隐式初始化测试夹具等。\n - **测试自动化策略** \n - 强调\"测试即代码\"(Test as Code),通过设计模式(如 **Test Double**、**Test Stub**)隔离外部依赖。\n - 探讨测试与数据库交互的挑战(如事务管理、数据污染),并给出解决方案(如 **Fresh Fixture** 模式)。\n - **测试验证模式** \n - **State Verification**:验证被测对象的状态变化(如属性值)。\n - **Behavior Verification**:验证对象间的交互行为(如方法调用次数)。\n - **Custom Assertion**:通过自定义断言提高测试可读性。\n - **测试组织结构** \n - 按类、功能或夹具组织测试用例(如 **Testcase Class per Fixture**)。\n - 管理测试套件(Test Suites)和测试依赖关系。\n\n3. **典型模式示例** \n - **Fixture 管理** \n - **Delegated Setup**:将夹具构造逻辑委托给辅助方法。\n - **Prebuilt Fixture**:预构建共享夹具以提升性能。\n - **结果验证** \n - **Delta Assertion**:仅验证关键变化值,避免全量断言。\n - **Guard Assertion**:前置条件检查,防止测试误报。\n - **测试替身(Test Doubles)** \n - **Test Stub**:模拟外部依赖的返回值。\n - **Mock Object**:验证对象间的交互是否符合预期。\n\n4. **实践指导** \n - 提出从\"Happy Path\"(正常流程)到复杂场景的测试演进路线。\n - 强调测试的**独立性**(避免测试间依赖)和**自检能力**(无需人工验证结果)。\n\n---\n\n### **适用场景**\n- 开发人员需解决测试代码**臃肿、脆弱或低效**的问题。\n- 团队需建立**统一、可扩展**的自动化测试规范。\n- 涉及**数据库、外部服务**等复杂依赖的测试设计。\n\n书中内容以模式目录形式呈现,可直接作为工具手册使用。"},"usage":{"models":[{"output_tokens":1081,"model_id":"deepseek-r1","input_tokens":1283}]},"request_id":"703ba252-43c0-9a05-a656-1c2bf03d21dc"} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt new file mode 100644 index 0000000..974d269 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding +content-type: application/json +x-request-id: 703ba252-43c0-9a05-a656-1c2bf03d21dc +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 50805 +req-arrive-time: 1742117445974 +resp-start-time: 1742117496779 +x-envoy-upstream-service-time: 50796 +content-encoding: gzip +date: Sun, 16 Mar 2025 09:31:36 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs index f26b007..22097a9 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs @@ -113,11 +113,7 @@ public static class Application Seed = 1234, Temperature = 0.85f, IncrementalOutput = true, - RagOptions = new ApplicationRagOptions() - { - PipelineIds = ["thie5bysoj"], - Tags = ["xUnit"] - } + RagOptions = new ApplicationRagOptions() { PipelineIds = ["thie5bysoj"], Tags = ["xUnit"] } } }, new ApplicationResponse( @@ -213,5 +209,60 @@ public static class Application ], null), new ApplicationUsage([new ApplicationModelUsage("deepseek-r1", 1129, 1126)]))); + + public static readonly RequestSnapshot ConversationSessionIdNoSse = + new( + "application-conversation-generation-session-id", + new ApplicationRequest() + { + Input = + new ApplicationInput() + { + Prompt = "总结一下第一本书的内容", SessionId = "9995da2046a04b448dc5a562563f4835" + }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["ll6yfcnxjg"], + MetadataFilter = new Dictionary { { "docType", "电子书" } } + }, + HasThoughts = true + } + }, + new ApplicationResponse( + "703ba252-43c0-9a05-a656-1c2bf03d21dc", + new ApplicationOutput( + "根据知识库中提供的《xUnit Test Patterns》内容片段,以下是其核心内容的总结:\n\n---\n\n### **《xUnit Test Patterns: Refactoring Test Code》核心内容**\n1. **核心目标** \n 系统化解决单元测试中的常见问题,提供可复用的测试模式,帮助编写**可维护、高效、可靠**的测试代码。\n\n2. **关键主题** \n - **测试代码重构** \n - 识别测试代码的\"坏味道\"(Test Smells),例如冗长的测试方法、重复的测试逻辑、脆弱的依赖等。\n - 提出重构策略,如使用 **Creation Method** 简化对象构造、**Implicit Setup** 隐式初始化测试夹具等。\n - **测试自动化策略** \n - 强调\"测试即代码\"(Test as Code),通过设计模式(如 **Test Double**、**Test Stub**)隔离外部依赖。\n - 探讨测试与数据库交互的挑战(如事务管理、数据污染),并给出解决方案(如 **Fresh Fixture** 模式)。\n - **测试验证模式** \n - **State Verification**:验证被测对象的状态变化(如属性值)。\n - **Behavior Verification**:验证对象间的交互行为(如方法调用次数)。\n - **Custom Assertion**:通过自定义断言提高测试可读性。\n - **测试组织结构** \n - 按类、功能或夹具组织测试用例(如 **Testcase Class per Fixture**)。\n - 管理测试套件(Test Suites)和测试依赖关系。\n\n3. **典型模式示例** \n - **Fixture 管理** \n - **Delegated Setup**:将夹具构造逻辑委托给辅助方法。\n - **Prebuilt Fixture**:预构建共享夹具以提升性能。\n - **结果验证** \n - **Delta Assertion**:仅验证关键变化值,避免全量断言。\n - **Guard Assertion**:前置条件检查,防止测试误报。\n - **测试替身(Test Doubles)** \n - **Test Stub**:模拟外部依赖的返回值。\n - **Mock Object**:验证对象间的交互是否符合预期。\n\n4. **实践指导** \n - 提出从\"Happy Path\"(正常流程)到复杂场景的测试演进路线。\n - 强调测试的**独立性**(避免测试间依赖)和**自检能力**(无需人工验证结果)。\n\n---\n\n### **适用场景**\n- 开发人员需解决测试代码**臃肿、脆弱或低效**的问题。\n- 团队需建立**统一、可扩展**的自动化测试规范。\n- 涉及**数据库、外部服务**等复杂依赖的测试设计。\n\n书中内容以模式目录形式呈现,可直接作为工具手册使用。", + "stop", + "9995da2046a04b448dc5a562563f4835", + [ + new ApplicationOutputThought( + null, + "agentRag", + "知识检索", + "rag", + "{}", + null, + "[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Refactoring a Test...xlvPARTI.The Narratives····.1Chapter 1. A Brief Tour3About This Chapter3The Simplest Test Automation Strategy ThatCould Possibly Work3Development Process4Customer Tests5Unit Tests . . .Design for TestabilityTest Organization···What's Next?Chapter 2. Test Smells . . ..·····9About This Chapter9An Introduction to Test Smells..9What's a Test Smell? . . ...10Kinds of Test Smells ...10What to Do about Smells?..11A Catalog of Smells·...12The Project Smells...12The Behavior Smells. . ...13The Code Smells..16What's Next?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_27\",\"images\":[],\"referenceIndex\":1,\"score\":0.5722247362136841,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Delegated Setup. ...411Creation Method...415Implicit Setup...424Prebuilt Fixture...429Lazy Setup...435Suite Fixture Setup ...。。。441Setup Decorator...447Chained Tests...454Chapter 21. Result Verification Patterns p·...461State Verification...462Behavior Verification...468Custom Assertion...474Delta Assertion...485Guard Assertion...490Unfinished Test Assertion...494Chapter 22. Fixture Teardown Patterns...499Garbage-Collected Teardown...500CONTENTSAutomated Teardown...503In-line Teardown...509Implicit Teardown...516Chapter 23. Test Double Patterns ...521Test Double...522Test Stub...529\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_40\",\"images\":[],\"referenceIndex\":2,\"score\":0.5684536695480347,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":3,\"score\":0.5677477717399597,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":4,\"score\":0.5674441456794739,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"电子书\\\"]\\n关键字:[\\\"xUnit\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_ll6yfcnxjg_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":5,\"score\":0.5672414302825928,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]", + null, + "{}"), + new ApplicationOutputThought( + "好的,用户让我总结一下第一本书的内容,也就是《xUnit Test Patterns》。首先,我需要回顾知识库中的相关文档。用户之前已经询问过xUnit相关的书籍,现在需要更深入的信息。\n\n首先,知识库中有多个条目提到了这本书,每个条目都引用了书中的不同章节和内容。例如,文档[1]提到了测试自动化策略、开发流程、客户测试、单元测试和测试组织。文档[2]和[3]提到了具体的模式,如Delegated Setup、Creation Method、Fixture管理、测试验证模式等。文档[4]和[5]讨论了数据库测试、测试自动化路线图以及结果验证的方法。\n\n用户的问题是要总结第一本书的内容,即《xUnit Test Patterns》。根据知识库中的信息,这本书主要围绕测试模式和最佳实践展开,涵盖测试结构、组织、验证、固件管理等方面。需要将这些分散的信息整合起来,形成一个结构化的总结。\n\n接下来,我需要确定这本书的核心主题。从各个文档的正文来看,书中讨论了测试代码的坏味道(Test Smells)、重构测试代码的方法、测试自动化策略、测试固件的管理(如Setup和Teardown模式)、测试验证模式(如状态验证和行为验证)、测试替身(Test Doubles)如Test Stub等。此外,还涉及测试组织结构、测试用例类设计、数据库测试的策略和挑战。\n\n用户可能希望了解这本书的整体框架和关键点,而不仅仅是零散的章节内容。因此,总结时需要分模块或主题来组织信息,例如核心概念、测试模式、实践策略、高级主题等。同时,要突出书中的核心贡献,如对测试模式的分类和解决方案。\n\n需要注意的是,知识库中的信息可能不完整,但可以基于现有内容进行合理推断。例如,文档[1]提到了测试坏味道的分类,文档[2]和[5]详细描述了不同的测试模式和验证方法,文档[3]和[4]讨论了测试组织和数据库测试的挑战。结合这些,可以推断该书系统性地介绍了如何编写可维护、高效的测试代码,解决测试中的常见问题。\n\n最后,需要确保总结简洁明了,涵盖主要章节和关键概念,让用户快速了解这本书的价值和内容结构。可能还需要指出这本书适合的读者群体,如测试工程师、开发人员以及需要提高测试代码质量的团队。", + "reasoning", + "思考过程", + "reasoning", + null, + null, + null, + "好的,用户让我总结一下第一本书的内容,也就是《xUnit Test Patterns》。首先,我需要回顾知识库中的相关文档。用户之前已经询问过xUnit相关的书籍,现在需要更深入的信息。\n\n首先,知识库中有多个条目提到了这本书,每个条目都引用了书中的不同章节和内容。例如,文档[1]提到了测试自动化策略、开发流程、客户测试、单元测试和测试组织。文档[2]和[3]提到了具体的模式,如Delegated Setup、Creation Method、Fixture管理、测试验证模式等。文档[4]和[5]讨论了数据库测试、测试自动化路线图以及结果验证的方法。\n\n用户的问题是要总结第一本书的内容,即《xUnit Test Patterns》。根据知识库中的信息,这本书主要围绕测试模式和最佳实践展开,涵盖测试结构、组织、验证、固件管理等方面。需要将这些分散的信息整合起来,形成一个结构化的总结。\n\n接下来,我需要确定这本书的核心主题。从各个文档的正文来看,书中讨论了测试代码的坏味道(Test Smells)、重构测试代码的方法、测试自动化策略、测试固件的管理(如Setup和Teardown模式)、测试验证模式(如状态验证和行为验证)、测试替身(Test Doubles)如Test Stub等。此外,还涉及测试组织结构、测试用例类设计、数据库测试的策略和挑战。\n\n用户可能希望了解这本书的整体框架和关键点,而不仅仅是零散的章节内容。因此,总结时需要分模块或主题来组织信息,例如核心概念、测试模式、实践策略、高级主题等。同时,要突出书中的核心贡献,如对测试模式的分类和解决方案。\n\n需要注意的是,知识库中的信息可能不完整,但可以基于现有内容进行合理推断。例如,文档[1]提到了测试坏味道的分类,文档[2]和[5]详细描述了不同的测试模式和验证方法,文档[3]和[4]讨论了测试组织和数据库测试的挑战。结合这些,可以推断该书系统性地介绍了如何编写可维护、高效的测试代码,解决测试中的常见问题。\n\n最后,需要确保总结简洁明了,涵盖主要章节和关键概念,让用户快速了解这本书的价值和内容结构。可能还需要指出这本书适合的读者群体,如测试工程师、开发人员以及需要提高测试代码质量的团队。", + null) + ], + null), + new ApplicationUsage([new ApplicationModelUsage("deepseek-r1", 1283, 1081)]))); } } From c761b8fa163f3328e68cea8d360365c2d6114f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 20:45:03 +0800 Subject: [PATCH 06/35] test: add message conversation test --- .../ApplicationRagOptions.cs | 2 +- .../ApplicationSerializationTests.cs | 18 ++++++ ...generation-message-nosse.request.body.json | 35 +++++++++++ ...eneration-message-nosse.request.header.txt | 8 +++ ...generation-message-nosse.response.body.txt | 1 + ...neration-message-nosse.response.header.txt | 15 +++++ .../Utils/Snapshots.Application.cs | 60 +++++++++++++++++++ 7 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.header.txt diff --git a/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs index f349c5e..3d28f7d 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs @@ -30,7 +30,7 @@ public class ApplicationRagOptions /// /// Filter for structured files. /// - public Dictionary? StructuredFilter { get; set; } + public Dictionary? StructuredFilter { get; set; } /// /// File ids for current session. diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs index 67a3866..73ca73c 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs @@ -82,4 +82,22 @@ public async Task ConversationCompletion_SessionIdNoSse_SuccessAsync() Arg.Any()); response.Should().BeEquivalentTo(testCase.ResponseModel); } + + [Fact] + public async Task ConversationCompletion_MessageNoSse_SuccessAsync() + { + // Arrange + const bool sse = false; + var testCase = Snapshots.Application.ConversationMessageNoSse; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var response = await client.GetApplicationResponseAsync("anyId", testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + response.Should().BeEquivalentTo(testCase.ResponseModel); + } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.body.json new file mode 100644 index 0000000..f553890 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.body.json @@ -0,0 +1,35 @@ +{ + "input": { + "messages": [ + { + "role": "system", + "content": "You are a helpful assistant." + }, + { + "role": "user", + "content": "你是谁?" + }, + { + "role": "assistant", + "content": "我是阿里云开发的大规模语言模型,我叫通义千问。" + }, + { + "role": "user", + "content": "哪些人的主食偏好是米饭?" + } + ] + }, + "parameters": { + "has_thoughts": true, + "top_k": 100, + "top_p": 0.8, + "seed": 1234, + "temperature": 0.85, + "rag_options": { + "pipeline_ids": ["e6md69132k"], + "structured_filter": { + "年龄": 14 + } + } + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.header.txt new file mode 100644 index 0000000..cdf4d96 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/apps/5ccc140108fd4b2ea5e6101fbada7583/completion 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: 914 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.body.txt new file mode 100644 index 0000000..2c53618 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"thoughts":[{"action_input_stream":"{}","action_type":"agentRag","observation":"[{\"content\":\"【文档名】:用户食物偏好\\n名字:小明\\n主食偏好:面食\\n年龄:14\\n\",\"dataId\":\"table_df4b06e8931545b4b0a65e011087c197_10207234_1\",\"dataName\":\"用户食物偏好\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_e6md69132k_table_df4b06e8931545b4b0a65e011087c197_10207234_1\",\"referenceIndex\":1,\"score\":0.2185690850019455,\"webSearch\":false}]","action_name":"知识检索","action":"rag","arguments":"{}"},{"action_input_stream":"{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"哪些人的主食偏好是米饭?\"}","action_type":"api","observation":"[]","action_name":"长期记忆检索","action":"memory","arguments":"{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"哪些人的主食偏好是米饭?\"}"}],"finish_reason":"stop","session_id":"9e2cf8c81f9a4fbe900a1f04b8522244","text":"米饭作为主食,深受许多国家和地区人们的喜爱。以下是一些以米饭为主食的群体:\n\n1. **中国人**:尤其在南方地区,米饭是大多数家庭的主要食物。从广东、福建到四川、云南,米饭搭配各种菜肴构成了日常饮食的重要部分。\n\n2. **日本人**:日本料理中,白米饭占据核心地位,无论是便当中的小碗饭还是寿司的基础,都体现了米饭在日本饮食文化中的重要性。\n\n3. **韩国人**:韩国家庭餐桌上的“石锅拌饭”、“紫菜包饭”等经典菜品,反映了米饭在韩国饮食习惯里的不可或缺。\n\n4. **东南亚各国居民**(如泰国、越南、菲律宾、印尼等):这些地区的传统美食几乎都离不开米饭,像泰国香米更是闻名全球,成为该国饮食文化的象征之一。\n\n5. **印度及南亚次大陆部分地区人群**:虽然面饼(Roti/Naan)也很受欢迎,但米饭特别是与咖喱一起食用时,同样是众多印度家庭及其他南亚国家(如孟加拉国、斯里兰卡等)的重要主食选择。\n\n6. **中东部分国家的人们**:尽管面包可能是更普遍的选择,但在一些特定场合或日常饮食中,例如搭配烤肉、炖菜时,米饭同样被广泛使用。\n\n总体而言,由于其易于种植、营养丰富且能够很好地与其他食材结合的特点,米饭成为了上述地区人们世代相传的主要食物来源之一。"},"usage":{"models":[{"output_tokens":311,"model_id":"qwen-plus","input_tokens":344}]},"request_id":"d42335b3-fcb2-9d11-b651-29562ac02abe"} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.header.txt new file mode 100644 index 0000000..61085a5 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding +content-type: application/json +x-request-id: d42335b3-fcb2-9d11-b651-29562ac02abe +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 8647 +req-arrive-time: 1742127970039 +resp-start-time: 1742127978686 +x-envoy-upstream-service-time: 8640 +content-encoding: gzip +date: Sun, 16 Mar 2025 12:26:18 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs index 22097a9..bc9e58c 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs @@ -264,5 +264,65 @@ public static class Application ], null), new ApplicationUsage([new ApplicationModelUsage("deepseek-r1", 1283, 1081)]))); + + public static readonly RequestSnapshot ConversationMessageNoSse = + new( + "application-conversation-generation-message", + new ApplicationRequest() + { + Input = new ApplicationInput() + { + Messages = + [ + ApplicationMessage.System("You are a helpful assistant."), + ApplicationMessage.User("你是谁?"), + ApplicationMessage.Assistant("我是阿里云开发的大规模语言模型,我叫通义千问。"), + ApplicationMessage.User("哪些人的主食偏好是米饭?"), + ], + }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["e6md69132k"], + StructuredFilter = new Dictionary { { "年龄", 14 } } + }, + HasThoughts = true + } + }, + new ApplicationResponse( + "d42335b3-fcb2-9d11-b651-29562ac02abe", + new ApplicationOutput( + "米饭作为主食,深受许多国家和地区人们的喜爱。以下是一些以米饭为主食的群体:\n\n1. **中国人**:尤其在南方地区,米饭是大多数家庭的主要食物。从广东、福建到四川、云南,米饭搭配各种菜肴构成了日常饮食的重要部分。\n\n2. **日本人**:日本料理中,白米饭占据核心地位,无论是便当中的小碗饭还是寿司的基础,都体现了米饭在日本饮食文化中的重要性。\n\n3. **韩国人**:韩国家庭餐桌上的“石锅拌饭”、“紫菜包饭”等经典菜品,反映了米饭在韩国饮食习惯里的不可或缺。\n\n4. **东南亚各国居民**(如泰国、越南、菲律宾、印尼等):这些地区的传统美食几乎都离不开米饭,像泰国香米更是闻名全球,成为该国饮食文化的象征之一。\n\n5. **印度及南亚次大陆部分地区人群**:虽然面饼(Roti/Naan)也很受欢迎,但米饭特别是与咖喱一起食用时,同样是众多印度家庭及其他南亚国家(如孟加拉国、斯里兰卡等)的重要主食选择。\n\n6. **中东部分国家的人们**:尽管面包可能是更普遍的选择,但在一些特定场合或日常饮食中,例如搭配烤肉、炖菜时,米饭同样被广泛使用。\n\n总体而言,由于其易于种植、营养丰富且能够很好地与其他食材结合的特点,米饭成为了上述地区人们世代相传的主要食物来源之一。", + "stop", + "9e2cf8c81f9a4fbe900a1f04b8522244", + [ + new ApplicationOutputThought( + null, + "agentRag", + "知识检索", + "rag", + "{}", + null, + "[{\"content\":\"【文档名】:用户食物偏好\\n名字:小明\\n主食偏好:面食\\n年龄:14\\n\",\"dataId\":\"table_df4b06e8931545b4b0a65e011087c197_10207234_1\",\"dataName\":\"用户食物偏好\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_e6md69132k_table_df4b06e8931545b4b0a65e011087c197_10207234_1\",\"referenceIndex\":1,\"score\":0.2185690850019455,\"webSearch\":false}]", + null, + "{}"), + new ApplicationOutputThought( + null, + "api", + "长期记忆检索", + "memory", + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"哪些人的主食偏好是米饭?\"}", + null, + "[]", + null, + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"哪些人的主食偏好是米饭?\"}") + ], + null), + new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 344, 311)]))); } } From 56739b17d080cb223547fb370f2620b033280770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 21:11:41 +0800 Subject: [PATCH 07/35] test: add memory id tests --- .../ApplicationSerializationTests.cs | 18 +++++++++ ...n-text-with-memory-nosse.request.body.json | 13 ++++++ ...-text-with-memory-nosse.request.header.txt | 8 ++++ ...n-text-with-memory-nosse.response.body.txt | 1 + ...text-with-memory-nosse.response.header.txt | 15 +++++++ .../Utils/Snapshots.Application.cs | 40 +++++++++++++++++++ 6 files changed, 95 insertions(+) create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs index 73ca73c..67dd03f 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs @@ -100,4 +100,22 @@ public async Task ConversationCompletion_MessageNoSse_SuccessAsync() Arg.Any()); response.Should().BeEquivalentTo(testCase.ResponseModel); } + + [Fact] + public async Task SingleCompletion_MemoryNoSse_SuccessAsync() + { + // Arrange + const bool sse = false; + var testCase = Snapshots.Application.SinglePromptWithMemoryNoSse; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var response = await client.GetApplicationResponseAsync("anyId", testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + response.Should().BeEquivalentTo(testCase.ResponseModel); + } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json new file mode 100644 index 0000000..b4321ca --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json @@ -0,0 +1,13 @@ +{ + "input": { + "prompt": "我爱吃面食", + "memory_id": "ffd8be2352d84c6b9350e91c865b512e" + }, + "parameters": { + "has_thoughts": true, + "top_k": 100, + "top_p": 0.8, + "seed": 1234, + "temperature": 0.85 + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt new file mode 100644 index 0000000..7548692 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/apps/5ccc140108fd4b2ea5e6101fbada7583/completion 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: 280 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt new file mode 100644 index 0000000..e8d1965 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"thoughts":[{"action_input_stream":"{}","action_type":"agentRag","observation":"[]","action_name":"知识检索","action":"rag","arguments":"{}"},{"action_input_stream":"{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"我爱吃面食\"}","action_type":"api","observation":"[\"[2025-3-16 20:47:40 周日] 用户喜欢吃面食。\"]","action_name":"长期记忆检索","action":"memory","arguments":"{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"我爱吃面食\"}"}],"finish_reason":"stop","session_id":"cd395cb8d4604db786a14555fdcffa1a","text":"那您一定会对面条、馒头或者饺子这些美食很感兴趣呢!如果您有特定的面食问题或者需要推荐相关的菜品,可以告诉我,我很乐意为您提供帮助[1]。"},"usage":{"models":[{"output_tokens":43,"model_id":"qwen-plus","input_tokens":1201}]},"request_id":"8cea84fe-2770-91b0-a6d1-e1e8ef176fa6"} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt new file mode 100644 index 0000000..c6a1483 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding +content-type: application/json +x-request-id: 8cea84fe-2770-91b0-a6d1-e1e8ef176fa6 +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 2516 +req-arrive-time: 1742129333100 +resp-start-time: 1742129335617 +x-envoy-upstream-service-time: 2508 +content-encoding: gzip +date: Sun, 16 Mar 2025 12:48:55 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs index bc9e58c..126cb11 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs @@ -210,6 +210,46 @@ public static class Application null), new ApplicationUsage([new ApplicationModelUsage("deepseek-r1", 1129, 1126)]))); + public static readonly RequestSnapshot SinglePromptWithMemoryNoSse = + new( + "application-single-generation-text-with-memory", + new ApplicationRequest() + { + Input = new ApplicationInput() + { + Prompt = "我爱吃面食", MemoryId = "ffd8be2352d84c6b9350e91c865b512e" + }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + HasThoughts = true + } + }, + new ApplicationResponse( + "8cea84fe-2770-91b0-a6d1-e1e8ef176fa6", + new ApplicationOutput( + "那您一定会对面条、馒头或者饺子这些美食很感兴趣呢!如果您有特定的面食问题或者需要推荐相关的菜品,可以告诉我,我很乐意为您提供帮助[1]。", + "stop", + "cd395cb8d4604db786a14555fdcffa1a", + [ + new ApplicationOutputThought(null, "agentRag", "知识检索", "rag", "{}", null, "[]", null, "{}"), + new ApplicationOutputThought( + null, + "api", + "长期记忆检索", + "memory", + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"我爱吃面食\"}", + null, + "[\"[2025-3-16 20:47:40 周日] 用户喜欢吃面食。\"]", + null, + "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"我爱吃面食\"}") + ], + null), + new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 1201, 43)]))); + public static readonly RequestSnapshot ConversationSessionIdNoSse = new( "application-conversation-generation-session-id", From 8d004d5587466eebb460f35daf811a4000ae89ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 21:22:09 +0800 Subject: [PATCH 08/35] refactor: change inherit layout --- src/Cnblogs.DashScope.Core/ApplicationInput.cs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Cnblogs.DashScope.Core/ApplicationInput.cs b/src/Cnblogs.DashScope.Core/ApplicationInput.cs index ffbd969..85f1f0c 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationInput.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationInput.cs @@ -3,7 +3,9 @@ /// /// Inputs for application call. /// -public class ApplicationInput +/// Type of the BizContent. +public class ApplicationInput + where TBizContent : class { /// /// The prompt for model to generate response upon. Optional when has been set. @@ -32,17 +34,14 @@ public class ApplicationInput /// List of image urls for inputs. /// public IEnumerable? ImageList { get; set; } -} -/// -/// Inputs for application call. -/// -/// User defined custom content. -public class ApplicationInput : ApplicationInput - where TBizContent : class -{ /// /// User defined content. /// public TBizContent? Content { get; set; } = null; } + +/// +/// Inputs for application call. +/// +public class ApplicationInput : ApplicationInput>; From 7287c7df1ccb7ae09e8ed9b8c3a2cc08eff049e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 21:36:21 +0800 Subject: [PATCH 09/35] refactor: add generic methods --- .../ApplicationRequest.cs | 11 ++++++-- .../DashScopeClientCore.cs | 22 ++++++++++++++- .../IDashScopeClient.cs | 28 +++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs index 6533a30..b6e4130 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs @@ -3,15 +3,22 @@ /// /// Request body for an application all. /// -public class ApplicationRequest +/// Type of the biz_content +public class ApplicationRequest + where TBizContent : class { /// /// Content of this call. /// - public required ApplicationInput Input { get; init; } + public required ApplicationInput Input { get; init; } /// /// Optional configurations. /// public required ApplicationParameters? Parameters { get; init; } } + +/// +/// Request body for an application call with dictionary biz_content. +/// +public class ApplicationRequest : ApplicationRequest>; diff --git a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs index 43eebf4..8584637 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs @@ -36,10 +36,20 @@ public DashScopeClientCore(HttpClient httpClient) public Uri? BaseAddress => _httpClient.BaseAddress; /// - public async Task GetApplicationResponseAsync( + public Task GetApplicationResponseAsync( string applicationId, ApplicationRequest input, CancellationToken cancellationToken = default) + { + return GetApplicationResponseAsync>(applicationId, input, cancellationToken); + } + + /// + public async Task GetApplicationResponseAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default) + where TBizContent : class { var request = BuildRequest(HttpMethod.Post, ApiLinks.Application(applicationId), input); return (await SendAsync(request, cancellationToken))!; @@ -50,6 +60,16 @@ public IAsyncEnumerable GetApplicationResponseStreamAsync( string applicationId, ApplicationRequest input, CancellationToken cancellationToken = default) + { + return GetApplicationResponseStreamAsync>(applicationId, input, cancellationToken); + } + + /// + public IAsyncEnumerable GetApplicationResponseStreamAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default) + where TBizContent : class { var request = BuildSseRequest(HttpMethod.Post, ApiLinks.Application(applicationId), input); return StreamAsync(request, cancellationToken); diff --git a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs index 203e646..852c00f 100644 --- a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs +++ b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs @@ -22,6 +22,20 @@ Task GetApplicationResponseAsync( ApplicationRequest input, CancellationToken cancellationToken = default); + /// + /// Make a call to custom application. + /// + /// Name of the application. + /// The request body. + /// The cancellation token to use. + /// Type of the biz_content. + /// + Task GetApplicationResponseAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default) + where TBizContent : class; + /// /// Make a call to custom application. /// @@ -34,6 +48,20 @@ IAsyncEnumerable GetApplicationResponseStreamAsync( ApplicationRequest input, CancellationToken cancellationToken = default); + /// + /// Make a call to custom application. + /// + /// Name of the application. + /// The request body. + /// The cancellation token to use. + /// Type of the biz_content. + /// + IAsyncEnumerable GetApplicationResponseStreamAsync( + string applicationId, + ApplicationRequest input, + CancellationToken cancellationToken = default) + where TBizContent : class; + /// /// Return textual completions as configured for a given prompt. /// From dd5c31684c964b96b2b9f515a73782d455395ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 22:19:11 +0800 Subject: [PATCH 10/35] test: add workflow application tests --- .../ApplicationInput.cs | 16 ++++++------- .../ApplicationRequest.cs | 8 +++---- .../ApplicationUsage.cs | 4 ++-- .../IDashScopeClient.cs | 12 ++++++---- .../ApplicationSerializationTests.cs | 18 +++++++++++++++ ...plication-workflow-nosse.request.body.json | 14 +++++++++++ ...lication-workflow-nosse.request.header.txt | 8 +++++++ ...plication-workflow-nosse.response.body.txt | 1 + ...ication-workflow-nosse.response.header.txt | 15 ++++++++++++ .../Utils/Snapshots.Application.cs | 23 +++++++++++++++++++ .../Utils/TestApplicationBizParam.cs | 7 ++++++ 11 files changed, 107 insertions(+), 19 deletions(-) create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/TestApplicationBizParam.cs diff --git a/src/Cnblogs.DashScope.Core/ApplicationInput.cs b/src/Cnblogs.DashScope.Core/ApplicationInput.cs index 85f1f0c..965124b 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationInput.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationInput.cs @@ -3,9 +3,9 @@ /// /// Inputs for application call. /// -/// Type of the BizContent. -public class ApplicationInput - where TBizContent : class +/// Type of the BizContent. +public class ApplicationInput + where TBizParams : class { /// /// The prompt for model to generate response upon. Optional when has been set. @@ -13,22 +13,22 @@ public class ApplicationInput /// /// Prompt will be appended to when both set. /// - public string? Prompt { get; set; } = null; + public string? Prompt { get; set; } /// /// The session id for conversation history. This will be ignored if has been set. /// - public string? SessionId { get; set; } = null; + public string? SessionId { get; set; } /// /// The conversation history. /// - public IEnumerable? Messages { get; set; } = null; + public IEnumerable? Messages { get; set; } /// /// The id of memory when enabled. /// - public string? MemoryId { get; set; } = null; + public string? MemoryId { get; set; } /// /// List of image urls for inputs. @@ -38,7 +38,7 @@ public class ApplicationInput /// /// User defined content. /// - public TBizContent? Content { get; set; } = null; + public TBizParams? BizParams { get; set; } = null; } /// diff --git a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs index b6e4130..ca67ff4 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs @@ -3,14 +3,14 @@ /// /// Request body for an application all. /// -/// Type of the biz_content -public class ApplicationRequest - where TBizContent : class +/// Type of the biz_content +public class ApplicationRequest + where TBizParams : class { /// /// Content of this call. /// - public required ApplicationInput Input { get; init; } + public required ApplicationInput Input { get; init; } /// /// Optional configurations. diff --git a/src/Cnblogs.DashScope.Core/ApplicationUsage.cs b/src/Cnblogs.DashScope.Core/ApplicationUsage.cs index 02aa0c1..8a4ef98 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationUsage.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationUsage.cs @@ -3,5 +3,5 @@ /// /// Total token usages of this application call. /// -/// All models been used and their token usages. -public record ApplicationUsage(List Models); +/// All models been used and their token usages. Can be null when workflow application without using any model. +public record ApplicationUsage(List? Models); diff --git a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs index 852c00f..ab2d39c 100644 --- a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs +++ b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs @@ -1,4 +1,6 @@ -namespace Cnblogs.DashScope.Core; +using System.Text.Json; + +namespace Cnblogs.DashScope.Core; /// /// DashScope APIs. @@ -28,13 +30,13 @@ Task GetApplicationResponseAsync( /// Name of the application. /// The request body. /// The cancellation token to use. - /// Type of the biz_content. + /// Type of the biz_content. /// - Task GetApplicationResponseAsync( + Task GetApplicationResponseAsync( string applicationId, - ApplicationRequest input, + ApplicationRequest input, CancellationToken cancellationToken = default) - where TBizContent : class; + where TBizParams : class; /// /// Make a call to custom application. diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs index 67dd03f..a8021a0 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs @@ -118,4 +118,22 @@ public async Task SingleCompletion_MemoryNoSse_SuccessAsync() Arg.Any()); response.Should().BeEquivalentTo(testCase.ResponseModel); } + + [Fact] + public async Task SingleCompletion_WorkflowNoSse_SuccessAsync() + { + // Arrange + const bool sse = false; + var testCase = Snapshots.Application.WorkflowNoSse; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + var response = await client.GetApplicationResponseAsync("anyId", testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is(m => Checkers.IsJsonEquivalent(m.Content!, testCase.GetRequestJson(sse))), + Arg.Any()); + response.Should().BeEquivalentTo(testCase.ResponseModel); + } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.body.json new file mode 100644 index 0000000..6b55694 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.body.json @@ -0,0 +1,14 @@ +{ + "input": { + "prompt": "请你跟我这样说", + "biz_params": { + "sourceCode": "code" + } + }, + "parameters": { + "top_k": 100, + "top_p": 0.8, + "seed": 1234, + "temperature": 0.85 + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.header.txt new file mode 100644 index 0000000..e0c52bd --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.header.txt @@ -0,0 +1,8 @@ +POST /api/v1/apps/debbb624ccfd4ebdac605edc27f94f7a/completion 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: 268 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.body.txt new file mode 100644 index 0000000..c882c92 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"finish_reason":"stop","session_id":"5a20b47dac2f43a7b1cbb8924ca66c47","text":"code"},"usage":{},"request_id":"10990f51-e2d0-9338-9c52-319af5f4858b"} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.header.txt new file mode 100644 index 0000000..087d6ad --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding +content-type: application/json +x-request-id: 10990f51-e2d0-9338-9c52-319af5f4858b +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 414 +req-arrive-time: 1742133858888 +resp-start-time: 1742133859303 +x-envoy-upstream-service-time: 406 +content-encoding: gzip +date: Sun, 16 Mar 2025 14:04:18 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs index 126cb11..6ad5bb1 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs @@ -250,6 +250,29 @@ public static class Application null), new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 1201, 43)]))); + public static readonly RequestSnapshot, ApplicationResponse> + WorkflowNoSse = + new( + "application-workflow", + new ApplicationRequest() + { + Input = new ApplicationInput() + { + BizParams = new TestApplicationBizParam("code"), Prompt = "请你跟我这样说" + }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + } + }, + new ApplicationResponse( + "10990f51-e2d0-9338-9c52-319af5f4858b", + new ApplicationOutput("code", "stop", "5a20b47dac2f43a7b1cbb8924ca66c47", null, null), + new ApplicationUsage(null))); + public static readonly RequestSnapshot ConversationSessionIdNoSse = new( "application-conversation-generation-session-id", diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/TestApplicationBizParam.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/TestApplicationBizParam.cs new file mode 100644 index 0000000..a1274f4 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/TestApplicationBizParam.cs @@ -0,0 +1,7 @@ +using System.Text.Json.Serialization; + +namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; + +public record TestApplicationBizParam( + [property: JsonPropertyName("sourceCode")] + string SourceCode); From 47a42d537d8f00e2fbe0c71be8403d2b9e3ee93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 22:35:08 +0800 Subject: [PATCH 11/35] feat: support set workspace when injecting service or creating client --- .../ServiceCollectionInjector.cs | 15 ++++++++--- .../ApplicationRagOptions.cs | 4 +-- src/Cnblogs.DashScope.Core/DashScopeClient.cs | 25 +++++++++++++------ .../DashScopeClientCore.cs | 8 +++++- .../IDashScopeClient.cs | 4 +-- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/Cnblogs.DashScope.AspNetCore/ServiceCollectionInjector.cs b/src/Cnblogs.DashScope.AspNetCore/ServiceCollectionInjector.cs index 6d91b83..ee6b00a 100644 --- a/src/Cnblogs.DashScope.AspNetCore/ServiceCollectionInjector.cs +++ b/src/Cnblogs.DashScope.AspNetCore/ServiceCollectionInjector.cs @@ -38,9 +38,8 @@ public static IHttpClientBuilder AddDashScopeClient(this IServiceCollection serv var apiKey = section["apiKey"] ?? throw new InvalidOperationException("There is no apiKey provided in given section"); var baseAddress = section["baseAddress"]; - return string.IsNullOrEmpty(baseAddress) - ? services.AddDashScopeClient(apiKey) - : services.AddDashScopeClient(apiKey, baseAddress); + var workspaceId = section["workspaceId"]; + return services.AddDashScopeClient(apiKey, baseAddress, workspaceId); } /// @@ -49,16 +48,24 @@ public static IHttpClientBuilder AddDashScopeClient(this IServiceCollection serv /// The service collection to add service to. /// The DashScope api key. /// The DashScope api base address, you may change this value if you are using proxy. + /// Default workspace id to use. /// public static IHttpClientBuilder AddDashScopeClient( this IServiceCollection services, string apiKey, - string baseAddress = "https://dashscope.aliyuncs.com/api/v1/") + string? baseAddress = null, + string? workspaceId = null) { + baseAddress ??= "https://dashscope.aliyuncs.com/api/v1/"; return services.AddHttpClient( h => { h.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); + if (string.IsNullOrWhiteSpace(workspaceId) == false) + { + h.DefaultRequestHeaders.Add("X-DashScope-WorkSpace", workspaceId); + } + h.BaseAddress = new Uri(baseAddress); }); } diff --git a/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs index 3d28f7d..38aff36 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRagOptions.cs @@ -1,6 +1,4 @@ -using System.Text.Json; - -namespace Cnblogs.DashScope.Core; +namespace Cnblogs.DashScope.Core; /// /// Options for RAG application. diff --git a/src/Cnblogs.DashScope.Core/DashScopeClient.cs b/src/Cnblogs.DashScope.Core/DashScopeClient.cs index 26f716f..dea20f9 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeClient.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeClient.cs @@ -15,32 +15,43 @@ public class DashScopeClient : DashScopeClientCore /// /// The DashScope api key. /// The timeout for internal http client, defaults to 2 minute. + /// The base address for dashscope api call. + /// The workspace id. /// - /// The underlying httpclient is cached by apiKey and timeout. - /// Client created with same apiKey and timeout value will share same underlying instance. + /// The underlying httpclient is cached by constructor parameter list. + /// Client created with same parameter value will share same underlying instance. /// - public DashScopeClient(string apiKey, TimeSpan? timeout = null) - : base(GetConfiguredClient(apiKey, timeout)) + public DashScopeClient( + string apiKey, + TimeSpan? timeout = null, + string? baseAddress = null, + string? workspaceId = null) + : base(GetConfiguredClient(apiKey, timeout, baseAddress, workspaceId)) { } - private static HttpClient GetConfiguredClient(string apiKey, TimeSpan? timeout) + private static HttpClient GetConfiguredClient( + string apiKey, + TimeSpan? timeout = null, + string? baseAddress = null, + string? workspaceId = null) { var client = ClientPools.GetValueOrDefault(GetCacheKey()); if (client is null) { client = new HttpClient { - BaseAddress = new Uri(DashScopeDefaults.DashScopeApiBaseAddress), + BaseAddress = new Uri(baseAddress ?? DashScopeDefaults.DashScopeApiBaseAddress), Timeout = timeout ?? TimeSpan.FromMinutes(2) }; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey); + client.DefaultRequestHeaders.Add("X-DashScope-WorkSpace", workspaceId); ClientPools.Add(GetCacheKey(), client); } return client; - string GetCacheKey() => $"{apiKey}-{timeout?.TotalMilliseconds}"; + string GetCacheKey() => $"{apiKey}-{timeout?.TotalMilliseconds}-{baseAddress}-{workspaceId}"; } } diff --git a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs index 8584637..9b917d0 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs @@ -297,7 +297,8 @@ private static HttpRequestMessage BuildRequest( string url, TPayload? payload = null, bool sse = false, - bool isTask = false) + bool isTask = false, + string? workspaceId = null) where TPayload : class { var message = new HttpRequestMessage(method, url) @@ -315,6 +316,11 @@ private static HttpRequestMessage BuildRequest( message.Headers.Add("X-DashScope-Async", "enable"); } + if (string.IsNullOrWhiteSpace(workspaceId) == false) + { + message.Headers.Add("X-DashScope-WorkspaceId", workspaceId); + } + return message; } diff --git a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs index ab2d39c..a123050 100644 --- a/src/Cnblogs.DashScope.Core/IDashScopeClient.cs +++ b/src/Cnblogs.DashScope.Core/IDashScopeClient.cs @@ -1,6 +1,4 @@ -using System.Text.Json; - -namespace Cnblogs.DashScope.Core; +namespace Cnblogs.DashScope.Core; /// /// DashScope APIs. From 00141a1c15d26eba90d42946a814ace72c227840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 16 Mar 2025 22:40:41 +0800 Subject: [PATCH 12/35] test: add tests for base address and workspace id configure --- .../DashScopeClientTests.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/DashScopeClientTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/DashScopeClientTests.cs index be60571..93f7d4d 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/DashScopeClientTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/DashScopeClientTests.cs @@ -75,6 +75,36 @@ public void DashScopeClient_Constructor_WithApiKeyHeader() .BeEquivalentTo(new AuthenticationHeaderValue("Bearer", apiKey)); } + [Fact] + public void DashScopeClient_Constructor_WithWorkspaceId() + { + // Arrange + const string apiKey = "key"; + const string workspaceId = "workspaceId"; + var client = new DashScopeClient(apiKey, null, null, workspaceId); + + // Act + var value = HttpClientAccessor.GetValue(client) as HttpClient; + + // Assert + value?.DefaultRequestHeaders.GetValues("X-DashScope-WorkSpace").Should().BeEquivalentTo(workspaceId); + } + + [Fact] + public void DashScopeClient_Constructor_WithPrivateEndpoint() + { + // Arrange + const string apiKey = "key"; + const string privateEndpoint = "https://dashscope.cnblogs.com/api/v1"; + var client = new DashScopeClient(apiKey, null, privateEndpoint); + + // Act + var value = HttpClientAccessor.GetValue(client) as HttpClient; + + // Assert + value?.BaseAddress.Should().BeEquivalentTo(new Uri(privateEndpoint)); + } + public static TheoryData ParamsShouldNotCache => new() { From 72fd4a666fa114ceb6524a712e617bc1329f4777 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 17 Mar 2025 16:07:02 +0800 Subject: [PATCH 13/35] test: migrate changes --- .../Utils/Snapshots.MultimodalGeneration.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs index 1ec249a..7c0d279 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs @@ -74,7 +74,7 @@ public static class MultimodalGeneration MultimodalMessage.User( [ MultimodalMessageContent.ImageContent( - "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") ]) ] @@ -126,7 +126,7 @@ public static class MultimodalGeneration MultimodalMessage.User( [ MultimodalMessageContent.ImageContent( - "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") ]) ] From c6e2aefd0c2a48b6f8c0405c0ad7ec03f8ae09e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 17 Mar 2025 16:33:22 +0800 Subject: [PATCH 14/35] doc: update README with application call example --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++ README.zh-Hans.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) diff --git a/README.md b/README.md index efd74b1..c635192 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ public class YourService(IDashScopeClient client) - Image Generation - `CreateWanxImageGenerationTaskAsync()` and `GetWanxImageGenerationTaskAsync()` - Background Image Generation - `CreateWanxBackgroundGenerationTaskAsync()` and `GetWanxBackgroundGenerationTaskAsync()` - File API that used by Qwen-Long - `dashScopeClient.UploadFileAsync()` and `dashScopeClient.DeleteFileAsync` +- Application call - `GetApplicationResponseAsync()` and `GetApplicationResponseStreamAsync()` # Examples @@ -208,3 +209,71 @@ Delete file if needed ```csharp var deletionResult = await dashScopeClient.DeleteFileAsync(uploadedFile.Id); ``` + +## Application call + +Use `GetApplicationResponseAsync` to call an application. + +Use `GetApplicationResponseStreamAsync` for streaming output. + +```csharp +var request = + new ApplicationRequest() + { + Input = new ApplicationInput() { Prompt = "Summarize this file." }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["thie5bysoj"], + FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] + } + } + }; +var response = await client.GetApplicationResponseAsync("your-application-id", request); +Console.WriteLine(response.Output.Text); +``` + +`ApplicationRequest` use an `Dictionary` as `BizParams` by default. + +```csharp +var request = + new ApplicationRequest() + { + Input = new ApplicationInput() + { + Prompt = "Summarize this file.", + BizParams = new Dictionary() + { + { "customKey1", "custom-value" } + } + } + }; +var response = await client.GetApplicationResponseAsync("your-application-id", request); +Console.WriteLine(response.Output.Text); +``` + +You can use the generic version `ApplicationRequest` for strong-typed `BizParams`. But keep in mind that client use `snake_case` by default when doing json serialization, you may need to use `[JsonPropertyName("camelCase")]` for other type of naming policy. + +```csharp +public record TestApplicationBizParam( + [property: JsonPropertyName("sourceCode")] + string SourceCode); + +var request = + new ApplicationRequest() + { + Input = new ApplicationInput() + { + Prompt = "Summarize this file.", + BizParams = new TestApplicationBizParam("test") + } + }; +var response = await client.GetApplicationResponseAsync("your-application-id", request); +Console.WriteLine(response.Output.Text); +``` + diff --git a/README.zh-Hans.md b/README.zh-Hans.md index 9f81d6b..a84421d 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -76,6 +76,7 @@ public class YourService(IDashScopeClient client) - 人像风格重绘 - `CreateWanxImageGenerationTaskAsync()` and `GetWanxImageGenerationTaskAsync()` - 图像背景生成 - `CreateWanxBackgroundGenerationTaskAsync()` and `GetWanxBackgroundGenerationTaskAsync()` - 适用于 QWen-Long 的文件 API `dashScopeClient.UploadFileAsync()` and `dashScopeClient.DeleteFileAsync` +- 应用调用 `dashScopeClient.GetApplicationResponseAsync` 和 `dashScopeClient.GetApplicationResponseStreamAsync()` - 其他使用相同 Endpoint 的模型 # 示例 @@ -204,3 +205,71 @@ Console.WriteLine(completion.Output.Choices[0].Message.Content); ```csharp var deletionResult = await dashScopeClient.DeleteFileAsync(uploadedFile.Id); ``` + +## 应用调用 + +`GetApplicationResponseAsync` 用于进行应用调用。 + +`GetApplicationResponseStreamAsync` 用于流式调用。 + +```csharp +var request = + new ApplicationRequest() + { + Input = new ApplicationInput() { Prompt = "Summarize this file." }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + RagOptions = new ApplicationRagOptions() + { + PipelineIds = ["thie5bysoj"], + FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] + } + } + }; +var response = await client.GetApplicationResponseAsync("your-application-id", request); +Console.WriteLine(response.Output.Text); +``` + +`ApplicationRequest` 默认使用 `Dictionary` 作为 `BizParams` 的类型。 + +```csharp +var request = + new ApplicationRequest() + { + Input = new ApplicationInput() + { + Prompt = "Summarize this file.", + BizParams = new Dictionary() + { + { "customKey1", "custom-value" } + } + } + }; +var response = await client.GetApplicationResponseAsync("your-application-id", request); +Console.WriteLine(response.Output.Text); +``` + +如需强类型支持,可以使用泛型类 `ApplicationRequest`。 +注意 SDK 在 JSON 序列化时使用 `snake_case`。如果你的应用采用其他的命名规则,请使用 `[JsonPropertyName("camelCase")]` 来手动指定序列化时的属性名称。 + +```csharp +public record TestApplicationBizParam( + [property: JsonPropertyName("sourceCode")] + string SourceCode); + +var request = + new ApplicationRequest() + { + Input = new ApplicationInput() + { + Prompt = "Summarize this file.", + BizParams = new TestApplicationBizParam("test") + } + }; +var response = await client.GetApplicationResponseAsync("your-application-id", request); +Console.WriteLine(response.Output.Text); +``` From 47ea4c7834283e329ce4112f18ee345c52306901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 17 Mar 2025 16:35:48 +0800 Subject: [PATCH 15/35] test: update snapshot --- .../Utils/Snapshots.MultimodalGeneration.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs index 7c0d279..20f17f5 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs @@ -126,7 +126,7 @@ public static class MultimodalGeneration MultimodalMessage.User( [ MultimodalMessageContent.ImageContent( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), + "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") ]) ] @@ -174,7 +174,7 @@ public static class MultimodalGeneration MultimodalMessage.User( [ MultimodalMessageContent.ImageContent( - "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") ]) ] From da396a71631c3995aa2a48e39a5d383be9bae67b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 17 Mar 2025 17:03:14 +0800 Subject: [PATCH 16/35] feat: add application call sample --- sample/Cnblogs.DashScope.Sample/Program.cs | 14 ++++++++++++++ sample/Cnblogs.DashScope.Sample/SampleType.cs | 4 +++- .../SampleTypeDescriptor.cs | 1 + src/Cnblogs.DashScope.Core/ApplicationRequest.cs | 2 +- 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/sample/Cnblogs.DashScope.Sample/Program.cs b/sample/Cnblogs.DashScope.Sample/Program.cs index c5958f3..8841af4 100644 --- a/sample/Cnblogs.DashScope.Sample/Program.cs +++ b/sample/Cnblogs.DashScope.Sample/Program.cs @@ -56,6 +56,13 @@ case SampleType.MicrosoftExtensionsAiToolCall: await dashScopeClient.ToolCallWithExtensionAsync(); break; + case SampleType.ApplicationCall: + Console.Write("Application Id > "); + var applicationId = Console.ReadLine()!; + Console.Write("Prompt > "); + userInput = Console.ReadLine()!; + await ApplicationCallAsync(applicationId, userInput); + break; } return; @@ -215,3 +222,10 @@ async Task ChatWithMicrosoftExtensions() var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) { WriteIndented = true }; Console.WriteLine(JsonSerializer.Serialize(response, serializerOptions)); } + +async Task ApplicationCallAsync(string applicationId, string prompt) +{ + var request = new ApplicationRequest() { Input = new ApplicationInput() { Prompt = prompt } }; + var response = await dashScopeClient.GetApplicationResponseAsync(applicationId, request); + Console.WriteLine(response.Output.Text); +} diff --git a/sample/Cnblogs.DashScope.Sample/SampleType.cs b/sample/Cnblogs.DashScope.Sample/SampleType.cs index 94d119d..feddf79 100644 --- a/sample/Cnblogs.DashScope.Sample/SampleType.cs +++ b/sample/Cnblogs.DashScope.Sample/SampleType.cs @@ -14,5 +14,7 @@ public enum SampleType MicrosoftExtensionsAi, - MicrosoftExtensionsAiToolCall + MicrosoftExtensionsAiToolCall, + + ApplicationCall } diff --git a/sample/Cnblogs.DashScope.Sample/SampleTypeDescriptor.cs b/sample/Cnblogs.DashScope.Sample/SampleTypeDescriptor.cs index e39f284..26988a5 100644 --- a/sample/Cnblogs.DashScope.Sample/SampleTypeDescriptor.cs +++ b/sample/Cnblogs.DashScope.Sample/SampleTypeDescriptor.cs @@ -13,6 +13,7 @@ public static string GetDescription(this SampleType sampleType) SampleType.ChatCompletionWithFiles => "File upload sample using qwen-long", SampleType.MicrosoftExtensionsAi => "Use with Microsoft.Extensions.AI", SampleType.MicrosoftExtensionsAiToolCall => "Use tool call with Microsoft.Extensions.AI interfaces", + SampleType.ApplicationCall => "Call pre-defined application", _ => throw new ArgumentOutOfRangeException(nameof(sampleType), sampleType, "Unsupported sample option") }; } diff --git a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs index ca67ff4..b367d5e 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs @@ -15,7 +15,7 @@ public class ApplicationRequest /// /// Optional configurations. /// - public required ApplicationParameters? Parameters { get; init; } + public ApplicationParameters? Parameters { get; init; } } /// From 6b6d2d2e09294da7729cf3a91bfc63d0147c6936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 17 Mar 2025 22:44:51 +0800 Subject: [PATCH 17/35] feat: allow setting workspace id per request --- .../ApplicationRequest.cs | 17 ++++++++++--- .../DashScopeClientCore.cs | 11 ++++---- .../Internals/IDashScopeWorkspaceConfig.cs | 12 +++++++++ .../TextGenerationTokenDetails.cs | 7 ++++++ .../TextGenerationTokenUsage.cs | 5 ++++ ...le-generation-text-nosse.response.body.txt | 13 +--------- ...-generation-text-nosse.response.header.txt | 25 ++++++++++--------- .../Utils/Snapshots.Application.cs | 24 ++++++++++++++++++ .../Utils/Snapshots.TextGeneration.cs | 11 ++++---- .../WorkspaceIdTests.cs | 25 +++++++++++++++++++ 10 files changed, 112 insertions(+), 38 deletions(-) create mode 100644 src/Cnblogs.DashScope.Core/Internals/IDashScopeWorkspaceConfig.cs create mode 100644 src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs diff --git a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs index b367d5e..bdafef5 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs @@ -1,21 +1,30 @@ -namespace Cnblogs.DashScope.Core; +using System.Text.Json.Serialization; +using Cnblogs.DashScope.Core.Internals; + +namespace Cnblogs.DashScope.Core; /// /// Request body for an application all. /// /// Type of the biz_content -public class ApplicationRequest +public class ApplicationRequest : IDashScopeWorkspaceConfig where TBizParams : class { /// /// Content of this call. /// - public required ApplicationInput Input { get; init; } + public required ApplicationInput Input { get; set; } /// /// Optional configurations. /// - public ApplicationParameters? Parameters { get; init; } + public ApplicationParameters? Parameters { get; set; } + + /// + /// Optional workspace id. + /// + [JsonIgnore] + public string? WorkspaceId { get; set; } } /// diff --git a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs index 9b917d0..7cca41f 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs @@ -275,7 +275,9 @@ public async Task ListFilesAsync(CancellationToken cancellati } /// - public async Task DeleteFileAsync(DashScopeFileId id, CancellationToken cancellationToken = default) + public async Task DeleteFileAsync( + DashScopeFileId id, + CancellationToken cancellationToken = default) { var request = BuildRequest(HttpMethod.Delete, ApiLinks.Files + $"/{id}"); return (await SendCompatibleAsync(request, cancellationToken))!; @@ -297,8 +299,7 @@ private static HttpRequestMessage BuildRequest( string url, TPayload? payload = null, bool sse = false, - bool isTask = false, - string? workspaceId = null) + bool isTask = false) where TPayload : class { var message = new HttpRequestMessage(method, url) @@ -316,9 +317,9 @@ private static HttpRequestMessage BuildRequest( message.Headers.Add("X-DashScope-Async", "enable"); } - if (string.IsNullOrWhiteSpace(workspaceId) == false) + if (payload is IDashScopeWorkspaceConfig config && string.IsNullOrWhiteSpace(config.WorkspaceId) == false) { - message.Headers.Add("X-DashScope-WorkspaceId", workspaceId); + message.Headers.Add("X-DashScope-WorkSpace", config.WorkspaceId); } return message; diff --git a/src/Cnblogs.DashScope.Core/Internals/IDashScopeWorkspaceConfig.cs b/src/Cnblogs.DashScope.Core/Internals/IDashScopeWorkspaceConfig.cs new file mode 100644 index 0000000..752056b --- /dev/null +++ b/src/Cnblogs.DashScope.Core/Internals/IDashScopeWorkspaceConfig.cs @@ -0,0 +1,12 @@ +namespace Cnblogs.DashScope.Core.Internals; + +/// +/// Workspace configuration. +/// +internal interface IDashScopeWorkspaceConfig +{ + /// + /// Unique id of workspace to use. + /// + public string? WorkspaceId { get; } +} diff --git a/src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs b/src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs new file mode 100644 index 0000000..d8e5b18 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs @@ -0,0 +1,7 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Token usage details. +/// +/// Token count of cached input tokens +public record TextGenerationTokenDetails(int CachedTokens); diff --git a/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs b/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs index 8021388..7662d7d 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs +++ b/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs @@ -11,6 +11,11 @@ public class TextGenerationTokenUsage /// This number may larger than input if internet search is enabled. public int InputTokens { get; set; } + /// + /// Input token details. + /// + public TextGenerationTokenDetails? PromptTokensDetails { get; set; } + /// /// The number of output token. /// diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.body.txt index 8d85edb..76cd3dc 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.body.txt +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.body.txt @@ -1,12 +1 @@ -{ - "output": { - "finish_reason": "stop", - "text": "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下两个一相加的结果都是二。" - }, - "usage": { - "total_tokens": 43, - "output_tokens": 35, - "input_tokens": 8 - }, - "request_id": "4ef2ed16-4dc3-9083-a723-fb2e80c84d3b" -} +{"output":{"finish_reason":"stop","text":"1+1等于2。这是最基本的数学加法运算之一。"},"usage":{"prompt_tokens_details":{"cached_tokens":0},"total_tokens":30,"output_tokens":14,"input_tokens":16},"request_id":"7e3d5586-cb70-98ce-97bf-8a2ac0091c3f"} \ No newline at end of file diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.header.txt index 3b4f8a2..ada9654 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.header.txt +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.header.txt @@ -1,13 +1,14 @@ -HTTP/1.1 200 OK -eagleeye-traceid: 5bc840127c9dd7ed1de5586c0865cf01 -content-type: application/json +HTTP/1.1 200 OK +Vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Accept-Encoding +X-Request-ID: 7e3d5586-cb70-98ce-97bf-8a2ac0091c3f +x-dashscope-timeout: 180 x-dashscope-call-gateway: true -req-cost-time: 6004 -req-arrive-time: 1708924139239 -resp-start-time: 1708924145244 -x-envoy-upstream-service-time: 5998 -content-encoding: gzip -vary: Accept-Encoding -date: Mon, 26 Feb 2024 05:09:05 GMT -server: istio-envoy -transfer-encoding: chunked +x-dashscope-finished: true +req-cost-time: 974 +req-arrive-time: 1742222245417 +resp-start-time: 1742222246391 +x-envoy-upstream-service-time: 964 +Set-Cookie: acw_tc=7e3d5586-cb70-98ce-97bf-8a2ac0091c3f7d8fa666bbce18dfce67d4b0ced27ae0;path=/;HttpOnly;Max-Age=1800 +Date: Mon, 17 Mar 2025 14:37:26 GMT +Server: istio-envoy +Transfer-Encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs index 6ad5bb1..59cfe01 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs @@ -273,6 +273,30 @@ public static readonly RequestSnapshot, ApplicationResponse> + WorkflowInDifferentWorkSpaceNoSse = + new( + "application-workflow", + new ApplicationRequest() + { + Input = new ApplicationInput() + { + BizParams = new TestApplicationBizParam("code"), Prompt = "请你跟我这样说" + }, + Parameters = new ApplicationParameters() + { + TopK = 100, + TopP = 0.8f, + Seed = 1234, + Temperature = 0.85f, + }, + WorkspaceId = "workspaceId" + }, + new ApplicationResponse( + "10990f51-e2d0-9338-9c52-319af5f4858b", + new ApplicationOutput("code", "stop", "5a20b47dac2f43a7b1cbb8924ca66c47", null, null), + new ApplicationUsage(null))); + public static readonly RequestSnapshot ConversationSessionIdNoSse = new( "application-conversation-generation-session-id", diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs index 6f8fe94..4a6e30a 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs @@ -36,14 +36,15 @@ public static class TextFormat { Output = new TextGenerationOutput { - FinishReason = "stop", Text = "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下两个一相加的结果都是二。" + FinishReason = "stop", Text = "1+1等于2。这是最基本的数学加法运算之一。" }, - RequestId = "4ef2ed16-4dc3-9083-a723-fb2e80c84d3b", + RequestId = "7e3d5586-cb70-98ce-97bf-8a2ac0091c3f", Usage = new TextGenerationTokenUsage { - InputTokens = 8, - OutputTokens = 35, - TotalTokens = 43 + InputTokens = 16, + OutputTokens = 14, + TotalTokens = 30, + PromptTokensDetails = new TextGenerationTokenDetails(0) } }); diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs new file mode 100644 index 0000000..c6b3a98 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs @@ -0,0 +1,25 @@ +using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using NSubstitute; + +namespace Cnblogs.DashScope.Sdk.UnitTests; + +public class WorkspaceIdTests +{ + [Fact] + public async Task ApplicationCall_WithWorkspaceId_ApplyAsync() + { + // Arrange + const bool sse = false; + var testCase = Snapshots.Application.WorkflowInDifferentWorkSpaceNoSse; + var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); + + // Act + await client.GetApplicationResponseAsync("anyId", testCase.RequestModel); + + // Assert + handler.Received().MockSend( + Arg.Is( + m => m.Headers.GetValues("X-DashScope-WorkSpace").First() == testCase.RequestModel.WorkspaceId), + Arg.Any()); + } +} From 1d41b167c213bcb1ac04a638180101e30d6ba94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Thu, 20 Mar 2025 12:01:41 +0800 Subject: [PATCH 18/35] feat: support reasoning models --- README.md | 62 +- README.zh-Hans.md | 69 +- .../DashScopeChatClient.cs | 5 +- src/Cnblogs.DashScope.Core/TextChatMessage.cs | 12 +- .../DeepSeek/DeepSeekLlm.cs | 17 + .../DeepSeek/DeepSeekLlmName.cs | 14 + .../DeepSeek/DeepSeekTextGenerationApi.cs | 87 + src/Cnblogs.DashScope.Sdk/QWen/QWenLlm.cs | 7 +- .../QWen/QWenLlmNames.cs | 3 +- .../DeepSeekTextGenerationApiTests.cs | 74 + ...-message-reasoning-nosse.request.body.json | 14 + ...message-reasoning-nosse.request.header.txt | 8 + ...-message-reasoning-nosse.response.body.txt | 1 + ...essage-reasoning-nosse.response.header.txt | 15 + ...on-message-reasoning-sse.request.body.json | 14 + ...n-message-reasoning-sse.request.header.txt | 7 + ...on-message-reasoning-sse.response.body.txt | 1975 +++++++++++++++++ ...-message-reasoning-sse.response.header.txt | 14 + .../TextGenerationSerializationTests.cs | 28 +- .../Utils/Snapshots.TextGeneration.cs | 75 + 20 files changed, 2472 insertions(+), 29 deletions(-) create mode 100644 src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlm.cs create mode 100644 src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlmName.cs create mode 100644 src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekTextGenerationApi.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.body.json create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.header.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.body.txt create mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.header.txt diff --git a/README.md b/README.md index c635192..02f3ff3 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ builder.AddDashScopeClient(builder.Configuration); ```json { "DashScope": { - "ApiKey": "your-api-key" + "ApiKey": "your-api-key", } } ``` @@ -66,21 +66,54 @@ public class YourService(IDashScopeClient client) # Supported APIs -- Text Embedding API - `dashScopeClient.GetTextEmbeddingsAsync()` -- Text Generation API(qwen-turbo, qwen-max, etc.) - `dashScopeClient.GetQwenCompletionAsync()` and `dashScopeClient.GetQWenCompletionStreamAsync()` -- BaiChuan Models - Use `dashScopeClient.GetBaiChuanTextCompletionAsync()` -- LLaMa2 Models - `dashScopeClient.GetLlama2TextCompletionAsync()` -- Multimodal Generation API(qwen-vl-max, etc.) - `dashScopeClient.GetQWenMultimodalCompletionAsync()` and `dashScopeClient.GetQWenMultimodalCompletionStreamAsync()` +- Text Embedding API - `GetTextEmbeddingsAsync()` +- Text Generation API(qwen-turbo, qwen-max, etc.) - `GetQWenCompletionAsync()` and `GetQWenCompletionStreamAsync()` +- DeepSeek Models - `GetDeepSeekCompletionAsync()` and `GetDeepSeekCompletionStreamAsync()` +- BaiChuan Models - Use `GetBaiChuanTextCompletionAsync()` +- LLaMa2 Models - `GetLlama2TextCompletionAsync()` +- Multimodal Generation API(qwen-vl-max, etc.) - `GetQWenMultimodalCompletionAsync()` and `GetQWenMultimodalCompletionStreamAsync()` - Wanx Models(Image generation, background generation, etc) - Image Synthesis - `CreateWanxImageSynthesisTaskAsync()` and `GetWanxImageSynthesisTaskAsync()` - Image Generation - `CreateWanxImageGenerationTaskAsync()` and `GetWanxImageGenerationTaskAsync()` - Background Image Generation - `CreateWanxBackgroundGenerationTaskAsync()` and `GetWanxBackgroundGenerationTaskAsync()` -- File API that used by Qwen-Long - `dashScopeClient.UploadFileAsync()` and `dashScopeClient.DeleteFileAsync` +- File API that used by Qwen-Long - `UploadFileAsync()` and `DeleteFileAsync` - Application call - `GetApplicationResponseAsync()` and `GetApplicationResponseStreamAsync()` # Examples -Visit [tests](./test) for more usage of each api. +Visit [snapshots](./test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs) for calling samples. + +Visit [tests](./test/Cnblogs.DashScope.Sdk.UnitTests) for more usage of each api. + +## General Text Completion API + +Use `client.GetTextCompletionAsync` and `client.GetTextCompletionStreamAsync` to access text generation api directly. + +```csharp +var completion = await dashScopeClient.GetTextCompletionAsync( + new ModelRequest + { + Model = "your-model-name", + Input = new TextGenerationInput { Prompt = prompt }, + Parameters = new TextGenerationParameters() + { + // control parameters as you wish. + EnableSearch = true + } + }); +var completions = dashScopeClient.GetTextCompletionStreamAsync( + new ModelRequest + { + Model = "your-model-name", + Input = new TextGenerationInput { Messages = [TextChatMessage.System("you are a helpful assistant"), TextChatMessage.User("How are you?")] }, + Parameters = new TextGenerationParameters() + { + // control parameters as you wish. + EnableSearch = true, + IncreamentalOutput = true + } + }); +``` ## Single Text Completion @@ -90,6 +123,19 @@ var completion = await client.GetQWenCompletionAsync(QWenLlm.QWenMax, prompt); Console.WriteLine(completion.Output.Text); ``` +## Reasoning + +Use `completion.Output.Choices![0].Message.ReasoningContent` to access the reasoning content from model. + +```csharp +var history = new List +{ + ChatMessage.User("Calculate 1+1") +}; +var completion = await client.GetDeepSeekChatCompletionAsync(DeepSeekLlm.DeepSeekR1, history); +Console.WriteLine(completion.Output.Choices[0]!.Message.ReasoningContent); +``` + ## Multi-round chat ```csharp diff --git a/README.zh-Hans.md b/README.zh-Hans.md index a84421d..f275d76 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -66,23 +66,59 @@ public class YourService(IDashScopeClient client) # 支持的 API -- 通用文本向量 - `dashScopeClient.GetTextEmbeddingsAsync()` -- 通义千问(`qwen-turbo`, `qwen-max` 等) - `dashScopeClient.GetQwenCompletionAsync()` and `dashScopeClient.GetQWenCompletionStreamAsync()` -- 百川开源大模型 - Use `dashScopeClient.GetBaiChuanTextCompletionAsync()` -- LLaMa2 大语言模型 - `dashScopeClient.GetLlama2TextCompletionAsync()` -- 通义千问 VL 和通义千问 Audio(`qwen-vl-max`, `qwen-audio`) - `dashScopeClient.GetQWenMultimodalCompletionAsync()` and `dashScopeClient.GetQWenMultimodalCompletionStreamAsync()` +- 通用文本向量 - `GetTextEmbeddingsAsync()` +- 通义千问(`qwen-turbo`, `qwen-max` 等) - `GetQWenCompletionAsync()` 和 `GetQWenCompletionStreamAsync()` +- DeepSeek 系列模型(`deepseek-r1`,`deepseek-v3` 等) - `GetDeepSeekChatCompletionAsync()` 和 `GetDeepSeekChatCompletionStreamAsync()` +- 百川开源大模型 - `GetBaiChuanTextCompletionAsync()` +- LLaMa2 大语言模型 - `GetLlama2TextCompletionAsync()` +- 通义千问 VL 和通义千问 Audio(`qwen-vl-max`, `qwen-audio`) - `GetQWenMultimodalCompletionAsync()` 和 `GetQWenMultimodalCompletionStreamAsync()` - 通义万相系列 - - 文生图 - `CreateWanxImageSynthesisTaskAsync()` and `GetWanxImageSynthesisTaskAsync()` - - 人像风格重绘 - `CreateWanxImageGenerationTaskAsync()` and `GetWanxImageGenerationTaskAsync()` - - 图像背景生成 - `CreateWanxBackgroundGenerationTaskAsync()` and `GetWanxBackgroundGenerationTaskAsync()` -- 适用于 QWen-Long 的文件 API `dashScopeClient.UploadFileAsync()` and `dashScopeClient.DeleteFileAsync` -- 应用调用 `dashScopeClient.GetApplicationResponseAsync` 和 `dashScopeClient.GetApplicationResponseStreamAsync()` + - 文生图 - `CreateWanxImageSynthesisTaskAsync()` 和 `GetWanxImageSynthesisTaskAsync()` + - 人像风格重绘 - `CreateWanxImageGenerationTaskAsync()` 和 `GetWanxImageGenerationTaskAsync()` + - 图像背景生成 - `CreateWanxBackgroundGenerationTaskAsync()` 和 `GetWanxBackgroundGenerationTaskAsync()` +- 适用于 QWen-Long 的文件 API `UploadFileAsync()` 和 `DeleteFileAsync` +- 应用调用 `GetApplicationResponseAsync` 和 `GetApplicationResponseStreamAsync()` - 其他使用相同 Endpoint 的模型 # 示例 +查看 [Snapshots.cs](./test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs) 获得 API 调用参数示例. + 查看 [测试](./test) 获得更多 API 使用示例。 +## 文本生成 + +使用 `dashScopeClient.GetTextCompletionAsync` 和 `dashScopeClient.GetTextCompletionStreamAsync` 来直接访问文本生成接口。 + +相关文档:https://help.aliyun.com/zh/model-studio/user-guide/text-generation/ + +```csharp +var completion = await dashScopeClient.GetTextCompletionAsync( + new ModelRequest + { + Model = "your-model-name", + Input = new TextGenerationInput { Prompt = prompt }, + Parameters = new TextGenerationParameters() + { + // control parameters as you wish. + EnableSearch = true + } + }); + +var completions = dashScopeClient.GetTextCompletionStreamAsync( + new ModelRequest + { + Model = "your-model-name", + Input = new TextGenerationInput { Messages = [TextChatMessage.System("you are a helpful assistant"), TextChatMessage.User("How are you?")] }, + Parameters = new TextGenerationParameters() + { + // control parameters as you wish. + EnableSearch = true, + IncreamentalOutput = true + } + }); +``` + ## 单轮对话 ```csharp @@ -108,6 +144,19 @@ var completion = await client.GetQWenChatCompletionAsync(QWenLlm.QWenMax, histor Console.WriteLine(completion.Output.Choices[0].Message.Content); // The number is 42 ``` +## 推理 + +使用推理模型时,模型的思考过程可以通过 `ReasoningContent` 属性获取。 + +```csharp +var history = new List +{ + TextChatMessage.User("Calculate 1+1") +}; +var completion = await client.GetDeepSeekChatCompletionAsync(DeepSeekLlm.DeepSeekR1, history); +Console.WriteLine(completion.Output.Choices[0]!.Message.ReasoningContent); +``` + ## 工具调用 创建一个可供模型使用的方法。 diff --git a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs index 3e2561f..11b86af 100644 --- a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs +++ b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs @@ -183,7 +183,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( { update.Contents.Add( new UsageContent( - new UsageDetails() + new UsageDetails { InputTokenCount = response.Usage.InputTokens, OutputTokenCount = response.Usage.OutputTokens, @@ -208,7 +208,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( RawRepresentation = completion.Messages[0].RawRepresentation, CreatedAt = completion.CreatedAt, FinishReason = completion.FinishReason, - ModelId = completion.ModelId, + ModelId = completion.ModelId }; } else @@ -467,6 +467,7 @@ private IEnumerable ToTextChatMessages( from.Text, from.AuthorName, null, + null, functionCall.Count > 0 ? functionCall : null); } } diff --git a/src/Cnblogs.DashScope.Core/TextChatMessage.cs b/src/Cnblogs.DashScope.Core/TextChatMessage.cs index 71d6fd8..7191191 100644 --- a/src/Cnblogs.DashScope.Core/TextChatMessage.cs +++ b/src/Cnblogs.DashScope.Core/TextChatMessage.cs @@ -10,6 +10,7 @@ namespace Cnblogs.DashScope.Core; /// 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. +/// Reasoning content for reasoning model. /// Calls to the function. [method: JsonConstructor] public record TextChatMessage( @@ -17,6 +18,7 @@ public record TextChatMessage( string Content, string? Name = null, bool? Partial = null, + string? ReasoningContent = null, List? ToolCalls = null) : IMessage { /// @@ -84,11 +86,17 @@ public static TextChatMessage System(string content) /// The content of the message. /// When set to true, content of this message would be the prefix of next model output. /// Author name. + /// Think content when reasoning. /// Tool calls by model. /// - public static TextChatMessage Assistant(string content, bool? partial = null, string? name = null, List? toolCalls = null) + public static TextChatMessage Assistant( + string content, + bool? partial = null, + string? name = null, + string? reasoningContent = null, + List? toolCalls = null) { - return new TextChatMessage(DashScopeRoleNames.Assistant, content, name, partial, toolCalls); + return new TextChatMessage(DashScopeRoleNames.Assistant, content, name, partial, reasoningContent, toolCalls); } /// diff --git a/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlm.cs b/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlm.cs new file mode 100644 index 0000000..b5ce953 --- /dev/null +++ b/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlm.cs @@ -0,0 +1,17 @@ +namespace Cnblogs.DashScope.Sdk.DeepSeek; + +/// +/// DeepSeek models. +/// +public enum DeepSeekLlm +{ + /// + /// deepseek-v3 model. + /// + DeepSeekV3 = 1, + + /// + /// deepseek-r1 model. + /// + DeepSeekR1 = 2 +} diff --git a/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlmName.cs b/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlmName.cs new file mode 100644 index 0000000..f0c8bfa --- /dev/null +++ b/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekLlmName.cs @@ -0,0 +1,14 @@ +namespace Cnblogs.DashScope.Sdk.DeepSeek; + +internal static class DeepSeekLlmName +{ + public static string GetModelName(this DeepSeekLlm model) + { + return model switch + { + DeepSeekLlm.DeepSeekR1 => "deepseek-r1", + DeepSeekLlm.DeepSeekV3 => "deepseek-v3", + _ => ThrowHelper.UnknownModelName(nameof(model), model) + }; + } +} diff --git a/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekTextGenerationApi.cs b/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekTextGenerationApi.cs new file mode 100644 index 0000000..ecc988e --- /dev/null +++ b/src/Cnblogs.DashScope.Sdk/DeepSeek/DeepSeekTextGenerationApi.cs @@ -0,0 +1,87 @@ +using Cnblogs.DashScope.Core; + +namespace Cnblogs.DashScope.Sdk.DeepSeek; + +/// +/// Extensions for calling DeepSeek models, see: https://help.aliyun.com/zh/model-studio/developer-reference/deepseek +/// +public static class DeepSeekTextGenerationApi +{ + private static TextGenerationParameters StreamingParameters { get; } = new() { IncrementalOutput = true }; + + /// + /// Get text completion from deepseek model. + /// + /// The . + /// The model name. + /// The context messages. + /// + public static async Task> + GetDeepSeekChatCompletionAsync( + this IDashScopeClient client, + DeepSeekLlm model, + IEnumerable messages) + { + return await client.GetDeepSeekChatCompletionAsync(model.GetModelName(), messages); + } + + /// + /// Get text completion from deepseek model. + /// + /// The . + /// The model name. + /// The context messages. + /// + public static async Task> + GetDeepSeekChatCompletionAsync( + this IDashScopeClient client, + string model, + IEnumerable messages) + { + return await client.GetTextCompletionAsync( + new ModelRequest + { + Model = model, + Input = new TextGenerationInput { Messages = messages }, + Parameters = null + }); + } + + /// + /// Get streamed completion from deepseek model. + /// + /// + /// + /// + /// + public static IAsyncEnumerable> + GetDeepSeekChatCompletionStreamAsync( + this IDashScopeClient client, + DeepSeekLlm model, + IEnumerable messages) + { + return client.GetDeepSeekChatCompletionStreamAsync(model.GetModelName(), messages); + } + + /// + /// Get streamed completion from deepseek model. + /// + /// + /// + /// + /// + public static IAsyncEnumerable> + GetDeepSeekChatCompletionStreamAsync( + this IDashScopeClient client, + string model, + IEnumerable messages) + { + return client.GetTextCompletionStreamAsync( + new ModelRequest + { + Model = model, + Input = new TextGenerationInput { Messages = messages }, + Parameters = StreamingParameters + }); + } +} diff --git a/src/Cnblogs.DashScope.Sdk/QWen/QWenLlm.cs b/src/Cnblogs.DashScope.Sdk/QWen/QWenLlm.cs index b8dbc98..99beadd 100644 --- a/src/Cnblogs.DashScope.Sdk/QWen/QWenLlm.cs +++ b/src/Cnblogs.DashScope.Sdk/QWen/QWenLlm.cs @@ -133,5 +133,10 @@ public enum QWenLlm /// /// qvq-72b-preview /// - QwQ72BPreview = 25 + QvQ72BPreview = 25, + + /// + /// qwq-32b + /// + QwQ32B = 26 } diff --git a/src/Cnblogs.DashScope.Sdk/QWen/QWenLlmNames.cs b/src/Cnblogs.DashScope.Sdk/QWen/QWenLlmNames.cs index 8bc299e..a433baf 100644 --- a/src/Cnblogs.DashScope.Sdk/QWen/QWenLlmNames.cs +++ b/src/Cnblogs.DashScope.Sdk/QWen/QWenLlmNames.cs @@ -30,7 +30,8 @@ public static string GetModelName(this QWenLlm llm) QWenLlm.QWenPlusLatest => "qwen-plus-latest", QWenLlm.QWenTurboLatest => "qwen-turbo-latest", QWenLlm.QwQ32BPreview => "qwq-32b-preview", - QWenLlm.QwQ72BPreview => "qwq-72b-preview", + QWenLlm.QvQ72BPreview => "qvq-72b-preview", + QWenLlm.QwQ32B => "qwq-32b", _ => ThrowHelper.UnknownModelName(nameof(llm), llm) }; } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs new file mode 100644 index 0000000..5bc1956 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs @@ -0,0 +1,74 @@ +using Cnblogs.DashScope.Core; +using Cnblogs.DashScope.Sdk.DeepSeek; +using NSubstitute; + +namespace Cnblogs.DashScope.Sdk.UnitTests; + +public class DeepSeekTextGenerationApiTests +{ + [Fact] + public async Task TextCompletion_UseEnum_SuccessAsync() + { + // Arrange + var client = Substitute.For(); + + // Act + await client.GetDeepSeekChatCompletionAsync(DeepSeekLlm.DeepSeekR1, [TextChatMessage.User("你好")]); + + // Assert + await client.Received().GetTextCompletionAsync( + Arg.Is>( + x => x.Model == "deepseek-r1" && x.Input.Messages!.First().Content == "你好" && x.Parameters == null)); + } + + [Fact] + public async Task TextCompletion_UseCustomModel_SuccessAsync() + { + // Arrange + const string customModel = "deepseek-v3"; + var client = Substitute.For(); + + // Act + await client.GetDeepSeekChatCompletionAsync(customModel, [TextChatMessage.User("你好")]); + + // Assert + await client.Received().GetTextCompletionAsync( + Arg.Is>( + x => x.Model == customModel && x.Input.Messages!.First().Content == "你好" && x.Parameters == null)); + } + + [Fact] + public void StreamCompletion_UseEnum_SuccessAsync() + { + // Arrange + var client = Substitute.For(); + + // Act + _ = client.GetDeepSeekChatCompletionStreamAsync(DeepSeekLlm.DeepSeekV3, [TextChatMessage.User("你好")]); + + // Assert + _ = client.Received().GetTextCompletionStreamAsync( + Arg.Is>( + x => x.Model == "deepseek-v3" + && x.Input.Messages!.First().Content == "你好" + && x.Parameters!.IncrementalOutput == true)); + } + + [Fact] + public void StreamCompletion_CustomModel_SuccessAsync() + { + // Arrange + const string customModel = "deepseek-v3"; + var client = Substitute.For(); + + // Act + _ = client.GetDeepSeekChatCompletionStreamAsync(customModel, [TextChatMessage.User("你好")]); + + // Assert + _ = client.Received().GetTextCompletionStreamAsync( + Arg.Is>( + x => x.Model == customModel + && x.Input.Messages!.First().Content == "你好" + && x.Parameters!.IncrementalOutput == true)); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.body.json new file mode 100644 index 0000000..1d17aaa --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.body.json @@ -0,0 +1,14 @@ +{ + "model": "deepseek-r1", + "input": { + "messages": [ + { + "role": "user", + "content": "请问 1+1 是多少?" + } + ] + }, + "parameters": { + "incremental_output": false + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt new file mode 100644 index 0000000..4e58a1c --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-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: 273 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt new file mode 100644 index 0000000..9bc4376 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt @@ -0,0 +1 @@ +{"output":{"choices":[{"finish_reason":"stop","message":{"role":"assistant","content":"1 + 1 等于 **2**。这是基础的算术加法,当我们将一个单位与另一个单位相加时,总和为两个单位。","reasoning_content":"嗯,用户问1加1等于多少。这个问题看起来很简单,但可能有一些需要注意的地方。首先,我得确认用户是不是真的在问基本的数学问题,还是有其他的意图,比如测试我的反应或者开玩笑。\n\n1加1在基础算术里确实是2,但有时候可能会有不同的解释,比如在二进制中1+1等于10,或者在逻辑学中有时候表示为1,如果是布尔代数的话。不过通常情况下,用户可能只需要最直接的答案,也就是2。\n\n不过也有可能用户想考察我是否能够处理更复杂的情况,或者是否有隐藏的意思。比如,在某些情况下,1加1可能被用来比喻合作的效果,比如“1+1大于2”,但这可能超出了当前问题的范围。\n\n我需要考虑用户的背景。如果用户是小学生,那么直接回答2是正确的,并且可能需要鼓励的话。如果是成年人,可能还是同样的答案,但不需要额外的解释。如果用户来自数学或计算机领域,可能需要确认是否需要其他进制的答案,但通常默认是十进制。\n\n另外,检查是否有拼写错误或非阿拉伯数字的情况,比如罗马数字的I+I,但问题里明确写的是1+1,所以应该是阿拉伯数字。\n\n总结下来,最安全也是最正确的答案就是2。不过为了确保,可以简短地确认用户的意图,但按照常规问题处理,直接回答即可。"}}]},"usage":{"total_tokens":313,"output_tokens":302,"input_tokens":11},"request_id":"7039d8ff-89e0-9191-b4d3-0d258a7d70e1"} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt new file mode 100644 index 0000000..5767ccb --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding +content-type: application/json +x-request-id: 7039d8ff-89e0-9191-b4d3-0d258a7d70e1 +x-dashscope-timeout: 180 +x-dashscope-call-gateway: true +x-dashscope-finished: true +req-cost-time: 11619 +req-arrive-time: 1742405583711 +resp-start-time: 1742405595330 +x-envoy-upstream-service-time: 11610 +content-encoding: gzip +date: Wed, 19 Mar 2025 17:33:15 GMT +server: istio-envoy +transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.body.json b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.body.json new file mode 100644 index 0000000..9e514e1 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.body.json @@ -0,0 +1,14 @@ +{ + "model": "deepseek-r1", + "input": { + "messages": [ + { + "role": "user", + "content": "请问 1+1 是多少?" + } + ] + }, + "parameters": { + "incremental_output": true + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.header.txt new file mode 100644 index 0000000..62df9ec --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.header.txt @@ -0,0 +1,7 @@ +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: 309 diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.body.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.body.txt new file mode 100644 index 0000000..40e024f --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.body.txt @@ -0,0 +1,1975 @@ +id:1 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"嗯","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":14,"input_tokens":11,"output_tokens":3},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:2 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":15,"input_tokens":11,"output_tokens":4},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:3 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":16,"input_tokens":11,"output_tokens":5},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:4 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":17,"input_tokens":11,"output_tokens":6},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:5 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":18,"input_tokens":11,"output_tokens":7},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:6 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":19,"input_tokens":11,"output_tokens":8},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:7 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":20,"input_tokens":11,"output_tokens":9},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:8 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":21,"input_tokens":11,"output_tokens":10},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:9 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"多少","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":22,"input_tokens":11,"output_tokens":11},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:10 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":23,"input_tokens":11,"output_tokens":12},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:11 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这个问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":24,"input_tokens":11,"output_tokens":13},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:12 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"看起来","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":25,"input_tokens":11,"output_tokens":14},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:13 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"很简单","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":26,"input_tokens":11,"output_tokens":15},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:14 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":27,"input_tokens":11,"output_tokens":16},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:15 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但其实","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":28,"input_tokens":11,"output_tokens":17},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:16 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":29,"input_tokens":11,"output_tokens":18},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:17 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"有很多","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":30,"input_tokens":11,"output_tokens":19},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:18 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"种","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":31,"input_tokens":11,"output_tokens":20},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:19 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":32,"input_tokens":11,"output_tokens":21},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:20 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需要考虑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":33,"input_tokens":11,"output_tokens":22},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:21 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":34,"input_tokens":11,"output_tokens":23},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:22 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"首先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":35,"input_tokens":11,"output_tokens":24},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:23 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":36,"input_tokens":11,"output_tokens":25},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:24 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我得","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":37,"input_tokens":11,"output_tokens":26},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:25 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"确定","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":38,"input_tokens":11,"output_tokens":27},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:26 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":39,"input_tokens":11,"output_tokens":28},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:27 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是不是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":40,"input_tokens":11,"output_tokens":29},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:28 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":41,"input_tokens":11,"output_tokens":30},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:29 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":42,"input_tokens":11,"output_tokens":31},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:30 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":43,"input_tokens":11,"output_tokens":32},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:31 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"上的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":44,"input_tokens":11,"output_tokens":33},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:32 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"基本","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":45,"input_tokens":11,"output_tokens":34},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:33 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加法","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":46,"input_tokens":11,"output_tokens":35},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:34 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":47,"input_tokens":11,"output_tokens":36},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:35 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"通常","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":48,"input_tokens":11,"output_tokens":37},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:36 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"来说","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":49,"input_tokens":11,"output_tokens":38},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:37 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":50,"input_tokens":11,"output_tokens":39},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:38 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":51,"input_tokens":11,"output_tokens":40},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:39 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":52,"input_tokens":11,"output_tokens":41},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:40 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":53,"input_tokens":11,"output_tokens":42},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:41 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":54,"input_tokens":11,"output_tokens":43},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:42 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":55,"input_tokens":11,"output_tokens":44},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:43 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":56,"input_tokens":11,"output_tokens":45},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:44 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":57,"input_tokens":11,"output_tokens":46},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:45 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":58,"input_tokens":11,"output_tokens":47},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:46 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"里的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":59,"input_tokens":11,"output_tokens":48},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:47 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"基本","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":60,"input_tokens":11,"output_tokens":49},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:48 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"事实","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":61,"input_tokens":11,"output_tokens":50},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:49 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":62,"input_tokens":11,"output_tokens":51},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:50 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"根据","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":63,"input_tokens":11,"output_tokens":52},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:51 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"皮","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":64,"input_tokens":11,"output_tokens":53},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:52 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"亚","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":65,"input_tokens":11,"output_tokens":54},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:53 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"诺","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":66,"input_tokens":11,"output_tokens":55},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:54 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"公","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":67,"input_tokens":11,"output_tokens":56},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:55 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"理","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":68,"input_tokens":11,"output_tokens":57},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:56 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":69,"input_tokens":11,"output_tokens":58},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:57 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"基本的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":70,"input_tokens":11,"output_tokens":59},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:58 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"算术","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":71,"input_tokens":11,"output_tokens":60},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:59 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"规则","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":72,"input_tokens":11,"output_tokens":61},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:60 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":73,"input_tokens":11,"output_tokens":62},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:61 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":74,"input_tokens":11,"output_tokens":63},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:62 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":75,"input_tokens":11,"output_tokens":64},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:63 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"有时候","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":76,"input_tokens":11,"output_tokens":65},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:64 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":77,"input_tokens":11,"output_tokens":66},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:65 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能有","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":78,"input_tokens":11,"output_tokens":67},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:66 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"隐藏","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":79,"input_tokens":11,"output_tokens":68},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:67 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的含义","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":80,"input_tokens":11,"output_tokens":69},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:68 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":81,"input_tokens":11,"output_tokens":70},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:69 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"特别是在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":82,"input_tokens":11,"output_tokens":71},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:70 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不同的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":83,"input_tokens":11,"output_tokens":72},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:71 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"语境","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":84,"input_tokens":11,"output_tokens":73},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:72 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"下","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":85,"input_tokens":11,"output_tokens":74},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:73 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":86,"input_tokens":11,"output_tokens":75},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:74 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":87,"input_tokens":11,"output_tokens":76},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:75 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能会","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":88,"input_tokens":11,"output_tokens":77},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:76 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不同","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":89,"input_tokens":11,"output_tokens":78},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:77 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":90,"input_tokens":11,"output_tokens":79},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:78 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":91,"input_tokens":11,"output_tokens":80},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:79 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":92,"input_tokens":11,"output_tokens":81},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:80 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"二进制","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":93,"input_tokens":11,"output_tokens":82},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:81 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":94,"input_tokens":11,"output_tokens":83},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:82 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":95,"input_tokens":11,"output_tokens":84},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:83 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":96,"input_tokens":11,"output_tokens":85},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:84 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":97,"input_tokens":11,"output_tokens":86},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:85 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":98,"input_tokens":11,"output_tokens":87},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:86 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":99,"input_tokens":11,"output_tokens":88},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:87 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"10","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":100,"input_tokens":11,"output_tokens":89},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:88 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":101,"input_tokens":11,"output_tokens":90},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:89 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":102,"input_tokens":11,"output_tokens":91},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:90 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"布尔","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":103,"input_tokens":11,"output_tokens":92},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:91 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"代数","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":104,"input_tokens":11,"output_tokens":93},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:92 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":105,"input_tokens":11,"output_tokens":94},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:93 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":106,"input_tokens":11,"output_tokens":95},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:94 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":107,"input_tokens":11,"output_tokens":96},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:95 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":108,"input_tokens":11,"output_tokens":97},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:96 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":109,"input_tokens":11,"output_tokens":98},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:97 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":110,"input_tokens":11,"output_tokens":99},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:98 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":111,"input_tokens":11,"output_tokens":100},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:99 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":112,"input_tokens":11,"output_tokens":101},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:100 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":113,"input_tokens":11,"output_tokens":102},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:101 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"如果是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":114,"input_tokens":11,"output_tokens":103},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:102 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"逻辑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":115,"input_tokens":11,"output_tokens":104},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:103 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":116,"input_tokens":11,"output_tokens":105},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:104 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"运算","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":117,"input_tokens":11,"output_tokens":106},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:105 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的话","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":118,"input_tokens":11,"output_tokens":107},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:106 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":119,"input_tokens":11,"output_tokens":108},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:107 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":120,"input_tokens":11,"output_tokens":109},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:108 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"大部分","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":121,"input_tokens":11,"output_tokens":110},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:109 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况下","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":122,"input_tokens":11,"output_tokens":111},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:110 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":123,"input_tokens":11,"output_tokens":112},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:111 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"尤其是在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":124,"input_tokens":11,"output_tokens":113},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:112 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"日常","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":125,"input_tokens":11,"output_tokens":114},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:113 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"交流","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":126,"input_tokens":11,"output_tokens":115},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:114 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":127,"input_tokens":11,"output_tokens":116},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:115 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":128,"input_tokens":11,"output_tokens":117},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:116 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"人们","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":129,"input_tokens":11,"output_tokens":118},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:117 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"提到","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":130,"input_tokens":11,"output_tokens":119},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:118 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":131,"input_tokens":11,"output_tokens":120},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:119 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":132,"input_tokens":11,"output_tokens":121},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:120 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":133,"input_tokens":11,"output_tokens":122},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:121 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的时候","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":134,"input_tokens":11,"output_tokens":123},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:122 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"都是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":135,"input_tokens":11,"output_tokens":124},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:123 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"指","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":136,"input_tokens":11,"output_tokens":125},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:124 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"十进制","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":137,"input_tokens":11,"output_tokens":126},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:125 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加法","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":138,"input_tokens":11,"output_tokens":127},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:126 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":139,"input_tokens":11,"output_tokens":128},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:127 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"结果","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":140,"input_tokens":11,"output_tokens":129},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:128 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"自然是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":141,"input_tokens":11,"output_tokens":130},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:129 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":142,"input_tokens":11,"output_tokens":131},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:130 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":143,"input_tokens":11,"output_tokens":132},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:131 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":144,"input_tokens":11,"output_tokens":133},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:132 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"也有可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":145,"input_tokens":11,"output_tokens":134},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:133 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":146,"input_tokens":11,"output_tokens":135},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:134 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":147,"input_tokens":11,"output_tokens":136},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:135 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"测试","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":148,"input_tokens":11,"output_tokens":137},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:136 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":149,"input_tokens":11,"output_tokens":138},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:137 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"反应","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":150,"input_tokens":11,"output_tokens":139},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:138 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":151,"input_tokens":11,"output_tokens":140},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:139 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":152,"input_tokens":11,"output_tokens":141},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:140 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"想","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":153,"input_tokens":11,"output_tokens":142},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:141 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"看看","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":154,"input_tokens":11,"output_tokens":143},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:142 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我会","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":155,"input_tokens":11,"output_tokens":144},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:143 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不会","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":156,"input_tokens":11,"output_tokens":145},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:144 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"考虑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":157,"input_tokens":11,"output_tokens":146},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:145 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":158,"input_tokens":11,"output_tokens":147},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:146 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能性","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":159,"input_tokens":11,"output_tokens":148},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:147 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":160,"input_tokens":11,"output_tokens":149},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:148 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":161,"input_tokens":11,"output_tokens":150},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:149 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":162,"input_tokens":11,"output_tokens":151},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:150 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"特定的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":163,"input_tokens":11,"output_tokens":152},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:151 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"谜","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":164,"input_tokens":11,"output_tokens":153},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:152 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"语","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":165,"input_tokens":11,"output_tokens":154},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:153 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":166,"input_tokens":11,"output_tokens":155},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:154 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"笑话","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":167,"input_tokens":11,"output_tokens":156},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:155 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":168,"input_tokens":11,"output_tokens":157},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:156 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":169,"input_tokens":11,"output_tokens":158},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:157 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":170,"input_tokens":11,"output_tokens":159},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:158 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":171,"input_tokens":11,"output_tokens":160},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:159 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":172,"input_tokens":11,"output_tokens":161},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:160 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":173,"input_tokens":11,"output_tokens":162},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:161 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":174,"input_tokens":11,"output_tokens":163},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:162 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":175,"input_tokens":11,"output_tokens":164},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:163 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"“","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":176,"input_tokens":11,"output_tokens":165},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:164 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":177,"input_tokens":11,"output_tokens":166},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:165 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"滴水","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":178,"input_tokens":11,"output_tokens":167},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:166 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":179,"input_tokens":11,"output_tokens":168},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:167 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":180,"input_tokens":11,"output_tokens":169},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:168 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"滴水","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":181,"input_tokens":11,"output_tokens":170},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:169 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"还是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":182,"input_tokens":11,"output_tokens":171},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:170 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":183,"input_tokens":11,"output_tokens":172},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:171 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"滴水","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":184,"input_tokens":11,"output_tokens":173},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:172 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"”,","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":185,"input_tokens":11,"output_tokens":174},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:173 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":186,"input_tokens":11,"output_tokens":175},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:174 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"类似的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":187,"input_tokens":11,"output_tokens":176},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:175 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"文字","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":188,"input_tokens":11,"output_tokens":177},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:176 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"游戏","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":189,"input_tokens":11,"output_tokens":178},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:177 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":190,"input_tokens":11,"output_tokens":179},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:178 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":191,"input_tokens":11,"output_tokens":180},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:179 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"根据","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":192,"input_tokens":11,"output_tokens":181},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:180 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"常规","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":193,"input_tokens":11,"output_tokens":182},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:181 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":194,"input_tokens":11,"output_tokens":183},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:182 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":195,"input_tokens":11,"output_tokens":184},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:183 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我应该","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":196,"input_tokens":11,"output_tokens":185},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:184 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":197,"input_tokens":11,"output_tokens":186},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:185 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"给出","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":198,"input_tokens":11,"output_tokens":187},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:186 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"正确的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":199,"input_tokens":11,"output_tokens":188},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:187 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":200,"input_tokens":11,"output_tokens":189},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:188 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":201,"input_tokens":11,"output_tokens":190},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:189 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":202,"input_tokens":11,"output_tokens":191},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:190 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"再","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":203,"input_tokens":11,"output_tokens":192},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:191 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"补充","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":204,"input_tokens":11,"output_tokens":193},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:192 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":205,"input_tokens":11,"output_tokens":194},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:193 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":206,"input_tokens":11,"output_tokens":195},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:194 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":207,"input_tokens":11,"output_tokens":196},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:195 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":208,"input_tokens":11,"output_tokens":197},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:196 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这样","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":209,"input_tokens":11,"output_tokens":198},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:197 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"既","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":210,"input_tokens":11,"output_tokens":199},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:198 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"准确","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":211,"input_tokens":11,"output_tokens":200},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:199 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"又","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":212,"input_tokens":11,"output_tokens":201},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:200 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"全面","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":213,"input_tokens":11,"output_tokens":202},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:201 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":214,"input_tokens":11,"output_tokens":203},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:202 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"所以","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":215,"input_tokens":11,"output_tokens":204},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:203 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":216,"input_tokens":11,"output_tokens":205},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:204 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":217,"input_tokens":11,"output_tokens":206},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:205 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"回答","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":218,"input_tokens":11,"output_tokens":207},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:206 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":219,"input_tokens":11,"output_tokens":208},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:207 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":220,"input_tokens":11,"output_tokens":209},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:208 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"然后","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":221,"input_tokens":11,"output_tokens":210},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:209 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"解释","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":222,"input_tokens":11,"output_tokens":211},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:210 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":223,"input_tokens":11,"output_tokens":212},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:211 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能性","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":224,"input_tokens":11,"output_tokens":213},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:212 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":225,"input_tokens":11,"output_tokens":214},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:213 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":226,"input_tokens":11,"output_tokens":215},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:214 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":227,"input_tokens":11,"output_tokens":216},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:215 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":228,"input_tokens":11,"output_tokens":217},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:216 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"看起来","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":229,"input_tokens":11,"output_tokens":218},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:217 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"直接","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":230,"input_tokens":11,"output_tokens":219},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:218 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":231,"input_tokens":11,"output_tokens":220},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:219 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":232,"input_tokens":11,"output_tokens":221},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:220 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不需要","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":233,"input_tokens":11,"output_tokens":222},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:221 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"太","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":234,"input_tokens":11,"output_tokens":223},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:222 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"复杂的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":235,"input_tokens":11,"output_tokens":224},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:223 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"解释","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":236,"input_tokens":11,"output_tokens":225},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:224 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":237,"input_tokens":11,"output_tokens":226},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:225 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":238,"input_tokens":11,"output_tokens":227},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:226 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"为了","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":239,"input_tokens":11,"output_tokens":228},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:227 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"保险","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":240,"input_tokens":11,"output_tokens":229},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:228 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"起见","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":241,"input_tokens":11,"output_tokens":230},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:229 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":242,"input_tokens":11,"output_tokens":231},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:230 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"还是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":243,"input_tokens":11,"output_tokens":232},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:231 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"确认","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":244,"input_tokens":11,"output_tokens":233},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:232 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"一下","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":245,"input_tokens":11,"output_tokens":234},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:233 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是否有","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":246,"input_tokens":11,"output_tokens":235},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:234 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":247,"input_tokens":11,"output_tokens":236},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:235 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"意图","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":248,"input_tokens":11,"output_tokens":237},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:236 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比较好","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":249,"input_tokens":11,"output_tokens":238},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:237 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":250,"input_tokens":11,"output_tokens":239},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:238 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":251,"input_tokens":11,"output_tokens":240},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:239 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":252,"input_tokens":11,"output_tokens":241},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:240 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":253,"input_tokens":11,"output_tokens":242},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:241 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"只是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":254,"input_tokens":11,"output_tokens":243},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:242 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"单纯","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":255,"input_tokens":11,"output_tokens":244},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:243 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"想知道","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":256,"input_tokens":11,"output_tokens":245},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:244 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":257,"input_tokens":11,"output_tokens":246},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:245 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":258,"input_tokens":11,"output_tokens":247},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:246 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"所以","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":259,"input_tokens":11,"output_tokens":248},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:247 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"直接","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":260,"input_tokens":11,"output_tokens":249},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:248 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"回答","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":261,"input_tokens":11,"output_tokens":250},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:249 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":262,"input_tokens":11,"output_tokens":251},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:250 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"即可","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":263,"input_tokens":11,"output_tokens":252},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:251 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":264,"input_tokens":11,"output_tokens":253},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:252 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需要","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":265,"input_tokens":11,"output_tokens":254},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:253 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"平衡","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":266,"input_tokens":11,"output_tokens":255},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:254 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"简洁","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":267,"input_tokens":11,"output_tokens":256},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:255 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"和","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":268,"input_tokens":11,"output_tokens":257},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:256 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"全面","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":269,"input_tokens":11,"output_tokens":258},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:257 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"性","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":270,"input_tokens":11,"output_tokens":259},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:258 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":271,"input_tokens":11,"output_tokens":260},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:259 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":272,"input_tokens":11,"output_tokens":261},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:260 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":273,"input_tokens":11,"output_tokens":262},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:261 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"给出","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":274,"input_tokens":11,"output_tokens":263},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:262 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"直接","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":275,"input_tokens":11,"output_tokens":264},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:263 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":276,"input_tokens":11,"output_tokens":265},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:264 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":277,"input_tokens":11,"output_tokens":266},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:265 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"然后","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":278,"input_tokens":11,"output_tokens":267},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:266 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"简单","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":279,"input_tokens":11,"output_tokens":268},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:267 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"说明","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":280,"input_tokens":11,"output_tokens":269},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:268 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":281,"input_tokens":11,"output_tokens":270},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:269 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":282,"input_tokens":11,"output_tokens":271},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:270 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的存在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":283,"input_tokens":11,"output_tokens":272},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:271 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":284,"input_tokens":11,"output_tokens":273},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:272 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这样","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":285,"input_tokens":11,"output_tokens":274},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:273 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"既","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":286,"input_tokens":11,"output_tokens":275},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:274 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"满足","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":287,"input_tokens":11,"output_tokens":276},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:275 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需求","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":288,"input_tokens":11,"output_tokens":277},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:276 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":289,"input_tokens":11,"output_tokens":278},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:277 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"又","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":290,"input_tokens":11,"output_tokens":279},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:278 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"避免","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":291,"input_tokens":11,"output_tokens":280},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:279 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"信息","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":292,"input_tokens":11,"output_tokens":281},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:280 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":293,"input_tokens":11,"output_tokens":282},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:281 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"载","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":294,"input_tokens":11,"output_tokens":283},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:282 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":295,"input_tokens":11,"output_tokens":284},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:283 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"总之","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":296,"input_tokens":11,"output_tokens":285},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:284 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":297,"input_tokens":11,"output_tokens":286},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:285 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"核心","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":298,"input_tokens":11,"output_tokens":287},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:286 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":299,"input_tokens":11,"output_tokens":288},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:287 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"应该是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":300,"input_tokens":11,"output_tokens":289},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:288 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":301,"input_tokens":11,"output_tokens":290},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:289 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":302,"input_tokens":11,"output_tokens":291},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:290 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":303,"input_tokens":11,"output_tokens":292},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:291 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"根据","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":304,"input_tokens":11,"output_tokens":293},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:292 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":305,"input_tokens":11,"output_tokens":294},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:293 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"适当","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":306,"input_tokens":11,"output_tokens":295},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:294 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"扩展","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":307,"input_tokens":11,"output_tokens":296},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:295 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":308,"input_tokens":11,"output_tokens":297},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:296 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":311,"input_tokens":11,"output_tokens":300},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:297 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"+","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":312,"input_tokens":11,"output_tokens":301},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:298 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":313,"input_tokens":11,"output_tokens":302},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:299 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" 在","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":315,"input_tokens":11,"output_tokens":304},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:300 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"基础","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":316,"input_tokens":11,"output_tokens":305},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:301 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"算术","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":317,"input_tokens":11,"output_tokens":306},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:302 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"中的","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":318,"input_tokens":11,"output_tokens":307},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:303 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"答案是","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":319,"input_tokens":11,"output_tokens":308},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:304 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":320,"input_tokens":11,"output_tokens":309},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:305 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"2","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":321,"input_tokens":11,"output_tokens":310},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:306 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":322,"input_tokens":11,"output_tokens":311},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:307 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":323,"input_tokens":11,"output_tokens":312},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:308 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"\n\n不过","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":325,"input_tokens":11,"output_tokens":314},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:309 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":",","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":326,"input_tokens":11,"output_tokens":315},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:310 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"根据","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":327,"input_tokens":11,"output_tokens":316},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:311 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"不同的","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":328,"input_tokens":11,"output_tokens":317},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:312 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"数学","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":329,"input_tokens":11,"output_tokens":318},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:313 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"或","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":330,"input_tokens":11,"output_tokens":319},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:314 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"逻辑","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":331,"input_tokens":11,"output_tokens":320},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:315 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"系统","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":332,"input_tokens":11,"output_tokens":321},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:316 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":",","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":333,"input_tokens":11,"output_tokens":322},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:317 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"结果","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":334,"input_tokens":11,"output_tokens":323},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:318 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"可能","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":335,"input_tokens":11,"output_tokens":324},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:319 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"不同","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":336,"input_tokens":11,"output_tokens":325},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:320 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":337,"input_tokens":11,"output_tokens":326},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:321 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"\n-","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":338,"input_tokens":11,"output_tokens":327},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:322 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":339,"input_tokens":11,"output_tokens":328},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:323 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"二进制","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":340,"input_tokens":11,"output_tokens":329},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:324 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":341,"input_tokens":11,"output_tokens":330},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:325 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":342,"input_tokens":11,"output_tokens":331},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:326 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":343,"input_tokens":11,"output_tokens":332},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:327 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"+","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":344,"input_tokens":11,"output_tokens":333},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:328 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":345,"input_tokens":11,"output_tokens":334},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:329 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" =","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":346,"input_tokens":11,"output_tokens":335},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:330 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" 10","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":348,"input_tokens":11,"output_tokens":337},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:331 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"(","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":349,"input_tokens":11,"output_tokens":338},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:332 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"读","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":350,"input_tokens":11,"output_tokens":339},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:333 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"作","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":351,"input_tokens":11,"output_tokens":340},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:334 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"“","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":352,"input_tokens":11,"output_tokens":341},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:335 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"一","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":353,"input_tokens":11,"output_tokens":342},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:336 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"零","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":354,"input_tokens":11,"output_tokens":343},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:337 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"”","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":355,"input_tokens":11,"output_tokens":344},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:338 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":")。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":356,"input_tokens":11,"output_tokens":345},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:339 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"\n-","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":357,"input_tokens":11,"output_tokens":346},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:340 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":358,"input_tokens":11,"output_tokens":347},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:341 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"布尔","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":359,"input_tokens":11,"output_tokens":348},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:342 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"代数","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":360,"input_tokens":11,"output_tokens":349},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:343 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":361,"input_tokens":11,"output_tokens":350},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:344 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":362,"input_tokens":11,"output_tokens":351},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:345 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":363,"input_tokens":11,"output_tokens":352},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:346 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"+","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":364,"input_tokens":11,"output_tokens":353},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:347 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":365,"input_tokens":11,"output_tokens":354},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:348 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" =","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":366,"input_tokens":11,"output_tokens":355},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:349 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" 1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":368,"input_tokens":11,"output_tokens":357},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:350 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"(","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":369,"input_tokens":11,"output_tokens":358},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:351 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"逻辑","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":370,"input_tokens":11,"output_tokens":359},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:352 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"“","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":371,"input_tokens":11,"output_tokens":360},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:353 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"或","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":372,"input_tokens":11,"output_tokens":361},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:354 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"”","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":373,"input_tokens":11,"output_tokens":362},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:355 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"运算","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":374,"input_tokens":11,"output_tokens":363},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:356 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":")。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":375,"input_tokens":11,"output_tokens":364},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:357 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"\n-","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":376,"input_tokens":11,"output_tokens":365},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:358 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":377,"input_tokens":11,"output_tokens":366},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:359 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"抽象","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":378,"input_tokens":11,"output_tokens":367},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:360 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"场景","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":379,"input_tokens":11,"output_tokens":368},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:361 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":380,"input_tokens":11,"output_tokens":369},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:362 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":381,"input_tokens":11,"output_tokens":370},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:363 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"如","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":382,"input_tokens":11,"output_tokens":371},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:364 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"“","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":383,"input_tokens":11,"output_tokens":372},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:365 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":384,"input_tokens":11,"output_tokens":373},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:366 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"滴水","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":385,"input_tokens":11,"output_tokens":374},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:367 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" +","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":386,"input_tokens":11,"output_tokens":375},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:368 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" 1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":388,"input_tokens":11,"output_tokens":377},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:369 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"滴水","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":389,"input_tokens":11,"output_tokens":378},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:370 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" =","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":390,"input_tokens":11,"output_tokens":379},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:371 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" 1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":392,"input_tokens":11,"output_tokens":381},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:372 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"大","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":393,"input_tokens":11,"output_tokens":382},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:373 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"滴水","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":394,"input_tokens":11,"output_tokens":383},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:374 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"”(","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":395,"input_tokens":11,"output_tokens":384},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:375 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"非","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":396,"input_tokens":11,"output_tokens":385},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:376 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"数学","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":397,"input_tokens":11,"output_tokens":386},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:377 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"意义的","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":398,"input_tokens":11,"output_tokens":387},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:378 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"合并","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":399,"input_tokens":11,"output_tokens":388},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:379 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":")。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":400,"input_tokens":11,"output_tokens":389},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:380 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"\n\n日常","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":401,"input_tokens":11,"output_tokens":390},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:381 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"问题","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":402,"input_tokens":11,"output_tokens":391},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:382 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"中","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":403,"input_tokens":11,"output_tokens":392},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:383 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"默认","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":404,"input_tokens":11,"output_tokens":393},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:384 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"使用","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":405,"input_tokens":11,"output_tokens":394},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:385 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"十进制","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":406,"input_tokens":11,"output_tokens":395},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:386 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"算术","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":407,"input_tokens":11,"output_tokens":396},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:387 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":",","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":408,"input_tokens":11,"output_tokens":397},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:388 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"因此","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":409,"input_tokens":11,"output_tokens":398},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:389 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"答案是","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":410,"input_tokens":11,"output_tokens":399},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:390 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":411,"input_tokens":11,"output_tokens":400},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:391 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"2","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":412,"input_tokens":11,"output_tokens":401},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:392 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":413,"input_tokens":11,"output_tokens":402},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:393 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":" 😊","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":416,"input_tokens":11,"output_tokens":405},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:394 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":417,"input_tokens":11,"output_tokens":406},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + +id:395 +event:result +:HTTP_STATUS/200 +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"","role":"assistant"},"finish_reason":"stop"}]},"usage":{"total_tokens":417,"input_tokens":11,"output_tokens":406},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.header.txt b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.header.txt new file mode 100644 index 0000000..668bf11 --- /dev/null +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.header.txt @@ -0,0 +1,14 @@ +HTTP/1.1 200 OK +vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers +x-request-id: e4ad5d0f-8019-9716-adc6-eae1411d3c9a +content-type: text/event-stream;charset=UTF-8 +x-dashscope-call-gateway: true +x-dashscope-timeout: 180 +x-dashscope-finished: false +req-cost-time: 500 +req-arrive-time: 1742405632039 +resp-start-time: 1742405632540 +x-envoy-upstream-service-time: 490 +date: Wed, 19 Mar 2025 17:33:52 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 eda61e4..de32581 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs @@ -68,18 +68,27 @@ public async Task SingleCompletion_MessageFormatNoSse_SuccessAsync( response.Should().BeEquivalentTo(testCase.ResponseModel); } - [Fact] - public async Task SingleCompletion_MessageFormatSse_SuccessAsync() + [Theory] + [MemberData(nameof(SingleGenerationMessageSseFormatData))] + public async Task SingleCompletion_MessageFormatSse_SuccessAsync( + RequestSnapshot, + ModelResponse> snapshot) { // Arrange const bool sse = true; - var testCase = Snapshots.TextGeneration.MessageFormat.SingleMessageIncremental; + var testCase = snapshot; var (client, handler) = await Sut.GetTestClientAsync(sse, testCase); // Act var message = new StringBuilder(); + var reasoning = new StringBuilder(); var outputs = await client.GetTextCompletionStreamAsync(testCase.RequestModel).ToListAsync(); - outputs.ForEach(x => message.Append(x.Output.Choices![0].Message.Content)); + outputs.ForEach( + x => + { + message.Append(x.Output.Choices![0].Message.Content); + reasoning.Append(x.Output.Choices![0].Message.ReasoningContent ?? string.Empty); + }); // Assert handler.Received().MockSend( @@ -88,8 +97,11 @@ public async Task SingleCompletion_MessageFormatSse_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)); + o => o.Excluding(y => y.Output.Choices![0].Message.Content) + .Excluding(y => y.Output.Choices![0].Message.ReasoningContent)); message.ToString().Should().Be(testCase.ResponseModel.Output.Choices![0].Message.Content); + reasoning.ToString().Should() + .Be(testCase.ResponseModel.Output.Choices![0].Message.ReasoningContent ?? string.Empty); } [Theory] @@ -141,9 +153,15 @@ public async Task ConversationCompletion_MessageFormatSse_SuccessAsync( public static readonly TheoryData, ModelResponse>> SingleGenerationMessageFormatData = new( Snapshots.TextGeneration.MessageFormat.SingleMessage, + Snapshots.TextGeneration.MessageFormat.SingleMessageReasoning, Snapshots.TextGeneration.MessageFormat.SingleMessageWithTools, Snapshots.TextGeneration.MessageFormat.SingleMessageJson); + public static readonly TheoryData, + ModelResponse>> SingleGenerationMessageSseFormatData = new( + Snapshots.TextGeneration.MessageFormat.SingleMessageIncremental, + Snapshots.TextGeneration.MessageFormat.SingleMessageReasoningIncremental); + public static readonly TheoryData, ModelResponse>> ConversationMessageFormatSseData = new( Snapshots.TextGeneration.MessageFormat.ConversationMessageIncremental, diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs index 4a6e30a..eca1ed8 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs @@ -131,6 +131,44 @@ public static class MessageFormat } }); + public static readonly RequestSnapshot, + ModelResponse> + SingleMessageReasoning = new( + "single-generation-message-reasoning", + new ModelRequest + { + Model = "deepseek-r1", + Input = + new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + Parameters = new TextGenerationParameters + { + IncrementalOutput = false + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1 + 1 等于 **2**。这是基础的算术加法,当我们将一个单位与另一个单位相加时,总和为两个单位。", + reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但可能有一些需要注意的地方。首先,我得确认用户是不是真的在问基本的数学问题,还是有其他的意图,比如测试我的反应或者开玩笑。\n\n1加1在基础算术里确实是2,但有时候可能会有不同的解释,比如在二进制中1+1等于10,或者在逻辑学中有时候表示为1,如果是布尔代数的话。不过通常情况下,用户可能只需要最直接的答案,也就是2。\n\n不过也有可能用户想考察我是否能够处理更复杂的情况,或者是否有隐藏的意思。比如,在某些情况下,1加1可能被用来比喻合作的效果,比如“1+1大于2”,但这可能超出了当前问题的范围。\n\n我需要考虑用户的背景。如果用户是小学生,那么直接回答2是正确的,并且可能需要鼓励的话。如果是成年人,可能还是同样的答案,但不需要额外的解释。如果用户来自数学或计算机领域,可能需要确认是否需要其他进制的答案,但通常默认是十进制。\n\n另外,检查是否有拼写错误或非阿拉伯数字的情况,比如罗马数字的I+I,但问题里明确写的是1+1,所以应该是阿拉伯数字。\n\n总结下来,最安全也是最正确的答案就是2。不过为了确保,可以简短地确认用户的意图,但按照常规问题处理,直接回答即可。") + } + ] + }, + RequestId = "7039d8ff-89e0-9191-b4d3-0d258a7d70e1", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 313, + OutputTokens = 302, + InputTokens = 11 + } + }); + public static readonly RequestSnapshot, ModelResponse> SingleChatClientMessage = new( @@ -266,6 +304,43 @@ public static class MessageFormat InputTokens = 8 } }); + public static readonly RequestSnapshot, + ModelResponse> + SingleMessageReasoningIncremental = new( + "single-generation-message-reasoning", + new ModelRequest + { + Model = "deepseek-r1", + Input = + new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + Parameters = new TextGenerationParameters + { + IncrementalOutput = true + } + }, + new ModelResponse + { + Output = new TextGenerationOutput + { + Choices = + [ + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 在基础算术中的答案是 **2**。\n\n不过,根据不同的数学或逻辑系统,结果可能不同:\n- **二进制**:1+1 = 10(读作“一零”)。\n- **布尔代数**:1+1 = 1(逻辑“或”运算)。\n- **抽象场景**:如“1滴水 + 1滴水 = 1大滴水”(非数学意义的合并)。\n\n日常问题中默认使用十进制算术,因此答案是 **2** \ud83d\ude0a。", + reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但其实可能有很多种情况需要考虑。首先,我得确定用户是不是在问数学上的基本加法。通常来说,1加1等于2,这是数学里的基本事实,根据皮亚诺公理或者基本的算术规则。不过,有时候问题可能有隐藏的含义,特别是在不同的语境下,答案可能会不同。比如在二进制中,1+1等于10,或者在布尔代数中,1+1可能等于1,如果是逻辑或运算的话。不过大部分情况下,尤其是在日常交流中,人们提到1+1的时候都是指十进制加法,结果自然是2。不过也有可能用户是在测试我的反应,或者想看看我会不会考虑其他可能性。比如在特定的谜语或笑话中,答案可能不是2,比如“1滴水加1滴水还是1滴水”,或者类似的文字游戏。但根据常规问题,我应该先给出正确的数学答案,再补充可能的其他情况,这样既准确又全面。所以可能先回答2,然后解释其他可能性。不过用户的问题看起来直接,可能不需要太复杂的解释,但为了保险起见,还是确认一下是否有其他意图比较好。或者用户可能只是单纯想知道答案,所以直接回答2即可。需要平衡简洁和全面性。可能先给出直接答案,然后简单说明其他情况的存在,这样既满足需求,又避免信息过载。总之,核心答案应该是2,但根据情况适当扩展。") + } + ] + }, + RequestId = "e4ad5d0f-8019-9716-adc6-eae1411d3c9a", + Usage = new TextGenerationTokenUsage + { + TotalTokens = 417, + OutputTokens = 406, + InputTokens = 11 + } + }); public static readonly RequestSnapshot, ModelResponse> From c4b6ca83a43a9c797d223e6c5b3bd9299ecff75b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Fri, 21 Mar 2025 22:20:05 +0800 Subject: [PATCH 19/35] fix: mark snapshot generator unpackable --- .../Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj index 8de488e..8c791ae 100644 --- a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj +++ b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj @@ -1,11 +1,12 @@  - - Exe - + + Exe + false + - - - + + + From d23475fed887c53ecd467788eec1730c5205e0bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Cant=C3=BA?= Date: Tue, 8 Apr 2025 10:29:01 -0500 Subject: [PATCH 20/35] Update projects --- sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj | 2 +- src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj index 88bfded..6fcdad9 100644 --- a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj +++ b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj index 63d65db..a92e8fc 100644 --- a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj +++ b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj @@ -10,7 +10,7 @@ - + From 19fc5294439a9223d5ac7ca37baf618acbca15dd Mon Sep 17 00:00:00 2001 From: David Cantu Date: Tue, 6 May 2025 17:24:04 -0500 Subject: [PATCH 21/35] Update to M.E.AI 9.4.3-preview.1.25230.7 --- .../Cnblogs.DashScope.Sample.csproj | 2 +- src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj | 2 +- src/Cnblogs.DashScope.AI/DashScopeChatClient.cs | 5 +++-- src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs | 7 ++++++- src/Cnblogs.DashScope.Core/TextGenerationParameters.cs | 5 ++++- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj index 6fcdad9..d8cdc9f 100644 --- a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj +++ b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj index a92e8fc..a06683f 100644 --- a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj +++ b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs index 11b86af..d85031b 100644 --- a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs +++ b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs @@ -1,4 +1,4 @@ -using System.Runtime.CompilerServices; +using System.Runtime.CompilerServices; using System.Text.Json; using Cnblogs.DashScope.Core; using Cnblogs.DashScope.Sdk; @@ -503,7 +503,8 @@ private IEnumerable ToTextChatMessages( RequiredChatToolMode required when string.IsNullOrEmpty(required.RequiredFunctionName) == false => ToolChoice.FunctionChoice(required.RequiredFunctionName), _ => ToolChoice.AutoChoice - } + }, + ParallelToolCalls = options.AllowMultipleToolCalls, }; } diff --git a/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs b/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs index c32bb72..d7774f2 100644 --- a/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs +++ b/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs @@ -1,4 +1,4 @@ -namespace Cnblogs.DashScope.Core; +namespace Cnblogs.DashScope.Core; /// /// The text generation options. @@ -49,4 +49,9 @@ public interface ITextGenerationParameters /// Behavior when choosing tools. /// public ToolChoice? ToolChoice { get; } + + /// + /// Whether to enable parallel tool calling + /// + public bool? ParallelToolCalls { get; } } diff --git a/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs b/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs index c5151f3..b6a6fe9 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs +++ b/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs @@ -1,4 +1,4 @@ -namespace Cnblogs.DashScope.Core; +namespace Cnblogs.DashScope.Core; /// /// The text generation options. @@ -44,6 +44,9 @@ public class TextGenerationParameters : ITextGenerationParameters /// public ToolChoice? ToolChoice { get; set; } + /// + public bool? ParallelToolCalls { get; set; } + /// public bool? IncrementalOutput { get; set; } } From 5563ee3ec1381e1eeb52894c49b71fc5399cbd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 12 May 2025 12:31:33 +0800 Subject: [PATCH 22/35] chore: upgrade json schema --- src/Cnblogs.DashScope.Core/QWenTokenizer.cs | 2 +- src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj | 2 +- .../Cnblogs.DashScope.Sdk.UnitTests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cnblogs.DashScope.Core/QWenTokenizer.cs b/src/Cnblogs.DashScope.Core/QWenTokenizer.cs index 3deec09..ebde5a3 100644 --- a/src/Cnblogs.DashScope.Core/QWenTokenizer.cs +++ b/src/Cnblogs.DashScope.Core/QWenTokenizer.cs @@ -70,7 +70,7 @@ public static int CountTokens(string text) /// /// The input text. /// The maximum number of tokens to encode. - /// If the tokenizer's normalization is enabled or is , this will be set to in its normalized form; otherwise, this value will be set to . + /// If the tokenizer's normalization is enabled, this will be set to in its normalized form; otherwise, this value will be set to . /// The token count can be generated which should be smaller than the maximum token count. /// public static int GetIndexByTokenCount(string text, int maxTokenCount, out string? normalizedText, out int tokenCount) diff --git a/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj b/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj index 3480ef8..bc613d8 100644 --- a/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj +++ b/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj @@ -5,7 +5,7 @@ Cnblogs;Dashscope;AI;Sdk;Embedding; - + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj index 3f82c79..981d700 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj @@ -15,7 +15,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From bd2cf1efb44461c560a91d17f57c59b19e76bd48 Mon Sep 17 00:00:00 2001 From: David Cantu Date: Wed, 14 May 2025 09:50:36 -0500 Subject: [PATCH 23/35] Update to M.E.AI 9.5.0-preview --- sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj | 2 +- src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj index d8cdc9f..57edd76 100644 --- a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj +++ b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj index a06683f..4d29dca 100644 --- a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj +++ b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj @@ -10,7 +10,7 @@ - + From c900075d69bad08fb8b4aec966a8bb3e5e239507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sat, 17 May 2025 21:55:41 +0800 Subject: [PATCH 24/35] chore: upgrade msai 9.5.0 --- sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj | 2 +- src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj index 57edd76..ba80da7 100644 --- a/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj +++ b/sample/Cnblogs.DashScope.Sample/Cnblogs.DashScope.Sample.csproj @@ -20,7 +20,7 @@ - + diff --git a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj index 4d29dca..93de919 100644 --- a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj +++ b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj @@ -10,7 +10,7 @@ - + From f27794e656de2af3fe001b39ec9f86f8c7f0b287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:07:41 +0800 Subject: [PATCH 25/35] refactor: make library compatible with net6 --- .editorconfig | 2 +- .github/workflows/ci.yml | 24 +- Cnblogs.DashScope.Sdk.sln | 14 + Directory.Build.props | 2 +- sample/Cnblogs.DashScope.Sample/Program.cs | 9 +- .../ToolCallWithExtensions.cs | 2 +- .../Cnblogs.DashScope.AI.csproj | 2 + .../DashScopeChatClient.cs | 28 +- .../DashScopeTextEmbeddingGenerator.cs | 2 +- .../ApplicationInput.cs | 4 +- .../ApplicationRequest.cs | 6 +- .../BackgroundGenerationInput.cs | 2 +- .../BatchGetEmbeddingsInput.cs | 2 +- .../Cnblogs.DashScope.Core.csproj | 4 +- .../DashScopeClientCore.cs | 6 +- .../DashScopeException.cs | 27 +- .../DashScopeTaskOutput.cs | 2 +- .../DashScopeTaskStatus.cs | 2 +- .../IBatchGetEmbeddingsParameters.cs | 4 +- .../ImageGenerationInput.cs | 4 +- .../ImageSynthesisInput.cs | 2 +- .../Internals/DashScopeDateTimeConvertor.cs | 6 +- .../Internals/JsonSeparatorNamingPolicy.cs | 128 ++++ .../JsonSnakeCaseLowerNamingPolicy.cs | 11 + .../Internals/TextGenerationStopConvertor.cs | 12 +- src/Cnblogs.DashScope.Core/ModelRequest.cs | 4 +- src/Cnblogs.DashScope.Core/MultimodalInput.cs | 2 +- .../MultimodalMessageContent.cs | 6 +- src/Cnblogs.DashScope.Core/QWenTokenizer.cs | 80 +-- src/Cnblogs.DashScope.Core/TextChatMessage.cs | 59 +- .../TextEmbeddingInput.cs | 2 +- .../TextGenerationChoice.cs | 2 +- .../Cnblogs.DashScope.Sdk.csproj | 3 - .../FunctionDefinition.cs | 5 +- .../ChatClientTests.cs | 22 +- .../Cnblogs.DashScope.AI.UnitTests.csproj | 32 + .../EmbeddingClientTests.cs | 6 +- ...ogs.DashScope.Sdk.SnapshotGenerator.csproj | 1 + .../Program.cs | 2 +- .../ApplicationSerializationTests.cs | 2 +- .../BackgroundGenerationSerializationTests.cs | 2 +- .../BaiChuanApiTests.cs | 2 +- .../Cnblogs.DashScope.Sdk.UnitTests.csproj | 62 +- .../DeepSeekTextGenerationApiTests.cs | 16 +- .../ErrorTests.cs | 2 +- .../FileSerializationTests.cs | 2 +- .../ImageGenerationSerializationTests.cs | 2 +- .../ImageSynthesisSerializationTests.cs | 2 +- .../Llama2TextGenerationApiTests.cs | 2 +- .../MultimodalGenerationSerializationTests.cs | 2 +- .../QWenMultimodalApiTests.cs | 18 +- .../QWenTextGenerationApiTests.cs | 2 +- .../QWenTokenizerTests.cs | 520 ++-------------- .../TaskSerializationTests.cs | 2 +- .../TextEmbeddingApiTests.cs | 2 +- .../TextEmbeddingSerializationTests.cs | 2 +- .../TextGenerationSerializationTests.cs | 2 +- .../TextGenerationStopConverterTests.cs | 26 +- .../TokenizationSerializationTests.cs | 2 +- .../ToolChoiceJsonConverterTests.cs | 18 +- .../Utils/GetCurrentWeatherParameters.cs | 19 - .../Utils/Snapshots.MultimodalGeneration.cs | 517 ---------------- .../WanxApiTests.cs | 2 +- .../WorkspaceIdTests.cs | 2 +- .../Cnblogs.DashScope.Tests.Shared.csproj | 27 + ...generation-message-nosse.request.body.json | 0 ...eneration-message-nosse.request.header.txt | 0 ...generation-message-nosse.response.body.txt | 0 ...neration-message-nosse.response.header.txt | 0 ...eration-session-id-nosse.request.body.json | 0 ...ration-session-id-nosse.request.header.txt | 0 ...eration-session-id-nosse.response.body.txt | 0 ...ation-session-id-nosse.response.header.txt | 0 ...le-generation-text-nosse.request.body.json | 0 ...e-generation-text-nosse.request.header.txt | 0 ...le-generation-text-nosse.response.body.txt | 0 ...-generation-text-nosse.response.header.txt | 0 ...ngle-generation-text-sse.request.body.json | 0 ...gle-generation-text-sse.request.header.txt | 0 ...ngle-generation-text-sse.response.body.txt | 0 ...le-generation-text-sse.response.header.txt | 0 ...n-text-with-memory-nosse.request.body.json | 0 ...-text-with-memory-nosse.request.header.txt | 0 ...n-text-with-memory-nosse.response.body.txt | 0 ...text-with-memory-nosse.response.header.txt | 0 ...-text-with-thought-nosse.request.body.json | 0 ...text-with-thought-nosse.request.header.txt | 0 ...-text-with-thought-nosse.response.body.txt | 0 ...ext-with-thought-nosse.response.header.txt | 0 ...plication-workflow-nosse.request.body.json | 0 ...lication-workflow-nosse.request.header.txt | 0 ...plication-workflow-nosse.response.body.txt | 0 ...ication-workflow-nosse.response.header.txt | 0 .../auth-error-nosse.request.body.json | 0 .../auth-error-nosse.request.header.txt | 0 .../auth-error-nosse.response.body.txt | 0 .../auth-error-nosse.response.header.txt | 0 ...kground-generation-nosse.request.body.json | 0 ...ground-generation-nosse.request.header.txt | 0 ...kground-generation-nosse.response.body.txt | 0 ...round-generation-nosse.response.header.txt | 0 ...tch-text-embedding-nosse.request.body.json | 0 ...ch-text-embedding-nosse.request.header.txt | 0 ...tch-text-embedding-nosse.response.body.txt | 0 ...h-text-embedding-nosse.response.header.txt | 0 ...el-completed-task-nosse.request.header.txt | 0 ...cel-completed-task-nosse.response.body.txt | 0 ...l-completed-task-nosse.response.header.txt | 0 ...on-message-partial-nosse.request.body.json | 0 ...n-message-partial-nosse.request.header.txt | 0 ...on-message-partial-nosse.response.body.txt | 0 ...-message-partial-nosse.response.header.txt | 0 ...n-generation-message-sse.request.body.json | 0 ...-generation-message-sse.request.header.txt | 0 ...n-generation-message-sse.response.body.txt | 0 ...generation-message-sse.response.header.txt | 0 ...n-message-with-files-sse.request.body.json | 0 ...-message-with-files-sse.request.header.txt | 0 ...n-message-with-files-sse.response.body.txt | 0 ...message-with-files-sse.response.header.txt | 0 .../delete-file-nosse.request.header.txt | 0 .../delete-file-nosse.response.body.txt | 0 .../delete-file-nosse.response.header.txt | 0 .../get-file-nosse.request.header.txt | 0 .../get-file-nosse.response.body.txt | 0 .../get-file-nosse.response.header.txt | 0 ...eneration-success-nosse.request.header.txt | 0 ...generation-success-nosse.response.body.txt | 0 ...neration-success-nosse.response.header.txt | 0 ...embedding-success-nosse.request.header.txt | 0 ...-embedding-success-nosse.response.body.txt | 0 ...mbedding-success-nosse.response.header.txt | 0 ...eneration-success-nosse.request.header.txt | 0 ...generation-success-nosse.response.body.txt | 0 ...neration-success-nosse.response.header.txt | 0 ...synthesis-success-nosse.request.header.txt | 0 ...-synthesis-success-nosse.response.body.txt | 0 ...ynthesis-success-nosse.response.header.txt | 0 .../get-task-running-nosse.request.header.txt | 0 .../get-task-running-nosse.response.body.txt | 0 ...get-task-running-nosse.response.header.txt | 0 .../get-task-unknown-nosse.request.header.txt | 0 .../get-task-unknown-nosse.response.body.txt | 0 ...get-task-unknown-nosse.response.header.txt | 0 .../image-generation-nosse.request.body.json | 0 .../image-generation-nosse.request.header.txt | 0 .../image-generation-nosse.response.body.txt | 0 ...image-generation-nosse.response.header.txt | 0 .../image-synthesis-nosse.request.body.json | 0 .../image-synthesis-nosse.request.header.txt | 0 .../image-synthesis-nosse.response.body.txt | 0 .../image-synthesis-nosse.response.header.txt | 0 .../list-files-nosse.request.header.txt | 0 .../list-files-nosse.response.body.txt | 0 .../list-files-nosse.response.header.txt | 0 .../list-task-nosse.request.header.txt | 0 .../list-task-nosse.response.body.txt | 0 .../list-task-nosse.response.header.txt | 0 ...l-generation-audio-nosse.request.body.json | 0 ...-generation-audio-nosse.request.header.txt | 0 ...l-generation-audio-nosse.response.body.txt | 0 ...generation-audio-nosse.response.header.txt | 0 ...dal-generation-audio-sse.request.body.json | 0 ...al-generation-audio-sse.request.header.txt | 0 ...dal-generation-audio-sse.response.body.txt | 0 ...l-generation-audio-sse.response.header.txt | 0 ...odal-generation-vl-nosse.request.body.json | 0 ...dal-generation-vl-nosse.request.header.txt | 0 ...odal-generation-vl-nosse.response.body.txt | 0 ...al-generation-vl-nosse.response.header.txt | 0 ...-generation-vl-ocr-nosse.request.body.json | 0 ...generation-vl-ocr-nosse.request.header.txt | 0 ...-generation-vl-ocr-nosse.response.body.txt | 0 ...eneration-vl-ocr-nosse.response.header.txt | 0 ...al-generation-vl-ocr-sse.request.body.json | 0 ...l-generation-vl-ocr-sse.request.header.txt | 0 ...al-generation-vl-ocr-sse.response.body.txt | 0 ...-generation-vl-ocr-sse.response.header.txt | 0 ...imodal-generation-vl-sse.request.body.json | 0 ...modal-generation-vl-sse.request.header.txt | 0 ...imodal-generation-vl-sse.response.body.txt | 0 ...odal-generation-vl-sse.response.header.txt | 0 ...eneration-vl-video-nosse.request.body.json | 0 ...neration-vl-video-nosse.request.header.txt | 0 ...eneration-vl-video-nosse.response.body.txt | 0 ...eration-vl-video-nosse.response.header.txt | 0 ...-generation-vl-video-sse.request.body.json | 0 ...generation-vl-video-sse.request.header.txt | 0 ...-generation-vl-video-sse.response.body.txt | 0 ...eneration-vl-video-sse.response.header.txt | 0 .../parameter-error-nosse.request.body.json | 0 .../parameter-error-nosse.request.header.txt | 0 .../parameter-error-nosse.response.body.txt | 0 .../parameter-error-nosse.response.header.txt | 0 .../parameter-error-sse.request.body.json | 0 .../parameter-error-sse.request.header.txt | 0 .../parameter-error-sse.response.body.txt | 0 .../parameter-error-sse.response.header.txt | 0 ...ation-message-json-nosse.request.body.json | 0 ...tion-message-json-nosse.request.header.txt | 0 ...ation-message-json-nosse.response.body.txt | 0 ...ion-message-json-nosse.response.header.txt | 0 ...generation-message-nosse.request.body.json | 0 ...eneration-message-nosse.request.header.txt | 0 ...generation-message-nosse.response.body.txt | 0 ...neration-message-nosse.response.header.txt | 0 ...-message-reasoning-nosse.request.body.json | 0 ...message-reasoning-nosse.request.header.txt | 0 ...-message-reasoning-nosse.response.body.txt | 0 ...essage-reasoning-nosse.response.header.txt | 0 ...on-message-reasoning-sse.request.body.json | 0 ...n-message-reasoning-sse.request.header.txt | 0 ...on-message-reasoning-sse.response.body.txt | 0 ...-message-reasoning-sse.response.header.txt | 0 ...e-generation-message-sse.request.body.json | 0 ...-generation-message-sse.request.header.txt | 0 ...e-generation-message-sse.response.body.txt | 0 ...generation-message-sse.response.header.txt | 0 ...message-with-tools-nosse.request.body.json | 7 - ...essage-with-tools-nosse.request.header.txt | 0 ...message-with-tools-nosse.response.body.txt | 0 ...ssage-with-tools-nosse.response.header.txt | 0 ...le-generation-text-nosse.request.body.json | 0 ...e-generation-text-nosse.request.header.txt | 0 ...le-generation-text-nosse.response.body.txt | 0 ...-generation-text-nosse.response.header.txt | 0 ...ngle-generation-text-sse.request.body.json | 0 ...gle-generation-text-sse.request.header.txt | 0 ...ngle-generation-text-sse.response.body.txt | 0 ...le-generation-text-sse.response.header.txt | 0 .../RawHttpData/test1.txt | 0 .../RawHttpData/test2.txt | 0 .../text-embedding-nosse.request.body.json | 0 .../text-embedding-nosse.request.header.txt | 0 .../text-embedding-nosse.response.body.txt | 0 .../text-embedding-nosse.response.header.txt | 0 .../tokenization-nosse.request.body.json | 0 .../tokenization-nosse.request.header.txt | 0 .../tokenization-nosse.response.body.txt | 0 .../tokenization-nosse.response.header.txt | 0 ...upload-file-error-nosse.request.header.txt | 0 .../upload-file-error-nosse.response.body.txt | 0 ...pload-file-error-nosse.response.header.txt | 0 .../upload-file-nosse.request.header.txt | 0 .../upload-file-nosse.response.body.txt | 0 .../upload-file-nosse.response.header.txt | 0 .../Utils/Cases.cs | 6 +- .../Utils/Checkers.cs | 2 +- .../Utils/EquivalentUtils.cs | 4 +- .../Utils/GetCurrentWeatherParameters.cs | 10 + .../Utils/MockHttpMessageHandler.cs | 2 +- .../Utils/RequestSnapshot.cs | 2 +- .../Utils/Snapshots.Application.cs | 164 ++--- .../Utils/Snapshots.Error.cs | 20 +- .../Utils/Snapshots.MultimodalGeneration.cs | 567 ++++++++++++++++++ .../Utils/Snapshots.Tasks.cs | 90 +-- .../Utils/Snapshots.TextEmbedding.cs | 10 +- .../Utils/Snapshots.TextGeneration.cs | 398 ++++++------ .../Utils/Snapshots.cs | 27 +- .../Utils/Sut.cs | 2 +- .../Utils/TestApplicationBizParam.cs | 2 +- 261 files changed, 1546 insertions(+), 1557 deletions(-) create mode 100644 src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs create mode 100644 src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.AI.UnitTests}/ChatClientTests.cs (92%) create mode 100644 test/Cnblogs.DashScope.AI.UnitTests/Cnblogs.DashScope.AI.UnitTests.csproj rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.AI.UnitTests}/EmbeddingClientTests.cs (91%) delete mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/GetCurrentWeatherParameters.cs delete mode 100644 test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs create mode 100644 test/Cnblogs.DashScope.Tests.Shared/Cnblogs.DashScope.Tests.Shared.csproj rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-message-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-message-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-message-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-message-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-workflow-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-workflow-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-workflow-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/application-workflow-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/auth-error-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/auth-error-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/auth-error-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/auth-error-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/background-generation-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/background-generation-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/background-generation-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/background-generation-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/batch-text-embedding-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/batch-text-embedding-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/batch-text-embedding-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/batch-text-embedding-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/cancel-completed-task-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/cancel-completed-task-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/cancel-completed-task-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-partial-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-with-files-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-with-files-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-with-files-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/conversation-generation-message-with-files-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/delete-file-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/delete-file-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/delete-file-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-file-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-file-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-file-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-background-generation-success-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-background-generation-success-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-background-generation-success-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-batch-text-embedding-success-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-batch-text-embedding-success-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-batch-text-embedding-success-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-image-generation-success-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-image-generation-success-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-image-generation-success-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-image-synthesis-success-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-image-synthesis-success-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-running-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-running-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-running-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-unknown-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-unknown-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/get-task-unknown-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-generation-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-generation-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-generation-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-generation-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-synthesis-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-synthesis-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-synthesis-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/image-synthesis-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/list-files-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/list-files-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/list-files-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/list-task-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/list-task-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/list-task-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-audio-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/parameter-error-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-json-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-json-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-json-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-json-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-reasoning-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-with-tools-nosse.request.body.json (85%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-with-tools-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-with-tools-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-message-with-tools-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-sse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-sse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-sse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/single-generation-text-sse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/test1.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/test2.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/text-embedding-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/text-embedding-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/text-embedding-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/text-embedding-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/tokenization-nosse.request.body.json (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/tokenization-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/tokenization-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/tokenization-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/upload-file-error-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/upload-file-error-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/upload-file-error-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/upload-file-nosse.request.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/upload-file-nosse.response.body.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/RawHttpData/upload-file-nosse.response.header.txt (100%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Cases.cs (69%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Checkers.cs (94%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/EquivalentUtils.cs (69%) create mode 100644 test/Cnblogs.DashScope.Tests.Shared/Utils/GetCurrentWeatherParameters.cs rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/MockHttpMessageHandler.cs (93%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/RequestSnapshot.cs (96%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Snapshots.Application.cs (92%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Snapshots.Error.cs (84%) create mode 100644 test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Snapshots.Tasks.cs (83%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Snapshots.TextEmbedding.cs (83%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Snapshots.TextGeneration.cs (57%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Snapshots.cs (89%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/Sut.cs (94%) rename test/{Cnblogs.DashScope.Sdk.UnitTests => Cnblogs.DashScope.Tests.Shared}/Utils/TestApplicationBizParam.cs (75%) diff --git a/.editorconfig b/.editorconfig index 6b17d25..644e447 100644 --- a/.editorconfig +++ b/.editorconfig @@ -384,5 +384,5 @@ dotnet_naming_style.s_camelcase.capitalization = camel_case indent_size = 2 tab_width = 2 -[*.{props,targets,config,nuspec,json}] +[*.{props,targets,config,nuspec,json,yml}] indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ab7c15..bd8d6b8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,15 +7,25 @@ on: branches: [ "main" ] jobs: - test: + test-net6: runs-on: ubuntu-latest container: mcr.microsoft.com/dotnet/sdk:8.0 steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Build - run: dotnet build -c Release - - name: Test - run: dotnet test -c Release + - name: Checkout + uses: actions/checkout@v4 + - name: Build + run: dotnet build Cnblogs.DashScope.AspNetCore -c Release + - name: Test + run: dotnet test Cnblogs.Sdk.UnitTests -c Release + test-net8: + runs-on: ubuntu-latest + container: mcr.microsoft.com/dotnet/sdk:8.0 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Build + run: dotnet build Cnblogs.DashScope.AI -c Release + - name: Test + run: dotnet test Cnblogs.DashScope.AI.UnitTests -c Release diff --git a/Cnblogs.DashScope.Sdk.sln b/Cnblogs.DashScope.Sdk.sln index 26d0161..165038d 100644 --- a/Cnblogs.DashScope.Sdk.sln +++ b/Cnblogs.DashScope.Sdk.sln @@ -20,6 +20,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.DashScope.Sdk.Snaps EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.DashScope.AI", "src\Cnblogs.DashScope.AI\Cnblogs.DashScope.AI.csproj", "{5D5AD75A-8084-4738-AC56-B8A23E649452}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.DashScope.AI.UnitTests", "test\Cnblogs.DashScope.AI.UnitTests\Cnblogs.DashScope.AI.UnitTests.csproj", "{25EE79E1-147B-42FD-AFEA-E1550EDD1D36}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cnblogs.DashScope.Tests.Shared", "test\Cnblogs.DashScope.Tests.Shared\Cnblogs.DashScope.Tests.Shared.csproj", "{06F0AF23-445B-4C6F-9E19-570DA9B7435D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +37,8 @@ Global {CC389455-A3EA-4F09-B524-4DC351A1E1AA} = {008988ED-0A3B-4272-BCC3-7B4110699345} {5088DE77-1CE3-46FB-B9D0-27A6C9A5EED1} = {CFC8ECB3-5248-46CD-A56C-EC088F2A3804} {5D5AD75A-8084-4738-AC56-B8A23E649452} = {008988ED-0A3B-4272-BCC3-7B4110699345} + {25EE79E1-147B-42FD-AFEA-E1550EDD1D36} = {CFC8ECB3-5248-46CD-A56C-EC088F2A3804} + {06F0AF23-445B-4C6F-9E19-570DA9B7435D} = {CFC8ECB3-5248-46CD-A56C-EC088F2A3804} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {FA6A118A-8D26-4B7A-9952-8504B8A0025B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -63,5 +69,13 @@ Global {5D5AD75A-8084-4738-AC56-B8A23E649452}.Debug|Any CPU.Build.0 = Debug|Any CPU {5D5AD75A-8084-4738-AC56-B8A23E649452}.Release|Any CPU.ActiveCfg = Release|Any CPU {5D5AD75A-8084-4738-AC56-B8A23E649452}.Release|Any CPU.Build.0 = Release|Any CPU + {25EE79E1-147B-42FD-AFEA-E1550EDD1D36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25EE79E1-147B-42FD-AFEA-E1550EDD1D36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25EE79E1-147B-42FD-AFEA-E1550EDD1D36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25EE79E1-147B-42FD-AFEA-E1550EDD1D36}.Release|Any CPU.Build.0 = Release|Any CPU + {06F0AF23-445B-4C6F-9E19-570DA9B7435D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {06F0AF23-445B-4C6F-9E19-570DA9B7435D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {06F0AF23-445B-4C6F-9E19-570DA9B7435D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {06F0AF23-445B-4C6F-9E19-570DA9B7435D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/Directory.Build.props b/Directory.Build.props index f39a7b6..3eaabd9 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - net8.0 + net6.0 enable enable Cnblogs diff --git a/sample/Cnblogs.DashScope.Sample/Program.cs b/sample/Cnblogs.DashScope.Sample/Program.cs index 8841af4..d003cd3 100644 --- a/sample/Cnblogs.DashScope.Sample/Program.cs +++ b/sample/Cnblogs.DashScope.Sample/Program.cs @@ -177,7 +177,7 @@ async Task ChatWithToolsAsync() "获得当前天气", new JsonSchemaBuilder().FromType().Build())) }; - var chatParameters = new TextGenerationParameters() { ResultFormat = ResultFormats.Message, Tools = tools }; + var chatParameters = new TextGenerationParameters { ResultFormat = ResultFormats.Message, Tools = tools }; var question = TextChatMessage.User("请问现在杭州的天气如何?"); history.Add(question); Console.WriteLine($"{question.Role} > {question.Content}"); @@ -214,10 +214,7 @@ async Task ChatWithMicrosoftExtensions() Console.WriteLine("Requesting model..."); var chatClient = dashScopeClient.AsChatClient("qwen-max"); List conversation = - [ - new(ChatRole.System, "You are a helpful AI assistant"), - new(ChatRole.User, "What is AI?") - ]; + new() { new(ChatRole.System, "You are a helpful AI assistant"), new(ChatRole.User, "What is AI?") }; var response = await chatClient.GetResponseAsync(conversation); var serializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) { WriteIndented = true }; Console.WriteLine(JsonSerializer.Serialize(response, serializerOptions)); @@ -225,7 +222,7 @@ async Task ChatWithMicrosoftExtensions() async Task ApplicationCallAsync(string applicationId, string prompt) { - var request = new ApplicationRequest() { Input = new ApplicationInput() { Prompt = prompt } }; + var request = new ApplicationRequest { Input = new ApplicationInput { Prompt = prompt } }; var response = await dashScopeClient.GetApplicationResponseAsync(applicationId, request); Console.WriteLine(response.Output.Text); } diff --git a/sample/Cnblogs.DashScope.Sample/ToolCallWithExtensions.cs b/sample/Cnblogs.DashScope.Sample/ToolCallWithExtensions.cs index 0c30cd4..72ccc1e 100644 --- a/sample/Cnblogs.DashScope.Sample/ToolCallWithExtensions.cs +++ b/sample/Cnblogs.DashScope.Sample/ToolCallWithExtensions.cs @@ -12,7 +12,7 @@ public static async Task ToolCallWithExtensionAsync(this IDashScopeClient dashSc [Description("Gets the weather")] string GetWeather(string location) => Random.Shared.NextDouble() > 0.5 ? "It's sunny" : "It's raining"; - var chatOptions = new ChatOptions { Tools = [AIFunctionFactory.Create(GetWeather)] }; + var chatOptions = new ChatOptions { Tools = new List { AIFunctionFactory.Create(GetWeather) } }; var client = dashScopeClient.AsChatClient("qwen-max").AsBuilder().UseFunctionInvocation().Build(); await foreach (var message in client.GetStreamingResponseAsync("What is weather of LA today?", chatOptions)) diff --git a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj index 93de919..8de1ebd 100644 --- a/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj +++ b/src/Cnblogs.DashScope.AI/Cnblogs.DashScope.AI.csproj @@ -1,5 +1,6 @@  + net8.0 Cnblogs.DashScope.AI true Cnblogs;Dashscope;Microsoft.Extensions.AI;Sdk;Embedding; @@ -10,6 +11,7 @@ + diff --git a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs index d85031b..c8a0d0f 100644 --- a/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs +++ b/src/Cnblogs.DashScope.AI/DashScopeChatClient.cs @@ -17,7 +17,7 @@ public sealed class DashScopeChatClient : IChatClient private readonly string _modelId; private static readonly JsonSchema EmptyObjectSchema = - JsonSchema.FromText("""{"type":"object","required":[],"properties":{}}"""); + JsonSchema.FromText("{\"type\":\"object\",\"required\":[],\"properties\":{}}"); private static readonly TextGenerationParameters DefaultTextGenerationParameter = new() { ResultFormat = "message" }; @@ -55,7 +55,7 @@ public async Task GetResponseAsync( if (useVl) { var response = await _dashScopeClient.GetMultimodalGenerationAsync( - new ModelRequest() + new ModelRequest { Input = new MultimodalInput { Messages = ToMultimodalMessages(chatMessages) }, Parameters = ToMultimodalParameters(options), @@ -63,7 +63,7 @@ public async Task GetResponseAsync( }, cancellationToken); - var returnMessage = new ChatMessage() + var returnMessage = new ChatMessage { RawRepresentation = response, Role = ToChatRole(response.Output.Choices[0].Message.Role), }; @@ -80,7 +80,7 @@ public async Task GetResponseAsync( if (response.Usage != null) { - completion.Usage = new UsageDetails() + completion.Usage = new UsageDetails { InputTokenCount = response.Usage.InputTokens, OutputTokenCount = response.Usage.OutputTokens, }; @@ -92,7 +92,7 @@ public async Task GetResponseAsync( { var parameters = ToTextGenerationParameters(options) ?? DefaultTextGenerationParameter; var response = await _dashScopeClient.GetTextCompletionAsync( - new ModelRequest() + new ModelRequest { Input = new TextGenerationInput { @@ -116,7 +116,7 @@ public async Task GetResponseAsync( if (response.Usage != null) { - completion.Usage = new UsageDetails() + completion.Usage = new UsageDetails { InputTokenCount = response.Usage.InputTokens, OutputTokenCount = response.Usage.OutputTokens, @@ -147,7 +147,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( var parameter = ToMultimodalParameters(options); parameter.IncrementalOutput = true; var stream = _dashScopeClient.GetMultimodalGenerationStreamAsync( - new ModelRequest() + new ModelRequest { Input = new MultimodalInput { Messages = ToMultimodalMessages(chatMessages) }, Parameters = parameter, @@ -164,7 +164,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( : ToFinishReason(response.Output.Choices[0].FinishReason); completionId ??= response.RequestId; - var update = new ChatResponseUpdate() + var update = new ChatResponseUpdate { ResponseId = completionId, CreatedAt = DateTimeOffset.Now, @@ -199,7 +199,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( { // qwen does not support streaming with function call, fallback to non-streaming var completion = await GetResponseAsync(chatMessages, options, cancellationToken); - yield return new ChatResponseUpdate() + yield return new ChatResponseUpdate { ResponseId = completion.ResponseId, Role = completion.Messages[0].Role, @@ -216,7 +216,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( var parameters = ToTextGenerationParameters(options) ?? DefaultTextGenerationParameter; parameters.IncrementalOutput = true; var stream = _dashScopeClient.GetTextCompletionStreamAsync( - new ModelRequest() + new ModelRequest { Input = new TextGenerationInput { @@ -238,7 +238,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( : ToFinishReason(response.Output.Choices[0].FinishReason); completionId ??= response.RequestId; - var update = new ChatResponseUpdate() + var update = new ChatResponseUpdate { ResponseId = completionId, CreatedAt = DateTimeOffset.Now, @@ -257,7 +257,7 @@ public async IAsyncEnumerable GetStreamingResponseAsync( { update.Contents.Add( new UsageContent( - new UsageDetails() + new UsageDetails { InputTokenCount = response.Usage.InputTokens, OutputTokenCount = response.Usage.OutputTokens, @@ -299,7 +299,7 @@ public void Dispose() private static ChatMessage ToChatMessage(TextChatMessage message) { - var returnMessage = new ChatMessage() + var returnMessage = new ChatMessage { RawRepresentation = message, Role = ToChatRole(message.Role), }; @@ -485,7 +485,7 @@ private IEnumerable ToTextChatMessages( format = "json_object"; } - return new TextGenerationParameters() + return new TextGenerationParameters { ResultFormat = format, Temperature = options.Temperature, diff --git a/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs b/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs index 06c28d7..f735844 100644 --- a/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs +++ b/src/Cnblogs.DashScope.AI/DashScopeTextEmbeddingGenerator.cs @@ -44,7 +44,7 @@ public async Task>> GenerateAsync( e => new Embedding(e.Embedding) { ModelId = _modelId, CreatedAt = DateTimeOffset.Now }); var rawUsage = rawResponse.Usage; var usage = rawUsage != null - ? new UsageDetails() { InputTokenCount = rawUsage.TotalTokens, TotalTokenCount = rawUsage.TotalTokens } + ? new UsageDetails { InputTokenCount = rawUsage.TotalTokens, TotalTokenCount = rawUsage.TotalTokens } : null; return new GeneratedEmbeddings>(embeddings) { diff --git a/src/Cnblogs.DashScope.Core/ApplicationInput.cs b/src/Cnblogs.DashScope.Core/ApplicationInput.cs index 965124b..fc537e6 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationInput.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationInput.cs @@ -44,4 +44,6 @@ public class ApplicationInput /// /// Inputs for application call. /// -public class ApplicationInput : ApplicationInput>; +public class ApplicationInput : ApplicationInput> +{ +} diff --git a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs index bdafef5..c1980e7 100644 --- a/src/Cnblogs.DashScope.Core/ApplicationRequest.cs +++ b/src/Cnblogs.DashScope.Core/ApplicationRequest.cs @@ -13,7 +13,7 @@ public class ApplicationRequest : IDashScopeWorkspaceConfig /// /// Content of this call. /// - public required ApplicationInput Input { get; set; } + public ApplicationInput Input { get; set; } = new(); /// /// Optional configurations. @@ -30,4 +30,6 @@ public class ApplicationRequest : IDashScopeWorkspaceConfig /// /// Request body for an application call with dictionary biz_content. /// -public class ApplicationRequest : ApplicationRequest>; +public class ApplicationRequest : ApplicationRequest> +{ +} diff --git a/src/Cnblogs.DashScope.Core/BackgroundGenerationInput.cs b/src/Cnblogs.DashScope.Core/BackgroundGenerationInput.cs index bd820dc..dd5b2b3 100644 --- a/src/Cnblogs.DashScope.Core/BackgroundGenerationInput.cs +++ b/src/Cnblogs.DashScope.Core/BackgroundGenerationInput.cs @@ -8,7 +8,7 @@ public class BackgroundGenerationInput /// /// The image url to generation background on. /// - public required string BaseImageUrl { get; set; } + public string BaseImageUrl { get; set; } = string.Empty; /// /// The reference image url for. diff --git a/src/Cnblogs.DashScope.Core/BatchGetEmbeddingsInput.cs b/src/Cnblogs.DashScope.Core/BatchGetEmbeddingsInput.cs index b9ab6e0..36b04cd 100644 --- a/src/Cnblogs.DashScope.Core/BatchGetEmbeddingsInput.cs +++ b/src/Cnblogs.DashScope.Core/BatchGetEmbeddingsInput.cs @@ -8,5 +8,5 @@ public class BatchGetEmbeddingsInput /// /// The url of text file to compute embeddings from. /// - public required string Url { get; set; } + public string Url { get; set; } = string.Empty; } diff --git a/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj b/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj index 791029d..7d46d37 100644 --- a/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj +++ b/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj @@ -8,11 +8,11 @@ - + - + diff --git a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs index 7cca41f..fdbed71 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs @@ -18,7 +18,7 @@ public class DashScopeClientCore : IDashScopeClient new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower, + PropertyNamingPolicy = JsonSnakeCaseLowerNamingPolicy.SnakeCaseLower, }; private readonly HttpClient _httpClient; @@ -332,7 +332,7 @@ private static HttpRequestMessage BuildRequest( { var response = await GetSuccessResponseAsync( message, - r => new DashScopeError() + r => new DashScopeError { Code = r.Error.Type, Message = r.Error.Message, @@ -367,7 +367,7 @@ private async IAsyncEnumerable StreamAsync( if (cancellationToken.IsCancellationRequested) throw new TaskCanceledException(); - var line = await reader.ReadLineAsync(cancellationToken); + var line = await reader.ReadLineAsync(); if (line != null && line.StartsWith("data:")) { var data = line["data:".Length..]; diff --git a/src/Cnblogs.DashScope.Core/DashScopeException.cs b/src/Cnblogs.DashScope.Core/DashScopeException.cs index d4aba49..3826f87 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeException.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeException.cs @@ -3,24 +3,35 @@ /// /// Represents error detail for DashScope API calls. /// -/// The requested api url. -/// The status code of response. Would be 0 if no response is received. -/// The error detail returned by server. -/// The error message. -public class DashScopeException(string? apiUrl, int status, DashScopeError? error, string message) : Exception(message) +public class DashScopeException : Exception { + /// + /// Represents error detail for DashScope API calls. + /// + /// The requested api url. + /// The status code of response. Would be 0 if no response is received. + /// The error detail returned by server. + /// The error message. + public DashScopeException(string? apiUrl, int status, DashScopeError? error, string message) + : base(message) + { + ApiUrl = apiUrl; + Error = error; + Status = status; + } + /// /// The requested api url. /// - public string? ApiUrl { get; } = apiUrl; + public string? ApiUrl { get; } /// /// The error detail returned by server. /// - public DashScopeError? Error { get; } = error; + public DashScopeError? Error { get; } /// /// The status code of response. Would be 0 if no response is received. /// - public int Status { get; } = status; + public int Status { get; } } diff --git a/src/Cnblogs.DashScope.Core/DashScopeTaskOutput.cs b/src/Cnblogs.DashScope.Core/DashScopeTaskOutput.cs index 8ca43f9..7a8bee7 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeTaskOutput.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeTaskOutput.cs @@ -11,7 +11,7 @@ public abstract record DashScopeTaskOutput /// /// The unique id of this task. /// - public required string TaskId { get; set; } + public string TaskId { get; set; } = string.Empty; /// /// The status of this task. diff --git a/src/Cnblogs.DashScope.Core/DashScopeTaskStatus.cs b/src/Cnblogs.DashScope.Core/DashScopeTaskStatus.cs index 83a3509..3b87579 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeTaskStatus.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeTaskStatus.cs @@ -5,7 +5,7 @@ namespace Cnblogs.DashScope.Core; /// /// Represents status of DashScope task. /// -[JsonConverter(typeof(JsonStringEnumConverter))] +[JsonConverter(typeof(JsonStringEnumConverter))] public enum DashScopeTaskStatus { /// diff --git a/src/Cnblogs.DashScope.Core/IBatchGetEmbeddingsParameters.cs b/src/Cnblogs.DashScope.Core/IBatchGetEmbeddingsParameters.cs index d2640e0..04a28d3 100644 --- a/src/Cnblogs.DashScope.Core/IBatchGetEmbeddingsParameters.cs +++ b/src/Cnblogs.DashScope.Core/IBatchGetEmbeddingsParameters.cs @@ -3,4 +3,6 @@ /// /// Optional parameter of batch get embeddings request. /// -public interface IBatchGetEmbeddingsParameters : ITextEmbeddingParameters; +public interface IBatchGetEmbeddingsParameters : ITextEmbeddingParameters +{ +} diff --git a/src/Cnblogs.DashScope.Core/ImageGenerationInput.cs b/src/Cnblogs.DashScope.Core/ImageGenerationInput.cs index d21dca1..4ea9876 100644 --- a/src/Cnblogs.DashScope.Core/ImageGenerationInput.cs +++ b/src/Cnblogs.DashScope.Core/ImageGenerationInput.cs @@ -8,10 +8,10 @@ public class ImageGenerationInput /// /// The image url to generation new image from. /// - public required string ImageUrl { get; set; } + public string ImageUrl { get; set; } = string.Empty; /// /// The style the new image should use, checkout docs for sample image of different indexes: https://help.aliyun.com/zh/dashscope/developer-reference/tongyi-wanxiang-style-repaint /// - public required int StyleIndex { get; set; } + public int StyleIndex { get; set; } } diff --git a/src/Cnblogs.DashScope.Core/ImageSynthesisInput.cs b/src/Cnblogs.DashScope.Core/ImageSynthesisInput.cs index 9c78118..21c0dcc 100644 --- a/src/Cnblogs.DashScope.Core/ImageSynthesisInput.cs +++ b/src/Cnblogs.DashScope.Core/ImageSynthesisInput.cs @@ -8,7 +8,7 @@ public class ImageSynthesisInput /// /// The prompt to generate image from. This will be chopped at max length of 500 characters. /// - public required string Prompt { get; set; } + public string Prompt { get; set; } = string.Empty; /// /// The negative prompt to generate image from. This will be chopped at max length of 500 characters. diff --git a/src/Cnblogs.DashScope.Core/Internals/DashScopeDateTimeConvertor.cs b/src/Cnblogs.DashScope.Core/Internals/DashScopeDateTimeConvertor.cs index c4c9987..45fc52f 100644 --- a/src/Cnblogs.DashScope.Core/Internals/DashScopeDateTimeConvertor.cs +++ b/src/Cnblogs.DashScope.Core/Internals/DashScopeDateTimeConvertor.cs @@ -6,11 +6,7 @@ namespace Cnblogs.DashScope.Core.Internals; internal class DashScopeDateTimeConvertor : JsonConverter { - private static readonly string[] DateTimeFormats = - [ - "yyyy-MM-dd HH:mm:ss.fff", - "yyyy-MM-dd HH:mm:ss.FFF" - ]; + private static readonly string[] DateTimeFormats = { "yyyy-MM-dd HH:mm:ss.fff", "yyyy-MM-dd HH:mm:ss.FFF" }; /// public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) diff --git a/src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs b/src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs new file mode 100644 index 0000000..761ae20 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs @@ -0,0 +1,128 @@ +using System.Buffers; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Text.Json; + +namespace Cnblogs.DashScope.Core.Internals; + +// back-porting from dotnet/runtime +internal abstract class JsonSeparatorNamingPolicy : JsonNamingPolicy +{ + private readonly bool _lowercase; + private readonly char _separator; + + internal JsonSeparatorNamingPolicy(bool lowercase, char separator) + { + _lowercase = lowercase; + _separator = separator; + } + + public sealed override string ConvertName(string? name) + { + if (name == null) + { + throw new ArgumentNullException(nameof(name)); + } + + return ConvertNameCore(_separator, _lowercase, name.AsSpan()); + } + + private static string ConvertNameCore(char separator, bool lowercase, ReadOnlySpan chars) + { + var rentedBuffer = (char[]?)null; + var minimumLength = (int)(1.2 * chars.Length); + var destination = minimumLength > 128 /*0x80*/ + ? (Span)(rentedBuffer = ArrayPool.Shared.Rent(minimumLength)) + : stackalloc char[128 /*0x80*/]; + var separatorState = SeparatorState.NotStarted; + var charsWritten = 0; + for (var index = 0; index < chars.Length; ++index) + { + var c = chars[index]; + var unicodeCategory = char.GetUnicodeCategory(c); + switch (unicodeCategory) + { + case UnicodeCategory.UppercaseLetter: + switch (separatorState) + { + case SeparatorState.UppercaseLetter: + if (index + 1 < chars.Length && char.IsLower(chars[index + 1])) + { + WriteChar(separator, ref destination); + } + + break; + case SeparatorState.LowercaseLetterOrDigit: + case SeparatorState.SpaceSeparator: + WriteChar(separator, ref destination); + break; + } + + if (lowercase) + c = char.ToLowerInvariant(c); + WriteChar(c, ref destination); + separatorState = SeparatorState.UppercaseLetter; + break; + case UnicodeCategory.LowercaseLetter: + case UnicodeCategory.DecimalDigitNumber: + if (separatorState == SeparatorState.SpaceSeparator) + WriteChar(separator, ref destination); + if (!lowercase && unicodeCategory == UnicodeCategory.LowercaseLetter) + c = char.ToUpperInvariant(c); + WriteChar(c, ref destination); + separatorState = SeparatorState.LowercaseLetterOrDigit; + break; + case UnicodeCategory.SpaceSeparator: + if (separatorState != SeparatorState.NotStarted) + { + separatorState = SeparatorState.SpaceSeparator; + } + + break; + default: + WriteChar(c, ref destination); + separatorState = SeparatorState.NotStarted; + break; + } + } + + var str = destination.Slice(0, charsWritten).ToString(); + if (rentedBuffer != null) + { + destination.Slice(0, charsWritten).Clear(); + ArrayPool.Shared.Return(rentedBuffer); + } + + return str; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + void WriteChar(char value, ref Span destination) + { + if (charsWritten == destination.Length) + ExpandBuffer(ref destination); + destination[charsWritten++] = value; + } + + void ExpandBuffer(ref Span destination) + { + var destination1 = ArrayPool.Shared.Rent(checked(destination.Length * 2)); + destination.CopyTo((Span)destination1); + if (rentedBuffer != null) + { + destination.Slice(0, charsWritten).Clear(); + ArrayPool.Shared.Return(rentedBuffer); + } + + rentedBuffer = destination1; + destination = (Span)rentedBuffer; + } + } + + private enum SeparatorState + { + NotStarted, + UppercaseLetter, + LowercaseLetterOrDigit, + SpaceSeparator, + } +} diff --git a/src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs b/src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs new file mode 100644 index 0000000..23d1f48 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs @@ -0,0 +1,11 @@ +namespace Cnblogs.DashScope.Core.Internals; + +internal class JsonSnakeCaseLowerNamingPolicy : JsonSeparatorNamingPolicy +{ + public static readonly JsonSnakeCaseLowerNamingPolicy SnakeCaseLower = new(); + + private JsonSnakeCaseLowerNamingPolicy() + : base(true, '_') + { + } +} diff --git a/src/Cnblogs.DashScope.Core/Internals/TextGenerationStopConvertor.cs b/src/Cnblogs.DashScope.Core/Internals/TextGenerationStopConvertor.cs index 1efd6b5..5f704a8 100644 --- a/src/Cnblogs.DashScope.Core/Internals/TextGenerationStopConvertor.cs +++ b/src/Cnblogs.DashScope.Core/Internals/TextGenerationStopConvertor.cs @@ -77,21 +77,21 @@ private static TextGenerationStop ReadArray(ref Utf8JsonReader reader) case JsonTokenType.EndArray: return type switch { - DeserializationArrayType.Strings => stringList ?? [], - DeserializationArrayType.Token => intList?.ToArray() ?? [], - DeserializationArrayType.Tokens => tokenList ?? [], + DeserializationArrayType.Strings => stringList ?? new List(), + DeserializationArrayType.Token => intList?.ToArray() ?? Array.Empty(), + DeserializationArrayType.Tokens => tokenList ?? new List(), _ => throw new JsonException("Impossible deserialization type") }; case JsonTokenType.StartArray when type is DeserializationArrayType.Tokens: - tokenList ??= []; + tokenList ??= new List(); tokenList.Add(ReadTokenId(ref reader)); break; case JsonTokenType.Number when type is DeserializationArrayType.Token: - intList ??= []; + intList ??= new List(); intList.Add(reader.GetInt32()); break; case JsonTokenType.String when type is DeserializationArrayType.Strings: - stringList ??= []; + stringList ??= new List(); stringList.Add(reader.GetString()!); break; default: diff --git a/src/Cnblogs.DashScope.Core/ModelRequest.cs b/src/Cnblogs.DashScope.Core/ModelRequest.cs index 69ad50c..93fbfff 100644 --- a/src/Cnblogs.DashScope.Core/ModelRequest.cs +++ b/src/Cnblogs.DashScope.Core/ModelRequest.cs @@ -10,12 +10,12 @@ public class ModelRequest /// /// The model to use. /// - public required string Model { get; init; } + public string Model { get; init; } = string.Empty; /// /// Input of this request. /// - public required TInput Input { get; init; } + public TInput Input { get; init; } = null!; } /// diff --git a/src/Cnblogs.DashScope.Core/MultimodalInput.cs b/src/Cnblogs.DashScope.Core/MultimodalInput.cs index 775b4d5..251e0ac 100644 --- a/src/Cnblogs.DashScope.Core/MultimodalInput.cs +++ b/src/Cnblogs.DashScope.Core/MultimodalInput.cs @@ -8,5 +8,5 @@ public class MultimodalInput /// /// The messages of context, model will generate from last user message. /// - public required IEnumerable Messages { get; set; } + public IEnumerable Messages { get; set; } = Array.Empty(); } diff --git a/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs b/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs index 98fff19..aee7879 100644 --- a/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs +++ b/src/Cnblogs.DashScope.Core/MultimodalMessageContent.cs @@ -1,6 +1,4 @@ -using System.Diagnostics.CodeAnalysis; - -namespace Cnblogs.DashScope.Core; +namespace Cnblogs.DashScope.Core; /// /// Represents one content of a . @@ -12,10 +10,8 @@ namespace Cnblogs.DashScope.Core; /// 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, IEnumerable? Video = null, int? MinPixels = null, diff --git a/src/Cnblogs.DashScope.Core/QWenTokenizer.cs b/src/Cnblogs.DashScope.Core/QWenTokenizer.cs index ebde5a3..f114a14 100644 --- a/src/Cnblogs.DashScope.Core/QWenTokenizer.cs +++ b/src/Cnblogs.DashScope.Core/QWenTokenizer.cs @@ -1,48 +1,35 @@ -using System.Text.RegularExpressions; -using Cnblogs.DashScope.Core.Internals; -using Microsoft.ML.Tokenizers; +using Cnblogs.DashScope.Core.Internals; +using Microsoft.DeepDev; namespace Cnblogs.DashScope.Core; /// -/// Local implementation for QWen tokenizer +/// Tokenizer using QWen /// -public partial class QWenTokenizer +public class QWenTokenizer { private static readonly Dictionary SpecialTokens = - new List - { - "<|endoftext|>", - "<|im_start|>", - "<|im_end|>" - } + new[] { "<|endoftext|>", "<|im_start|>", "<|im_end|>" } .Concat(Enumerable.Range(0, 205).Select(x => $"<|extra_{x}|>")) .Select((x, i) => new KeyValuePair(x, 151643 + i)) - .ToDictionary(); - - [GeneratedRegex( - @"(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+", - RegexOptions.Compiled, - "zh-CN")] - private static partial Regex Pattern(); + .ToDictionary(x => x.Key, x => x.Value); /// - /// Created tokenizer + /// Static tokenizer /// - public static Tokenizer Tokenizer { get; } = TiktokenTokenizer.Create( + public static readonly ITokenizer Tokenizer = TokenizerBuilder.CreateTokenizer( DashScopeEmbeddedResource.ReadBpeFile(), - new RegexPreTokenizer(Pattern(), SpecialTokens), - null, - SpecialTokens); + SpecialTokens, + @"(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+"); /// - /// Encode text to tokens. + /// Encode text. /// - /// The text to encode. + /// The text to be encoded. /// - public static IReadOnlyList Encode(string text) + public static List Encode(string text) { - return Tokenizer.EncodeToIds(text); + return Tokenizer.Encode(text, false); } /// @@ -56,25 +43,42 @@ public static string Decode(int[] tokens) } /// - /// Get token count for text. + /// Count tokens. + /// + /// Input text. + /// + public int CountTokens(string text) + { + return Tokenizer.Encode(text).Count; + } + + /// + /// Split text to string tokens. + /// + /// Input text. + /// + public IReadOnlyList GetTokens(string text) + { + return Tokenizer.Encode(text).Select(x => Tokenizer.Decode(new[] { x })).ToList(); + } + + /// + /// Count tokens. /// - /// The text to tokenize. + /// The text to be tokenized. /// - public static int CountTokens(string text) + public static int CountTokensStatic(string text) { - return Tokenizer.CountTokens(text); + return Tokenizer.Encode(text).Count; } /// - /// Find the index of the maximum encoding capacity without surpassing the token limit. + /// Get tokens /// - /// The input text. - /// The maximum number of tokens to encode. - /// If the tokenizer's normalization is enabled, this will be set to in its normalized form; otherwise, this value will be set to . - /// The token count can be generated which should be smaller than the maximum token count. + /// The text to tokenizers. /// - public static int GetIndexByTokenCount(string text, int maxTokenCount, out string? normalizedText, out int tokenCount) + public static IReadOnlyList GetTokensStatic(string text) { - return Tokenizer.GetIndexByTokenCount(text, maxTokenCount, out normalizedText, out tokenCount); + return Tokenizer.Encode(text).Select(x => Tokenizer.Decode(new[] { x })).ToList(); } } diff --git a/src/Cnblogs.DashScope.Core/TextChatMessage.cs b/src/Cnblogs.DashScope.Core/TextChatMessage.cs index 7191191..f61a033 100644 --- a/src/Cnblogs.DashScope.Core/TextChatMessage.cs +++ b/src/Cnblogs.DashScope.Core/TextChatMessage.cs @@ -6,20 +6,7 @@ namespace Cnblogs.DashScope.Core; /// /// Represents a chat message between the user and the model. /// -/// 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. -/// Reasoning content for reasoning model. -/// Calls to the function. -[method: JsonConstructor] -public record TextChatMessage( - string Role, - string Content, - string? Name = null, - bool? Partial = null, - string? ReasoningContent = null, - List? ToolCalls = null) : IMessage +public record TextChatMessage : IMessage { /// /// Create chat message from an uploaded DashScope file. @@ -39,6 +26,50 @@ public TextChatMessage(IEnumerable fileIds) { } + /// + /// Represents a chat message between the user and the model. + /// + /// 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. + /// Reasoning content for reasoning model. + /// Calls to the function. + [JsonConstructor] + public TextChatMessage( + string role, + string content, + string? name = null, + bool? partial = null, + string? reasoningContent = null, + List? toolCalls = null) + { + this.Role = role; + this.Content = content; + this.Name = name; + this.Partial = partial; + this.ReasoningContent = reasoningContent; + this.ToolCalls = toolCalls; + } + + /// The role of this message. + public string Role { get; init; } + + /// The content of this message. + public string Content { get; init; } + + /// Used when role is tool, represents the function name of this message generated by. + public string? Name { get; init; } + + /// Notify model that next message should use this message as prefix. + public bool? Partial { get; init; } + + /// Reasoning content for reasoning model. + public string? ReasoningContent { get; init; } + + /// Calls to the function. + public List? ToolCalls { get; init; } + /// /// Creates a file message. /// diff --git a/src/Cnblogs.DashScope.Core/TextEmbeddingInput.cs b/src/Cnblogs.DashScope.Core/TextEmbeddingInput.cs index 41295eb..fb884a2 100644 --- a/src/Cnblogs.DashScope.Core/TextEmbeddingInput.cs +++ b/src/Cnblogs.DashScope.Core/TextEmbeddingInput.cs @@ -8,5 +8,5 @@ public class TextEmbeddingInput /// /// The texts to be computed. /// - public required IEnumerable Texts { get; set; } + public IEnumerable Texts { get; set; } = Array.Empty(); } diff --git a/src/Cnblogs.DashScope.Core/TextGenerationChoice.cs b/src/Cnblogs.DashScope.Core/TextGenerationChoice.cs index 6f5d7ab..51eb4ac 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationChoice.cs +++ b/src/Cnblogs.DashScope.Core/TextGenerationChoice.cs @@ -13,5 +13,5 @@ public class TextGenerationChoice /// /// The generated message. /// - public required TextChatMessage Message { get; set; } + public TextChatMessage Message { get; set; } = new(Array.Empty()); } diff --git a/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj b/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj index bc613d8..68ba835 100644 --- a/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj +++ b/src/Cnblogs.DashScope.Sdk/Cnblogs.DashScope.Sdk.csproj @@ -4,9 +4,6 @@ true Cnblogs;Dashscope;AI;Sdk;Embedding; - - - diff --git a/src/Cnblogs.DashScope.Sdk/FunctionDefinition.cs b/src/Cnblogs.DashScope.Sdk/FunctionDefinition.cs index 1344496..042f5c5 100644 --- a/src/Cnblogs.DashScope.Sdk/FunctionDefinition.cs +++ b/src/Cnblogs.DashScope.Sdk/FunctionDefinition.cs @@ -1,5 +1,4 @@ using Cnblogs.DashScope.Core; -using Json.Schema; namespace Cnblogs.DashScope.Sdk; @@ -13,8 +12,8 @@ public record FunctionDefinition : IFunctionDefinition /// /// The name of the function. /// Descriptions about this function for model to reference on. - /// Parameter maps of this function. - public FunctionDefinition(string name, string description, JsonSchema? parameters) + /// Parameter maps of this function, can be dictionary or JsonSchema. + public FunctionDefinition(string name, string description, object? parameters) { Name = name; Description = description; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs b/test/Cnblogs.DashScope.AI.UnitTests/ChatClientTests.cs similarity index 92% rename from test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs rename to test/Cnblogs.DashScope.AI.UnitTests/ChatClientTests.cs index c1f5096..84f54c9 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs +++ b/test/Cnblogs.DashScope.AI.UnitTests/ChatClientTests.cs @@ -1,12 +1,12 @@ using System.Text; using Cnblogs.DashScope.Core; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using Microsoft.Extensions.AI; using NSubstitute; using NSubstitute.Extensions; -namespace Cnblogs.DashScope.Sdk.UnitTests; +namespace Cnblogs.DashScope.AI.UnitTests; public class ChatClientTests { @@ -28,7 +28,7 @@ public async Task ChatClient_TextCompletion_SuccessAsync() // Act var response = await client.GetResponseAsync( content, - new ChatOptions() + new ChatOptions { FrequencyPenalty = parameter?.RepetitionPenalty, PresencePenalty = parameter?.PresencePenalty, @@ -69,7 +69,7 @@ public async Task ChatClient_TextCompletionStream_SuccessAsync() // Act var response = client.GetStreamingResponseAsync( content, - new ChatOptions() + new ChatOptions { FrequencyPenalty = parameter?.RepetitionPenalty, PresencePenalty = parameter?.PresencePenalty, @@ -79,7 +79,7 @@ public async Task ChatClient_TextCompletionStream_SuccessAsync() Temperature = parameter?.Temperature, TopK = parameter?.TopK, TopP = parameter?.TopP, - StopSequences = ["你好"], + StopSequences = new List { "你好" }, ToolMode = ChatToolMode.Auto }); var text = new StringBuilder(); @@ -113,7 +113,10 @@ public async Task ChatClient_ImageRecognition_SuccessAsync() { new( ChatRole.User, - [new DataContent(contents[0].Image!, "image/png"), new TextContent(contents[1].Text)]) + new List + { + new DataContent(contents[0].Image!, "image/png"), new TextContent(contents[1].Text) + }), }; var parameter = testCase.RequestModel.Parameters; @@ -157,14 +160,17 @@ public async Task ChatClient_ImageRecognitionStream_SuccessAsync() { new( ChatRole.User, - [new DataContent(contents[0].Image!, "image/png"), new TextContent(contents[1].Text)]) + new List + { + new DataContent(contents[0].Image!, "image/png"), new TextContent(contents[1].Text) + }) }; var parameter = testCase.RequestModel.Parameters; // Act var response = client.GetStreamingResponseAsync( messages, - new ChatOptions() + new ChatOptions { FrequencyPenalty = parameter?.RepetitionPenalty, PresencePenalty = parameter?.PresencePenalty, diff --git a/test/Cnblogs.DashScope.AI.UnitTests/Cnblogs.DashScope.AI.UnitTests.csproj b/test/Cnblogs.DashScope.AI.UnitTests/Cnblogs.DashScope.AI.UnitTests.csproj new file mode 100644 index 0000000..4c729f0 --- /dev/null +++ b/test/Cnblogs.DashScope.AI.UnitTests/Cnblogs.DashScope.AI.UnitTests.csproj @@ -0,0 +1,32 @@ + + + + net8.0 + enable + enable + false + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/EmbeddingClientTests.cs b/test/Cnblogs.DashScope.AI.UnitTests/EmbeddingClientTests.cs similarity index 91% rename from test/Cnblogs.DashScope.Sdk.UnitTests/EmbeddingClientTests.cs rename to test/Cnblogs.DashScope.AI.UnitTests/EmbeddingClientTests.cs index 96e21b4..f8bad1b 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/EmbeddingClientTests.cs +++ b/test/Cnblogs.DashScope.AI.UnitTests/EmbeddingClientTests.cs @@ -1,11 +1,11 @@ using Cnblogs.DashScope.Core; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using Microsoft.Extensions.AI; using NSubstitute; using NSubstitute.Extensions; -namespace Cnblogs.DashScope.Sdk.UnitTests; +namespace Cnblogs.DashScope.AI.UnitTests; public class EmbeddingClientTests { @@ -27,7 +27,7 @@ public async Task EmbeddingClient_Text_SuccessAsync() // Act var response = await client.GenerateAsync( content, - new EmbeddingGenerationOptions() + new EmbeddingGenerationOptions { ModelId = testCase.RequestModel.Model, Dimensions = parameter?.Dimension }); diff --git a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj index 8c791ae..c23a53c 100644 --- a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj +++ b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Cnblogs.DashScope.Sdk.SnapshotGenerator.csproj @@ -1,6 +1,7 @@  + net8.0 Exe false diff --git a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs index 3f99f6b..83ba9e2 100644 --- a/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs +++ b/test/Cnblogs.DashScope.Sdk.SnapshotGenerator/Program.cs @@ -11,7 +11,7 @@ apiKey = Console.ReadLine(); } -var handler = new SocketsHttpHandler() { AutomaticDecompression = DecompressionMethods.All, }; +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}"); diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs index a8021a0..d6de7a6 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ApplicationSerializationTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/BackgroundGenerationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/BackgroundGenerationSerializationTests.cs index 6754aa2..91c44c4 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/BackgroundGenerationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/BackgroundGenerationSerializationTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/BaiChuanApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/BaiChuanApiTests.cs index 1184b1a..0d99cac 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/BaiChuanApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/BaiChuanApiTests.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; using Cnblogs.DashScope.Sdk.BaiChuan; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using NSubstitute; namespace Cnblogs.DashScope.Sdk.UnitTests; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj index 981d700..efc5f63 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj @@ -1,39 +1,39 @@ - - false - true - + + net8.0 + false + true + - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - + + + - - - Always - - + + + Always + + - - - - + + + + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs index 5bc1956..461b037 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/DeepSeekTextGenerationApiTests.cs @@ -13,7 +13,9 @@ public async Task TextCompletion_UseEnum_SuccessAsync() var client = Substitute.For(); // Act - await client.GetDeepSeekChatCompletionAsync(DeepSeekLlm.DeepSeekR1, [TextChatMessage.User("你好")]); + await client.GetDeepSeekChatCompletionAsync( + DeepSeekLlm.DeepSeekR1, + new List { TextChatMessage.User("你好") }.AsReadOnly()); // Assert await client.Received().GetTextCompletionAsync( @@ -29,7 +31,9 @@ public async Task TextCompletion_UseCustomModel_SuccessAsync() var client = Substitute.For(); // Act - await client.GetDeepSeekChatCompletionAsync(customModel, [TextChatMessage.User("你好")]); + await client.GetDeepSeekChatCompletionAsync( + customModel, + new List { TextChatMessage.User("你好") }.AsReadOnly()); // Assert await client.Received().GetTextCompletionAsync( @@ -44,7 +48,9 @@ public void StreamCompletion_UseEnum_SuccessAsync() var client = Substitute.For(); // Act - _ = client.GetDeepSeekChatCompletionStreamAsync(DeepSeekLlm.DeepSeekV3, [TextChatMessage.User("你好")]); + _ = client.GetDeepSeekChatCompletionStreamAsync( + DeepSeekLlm.DeepSeekV3, + new List { TextChatMessage.User("你好") }.AsReadOnly()); // Assert _ = client.Received().GetTextCompletionStreamAsync( @@ -62,7 +68,9 @@ public void StreamCompletion_CustomModel_SuccessAsync() var client = Substitute.For(); // Act - _ = client.GetDeepSeekChatCompletionStreamAsync(customModel, [TextChatMessage.User("你好")]); + _ = client.GetDeepSeekChatCompletionStreamAsync( + customModel, + new List { TextChatMessage.User("你好") }.AsReadOnly()); // Assert _ = client.Received().GetTextCompletionStreamAsync( diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ErrorTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ErrorTests.cs index e660852..ba17907 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ErrorTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ErrorTests.cs @@ -1,5 +1,5 @@ using Cnblogs.DashScope.Core; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; using NSubstitute.ExceptionExtensions; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/FileSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/FileSerializationTests.cs index 05faa58..9b92f25 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/FileSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/FileSerializationTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ImageGenerationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ImageGenerationSerializationTests.cs index d0d30b7..752e922 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ImageGenerationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ImageGenerationSerializationTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ImageSynthesisSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ImageSynthesisSerializationTests.cs index 909c6bf..47013e0 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ImageSynthesisSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ImageSynthesisSerializationTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Llama2TextGenerationApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Llama2TextGenerationApiTests.cs index 29c1a8c..c4d5679 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Llama2TextGenerationApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Llama2TextGenerationApiTests.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; using Cnblogs.DashScope.Sdk.Llama2; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using NSubstitute; namespace Cnblogs.DashScope.Sdk.UnitTests; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs index 8889981..0170d0d 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/MultimodalGenerationSerializationTests.cs @@ -1,6 +1,6 @@ using System.Text; using Cnblogs.DashScope.Core; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs index e3b5424..c2c15ce 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenMultimodalApiTests.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; using Cnblogs.DashScope.Sdk.QWenMultimodal; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using NSubstitute; namespace Cnblogs.DashScope.Sdk.UnitTests; @@ -8,13 +8,15 @@ namespace Cnblogs.DashScope.Sdk.UnitTests; public class QWenMultimodalApiTests { private static readonly List Messages = - [ - MultimodalMessage.User( - [ - MultimodalMessageContent.ImageContent("https://cdn.example.com/image.jpg"), - MultimodalMessageContent.TextContent("说明一下这张图片的内容") - ]) - ]; + new() + { + MultimodalMessage.User( + new List + { + MultimodalMessageContent.ImageContent("https://cdn.example.com/image.jpg"), + MultimodalMessageContent.TextContent("说明一下这张图片的内容") + }.AsReadOnly()) + }; [Fact] public async Task Multimodal_UseEnum_SuccessAsync() diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTextGenerationApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTextGenerationApiTests.cs index ad9d5fb..ddd6640 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTextGenerationApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTextGenerationApiTests.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; using Cnblogs.DashScope.Sdk.QWen; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using NSubstitute; namespace Cnblogs.DashScope.Sdk.UnitTests; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTokenizerTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTokenizerTests.cs index 8f91a35..69f0192 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTokenizerTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/QWenTokenizerTests.cs @@ -9,475 +9,42 @@ public class QWenTokenizerTests "很不错的一款产品,送人的额,非常喜欢,很不错,好评哦,以后还会多多支持的\n已经吃了,感觉不错。第二次购买,这个价格很实惠,卖家还赠送了美容器和尺子,很愉悦的一次购物。\n衣服的质量杠杠的,很漂亮,不枉我等了这么久啊,喜欢,以后还来这里买,我一次买了四件不到200块钱,真好\n用了一段时间了,感觉比传统的风扇好用,广度大,档数多,静音效果也不错,关键是还很漂亮!\n这个热量低,比意面还低,关键是口感还好,挺好吃,多煮一会一级棒,我的减脂早餐就靠它了\n整体评价:好 使用效果:好 包装与外观:好 三好商品\n电视机很好,我给老爸买的,老人很喜欢,图像清晰,音质很好,老人喜欢我满意。\n宝贝很轻巧,打的时候网弹力很足,儿子非常喜欢,五分好评,还送了羽毛球噢!\n终于装上,风很大,热的还可以,排风声音不小,安装的师傅说不能直吹,安装的时候非常满意,最后还帮忙把棚顶给擦干净了,非常感谢。\n颜色很美。就是别人的盒子都是平整的,唯独我的盒子有很严重的压痕。本来想直接用这个盒子装胶带的..现在这个样子强迫症看着实在很糟心。压成这样要么包装有问题,要么本来产品就有问题。而卖家一直在甩锅快递。由于包裹是被家里人拆开的,所以我也不知道是什么样子的,不好跟卖家掰扯。但我看别的人都是纸盒装的,想来我这个也是纸盒装的。那么排除包装的原因的话,很可能就是寄过来的就是个瑕疵品。比起同样今天到货的另一家,有个小瑕疵立马给我补寄了一个,这家的处理方式真的..换货..或者直接道歉说疏忽我都接受的。甩锅真的不能忍。本来还给好几个人推了这家店...就挺失望的 以后应该不会来了。这坚定的甩锅态度我也不点退换了..请不要给我打电话改评,谢谢。"; private static readonly int[] Tokens = - [ - 109517, - 110659, - 82700, - 3837, - 36605, - 103947, - 61191, - 3837, - 115171, - 3837, - 109517, - 3837, - 102959, - 104170, - 3837, - 103934, - 104342, - 103235, - 100143, - 9370, - 198, - 99461, - 105705, - 3837, - 100681, - 100832, - 1773, - 106309, - 103946, - 3837, - 99487, - 97480, - 99165, - 109896, - 3837, - 108602, - 97706, - 109349, - 34187, - 105157, - 31548, - 33108, - 101489, - 44729, - 3837, - 99165, - 111985, - 99774, - 32571, - 102297, - 8997, - 102214, - 108042, - 103178, - 103178, - 9370, - 3837, - 117817, - 3837, - 16530, - 119117, - 35946, - 49567, - 34187, - 113260, - 103924, - 3837, - 99729, - 3837, - 103934, - 97706, - 115217, - 99565, - 3837, - 35946, - 99796, - 105275, - 63703, - 14224, - 99828, - 17, - 15, - 15, - 106734, - 3837, - 88051, - 52801, - 198, - 11622, - 99593, - 101430, - 34187, - 3837, - 100681, - 56006, - 105062, - 117814, - 52801, - 11622, - 3837, - 80942, - 26381, - 26288, - 3837, - 100104, - 8863, - 42140, - 3837, - 99541, - 78685, - 101062, - 116006, - 3837, - 111623, - 97706, - 117817, - 6313, - 198, - 99487, - 108461, - 99285, - 3837, - 56006, - 36589, - 27091, - 97706, - 99285, - 3837, - 111623, - 107816, - 108432, - 3837, - 101174, - 106678, - 3837, - 42140, - 104783, - 102947, - 105072, - 102321, - 3837, - 97611, - 99536, - 100553, - 102589, - 80158, - 99904, - 99652, - 34187, - 198, - 101932, - 103964, - 5122, - 52801, - 85658, - 101062, - 5122, - 52801, - 94305, - 227, - 98641, - 57218, - 105502, - 5122, - 52801, - 220, - 44991, - 52801, - 45943, - 198, - 115281, - 101243, - 3837, - 35946, - 89012, - 114198, - 108850, - 3837, - 102032, - 108295, - 3837, - 107553, - 104542, - 3837, - 78685, - 99178, - 101243, - 3837, - 102032, - 99729, - 35946, - 100545, - 8997, - 105882, - 99165, - 99578, - 100084, - 3837, - 75437, - 103920, - 31139, - 100080, - 47534, - 99165, - 99336, - 3837, - 102067, - 115171, - 3837, - 75108, - 17177, - 102959, - 3837, - 97706, - 36605, - 34187, - 116140, - 118401, - 6313, - 198, - 104020, - 98641, - 17447, - 3837, - 99208, - 101235, - 3837, - 99259, - 9370, - 104468, - 3837, - 59956, - 99208, - 102274, - 112592, - 3837, - 103999, - 9370, - 105476, - 36587, - 53153, - 73145, - 102203, - 3837, - 103999, - 103920, - 99491, - 100545, - 3837, - 100161, - 97706, - 106128, - 99360, - 103031, - 99743, - 89012, - 101432, - 102466, - 34187, - 3837, - 99491, - 104305, - 8997, - 102284, - 99165, - 57566, - 1773, - 99486, - 107693, - 110792, - 100132, - 112857, - 9370, - 3837, - 100473, - 99510, - 97611, - 110792, - 18830, - 99165, - 105806, - 99451, - 101629, - 1773, - 102347, - 99172, - 101041, - 11622, - 99487, - 110792, - 98641, - 100773, - 99278, - 9370, - 496, - 99601, - 99487, - 102481, - 111057, - 99769, - 101952, - 100538, - 99165, - 103336, - 63109, - 1773, - 99451, - 12857, - 99654, - 106016, - 104184, - 110686, - 3837, - 106016, - 102347, - 82700, - 104435, - 86119, - 1773, - 68536, - 108602, - 105078, - 107001, - 101240, - 104655, - 1773, - 101887, - 108232, - 20412, - 99250, - 102078, - 17340, - 101348, - 29767, - 9370, - 3837, - 107020, - 107066, - 102021, - 102481, - 9370, - 3837, - 101132, - 99557, - 108602, - 119059, - 105948, - 1773, - 105984, - 50930, - 62922, - 100623, - 100132, - 100050, - 102307, - 98641, - 9370, - 3837, - 99172, - 36407, - 35946, - 99487, - 100000, - 100050, - 102307, - 98641, - 9370, - 1773, - 100624, - 102945, - 104184, - 104249, - 100363, - 3837, - 107093, - 99486, - 101400, - 101180, - 105729, - 18947, - 117219, - 24442, - 1773, - 107957, - 101165, - 100644, - 26939, - 81668, - 9370, - 100266, - 45629, - 3837, - 104627, - 30709, - 117219, - 108628, - 104169, - 99622, - 101400, - 104059, - 3837, - 101610, - 9370, - 54542, - 75768, - 100672, - 496, - 71134, - 81668, - 496, - 100631, - 101041, - 107961, - 36587, - 100900, - 100310, - 107108, - 100669, - 9370, - 1773, - 107001, - 101240, - 100672, - 53153, - 100292, - 1773, - 102347, - 97706, - 89012, - 52801, - 112285, - 83751, - 34187, - 101610, - 71416, - 1112, - 80158, - 101174, - 106586, - 9370, - 220, - 103934, - 99730, - 99670, - 101161, - 1773, - 43288, - 102405, - 9370, - 107001, - 101240, - 102316, - 35946, - 99744, - 27442, - 55806, - 110735, - 496, - 14880, - 100148, - 104169, - 106202, - 22418, - 63379, - 3837, - 102570, - 1773 - ]; + new[] + { + 109517, 110659, 82700, 3837, 36605, 103947, 61191, 3837, 115171, 3837, 109517, 3837, 102959, 104170, + 3837, 103934, 104342, 103235, 100143, 9370, 198, 99461, 105705, 3837, 100681, 100832, 1773, 106309, + 103946, 3837, 99487, 97480, 99165, 109896, 3837, 108602, 97706, 109349, 34187, 105157, 31548, 33108, + 101489, 44729, 3837, 99165, 111985, 99774, 32571, 102297, 8997, 102214, 108042, 103178, 103178, 9370, + 3837, 117817, 3837, 16530, 119117, 35946, 49567, 34187, 113260, 103924, 3837, 99729, 3837, 103934, + 97706, 115217, 99565, 3837, 35946, 99796, 105275, 63703, 14224, 99828, 17, 15, 15, 106734, 3837, 88051, + 52801, 198, 11622, 99593, 101430, 34187, 3837, 100681, 56006, 105062, 117814, 52801, 11622, 3837, 80942, + 26381, 26288, 3837, 100104, 8863, 42140, 3837, 99541, 78685, 101062, 116006, 3837, 111623, 97706, + 117817, 6313, 198, 99487, 108461, 99285, 3837, 56006, 36589, 27091, 97706, 99285, 3837, 111623, 107816, + 108432, 3837, 101174, 106678, 3837, 42140, 104783, 102947, 105072, 102321, 3837, 97611, 99536, 100553, + 102589, 80158, 99904, 99652, 34187, 198, 101932, 103964, 5122, 52801, 85658, 101062, 5122, 52801, 94305, + 227, 98641, 57218, 105502, 5122, 52801, 220, 44991, 52801, 45943, 198, 115281, 101243, 3837, 35946, + 89012, 114198, 108850, 3837, 102032, 108295, 3837, 107553, 104542, 3837, 78685, 99178, 101243, 3837, + 102032, 99729, 35946, 100545, 8997, 105882, 99165, 99578, 100084, 3837, 75437, 103920, 31139, 100080, + 47534, 99165, 99336, 3837, 102067, 115171, 3837, 75108, 17177, 102959, 3837, 97706, 36605, 34187, + 116140, 118401, 6313, 198, 104020, 98641, 17447, 3837, 99208, 101235, 3837, 99259, 9370, 104468, 3837, + 59956, 99208, 102274, 112592, 3837, 103999, 9370, 105476, 36587, 53153, 73145, 102203, 3837, 103999, + 103920, 99491, 100545, 3837, 100161, 97706, 106128, 99360, 103031, 99743, 89012, 101432, 102466, 34187, + 3837, 99491, 104305, 8997, 102284, 99165, 57566, 1773, 99486, 107693, 110792, 100132, 112857, 9370, + 3837, 100473, 99510, 97611, 110792, 18830, 99165, 105806, 99451, 101629, 1773, 102347, 99172, 101041, + 11622, 99487, 110792, 98641, 100773, 99278, 9370, 496, 99601, 99487, 102481, 111057, 99769, 101952, + 100538, 99165, 103336, 63109, 1773, 99451, 12857, 99654, 106016, 104184, 110686, 3837, 106016, 102347, + 82700, 104435, 86119, 1773, 68536, 108602, 105078, 107001, 101240, 104655, 1773, 101887, 108232, 20412, + 99250, 102078, 17340, 101348, 29767, 9370, 3837, 107020, 107066, 102021, 102481, 9370, 3837, 101132, + 99557, 108602, 119059, 105948, 1773, 105984, 50930, 62922, 100623, 100132, 100050, 102307, 98641, 9370, + 3837, 99172, 36407, 35946, 99487, 100000, 100050, 102307, 98641, 9370, 1773, 100624, 102945, 104184, + 104249, 100363, 3837, 107093, 99486, 101400, 101180, 105729, 18947, 117219, 24442, 1773, 107957, 101165, + 100644, 26939, 81668, 9370, 100266, 45629, 3837, 104627, 30709, 117219, 108628, 104169, 99622, 101400, + 104059, 3837, 101610, 9370, 54542, 75768, 100672, 496, 71134, 81668, 496, 100631, 101041, 107961, 36587, + 100900, 100310, 107108, 100669, 9370, 1773, 107001, 101240, 100672, 53153, 100292, 1773, 102347, 97706, + 89012, 52801, 112285, 83751, 34187, 101610, 71416, 1112, 80158, 101174, 106586, 9370, 220, 103934, + 99730, 99670, 101161, 1773, 43288, 102405, 9370, 107001, 101240, 102316, 35946, 99744, 27442, 55806, + 110735, 496, 14880, 100148, 104169, 106202, 22418, 63379, 3837, 102570, 1773 + }; [Fact] public void QWenTokenizer_Encode_SuccessAsync() @@ -503,20 +70,9 @@ public void QWenTokenizer_Decode_SuccessAsync() public void QWenTokenizer_EncodeToStrings_SuccessAsync() { // Act - var tokens = QWenTokenizer.Tokenizer.EncodeToTokens(Text, out _); + var tokens = QWenTokenizer.Tokenizer.Encode(Text); // Assert - tokens.Select(t => t.Id).Should().BeEquivalentTo(Tokens); - } - - [Fact] - public void QWenTokenizer_CountIndex_SuccessAsync() - { - // Act - var maxIndex = QWenTokenizer.GetIndexByTokenCount(Text, 100, out _, out var tokenCount); - - // Assert - maxIndex.Should().Be(155); - tokenCount.Should().BeLessThanOrEqualTo(100); + tokens.Should().BeEquivalentTo(Tokens); } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/TaskSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/TaskSerializationTests.cs index 149d2db..745e9c5 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TaskSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TaskSerializationTests.cs @@ -1,5 +1,5 @@ using Cnblogs.DashScope.Core; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; namespace Cnblogs.DashScope.Sdk.UnitTests; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingApiTests.cs index bbe1abb..5ad66d3 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingApiTests.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; using Cnblogs.DashScope.Sdk.TextEmbedding; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using NSubstitute; namespace Cnblogs.DashScope.Sdk.UnitTests; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingSerializationTests.cs index a662ade..0b380ce 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TextEmbeddingSerializationTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs index de32581..9a9406e 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs @@ -1,6 +1,6 @@ using System.Text; using Cnblogs.DashScope.Core; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationStopConverterTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationStopConverterTests.cs index 26c4af3..e269682 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationStopConverterTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationStopConverterTests.cs @@ -50,20 +50,26 @@ public record TestObj(TextGenerationStop? Stop); public static TheoryData Data => new() { - { new TextGenerationStop("hello"), """{"stop":"hello"}""" }, - { new TextGenerationStop(["hello", "world"]), """{"stop":["hello","world"]}""" }, - { new TextGenerationStop([12, 334]), """{"stop":[12,334]}""" }, - { new TextGenerationStop([[12, 334]]), """{"stop":[[12,334]]}""" }, - { null, """{"stop":null}""" } + { new TextGenerationStop("hello"), @"{""stop"":""hello""}" }, + { + new TextGenerationStop(new List { "hello", "world" }.AsReadOnly()), + "{\"stop\":[\"hello\",\"world\"]}" + }, + { new TextGenerationStop(new[] { 12, 334 }), "{\"stop\":[12,334]}" }, + { + new TextGenerationStop(new List { new[] { 12, 334 } }.AsReadOnly()), + "{\"stop\":[[12,334]]}" + }, + { null, "{\"stop\":null}" } }; public static TheoryData InvalidJson => new() { - """{"stop":{}}""", - """{"stop":[1234,"hello"]}""", - """{"stop":["hello"}}""", - """{"stop":[[34243,"hello"]]}""", - """{"stop":[[34243,123]}}""" + "{\"stop\":{}}", + "{\"stop\":[1234,\"hello\"]}", + "{\"stop\":[\"hello\"}}", + "{\"stop\":[[34243,\"hello\"]]}", + "{\"stop\":[[34243,123]}}" }; } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/TokenizationSerializationTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/TokenizationSerializationTests.cs index 08e4cae..6c3a49b 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/TokenizationSerializationTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/TokenizationSerializationTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using FluentAssertions; using NSubstitute; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/ToolChoiceJsonConverterTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/ToolChoiceJsonConverterTests.cs index 077a4b0..c9a23c7 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/ToolChoiceJsonConverterTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/ToolChoiceJsonConverterTests.cs @@ -50,19 +50,19 @@ public record TestObj(ToolChoice? Choice); public static TheoryData Data => new() { - { ToolChoice.AutoChoice, """{"choice":"auto"}""" }, - { ToolChoice.NoneChoice, """{"choice":"none"}""" }, - { ToolChoice.FunctionChoice("weather"), """{"choice":{"type":"function","function":{"name":"weather"}}}""" }, - { null, """{"choice":null}""" } + { ToolChoice.AutoChoice, "{\"choice\":\"auto\"}" }, + { ToolChoice.NoneChoice, "{\"choice\":\"none\"}" }, + { ToolChoice.FunctionChoice("weather"), "{\"choice\":{\"type\":\"function\",\"function\":{\"name\":\"weather\"}}}" }, + { null, "{\"choice\":null}" } }; public static TheoryData InvalidJson => new() { - """{"choice":{}}""", - """{"choice":"other"}""", - """{"choice":{"type":"other"}}""", - """{"choice":{"type":"other", "function":{"name": "weather"}}}""", - """{"choice":{"type":"function", "function": "other"}}""" + "{\"choice\":{}}", + "{\"choice\":\"other\"}", + "{\"choice\":{\"type\":\"other\"}}", + "{\"choice\":{\"type\":\"other\", \"function\":{\"name\": \"weather\"}}}", + "{\"choice\":{\"type\":\"function\", \"function\": \"other\"}}" }; } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/GetCurrentWeatherParameters.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/GetCurrentWeatherParameters.cs deleted file mode 100644 index 3d606f3..0000000 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/GetCurrentWeatherParameters.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Text.Json.Serialization; -using Json.More; -using Json.Schema.Generation; - -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; - -public record GetCurrentWeatherParameters( - [property: Required] - [property: Description("要获取天气的省市名称,例如浙江省杭州市")] - string Location, - [property: JsonConverter(typeof(EnumStringConverter))] - [property: Description("温度单位")] - TemperatureUnit Unit = TemperatureUnit.Celsius); - -public enum TemperatureUnit -{ - Celsius, - Fahrenheit -} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs deleted file mode 100644 index 20f17f5..0000000 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.MultimodalGeneration.cs +++ /dev/null @@ -1,517 +0,0 @@ -using Cnblogs.DashScope.Core; - -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; - -public static partial class Snapshots -{ - public static class MultimodalGeneration - { - public static readonly RequestSnapshot, - ModelResponse> VlNoSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - Seed = 1234, - TopK = 100, - TopP = 0.81f, - Temperature = 1.1f, - VlHighResolutionImages = true, - RepetitionPenalty = 1.3f, - PresencePenalty = 1.2f, - MaxTokens = 120, - Stop = "你好" - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent("海滩。") - ])) - ]), - RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", - Usage = new MultimodalTokenUsage - { - OutputTokens = 3, - InputTokens = 3613, - ImageTokens = 3577 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> VlChatClientNoSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - MultimodalMessage.User( - [ - MultimodalMessageContent.ImageContent( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), - MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") - ]) - ] - }, - Parameters = new MultimodalParameters - { - Seed = 1234, - TopK = 100, - TopP = 0.81f, - Temperature = 1.1f, - RepetitionPenalty = 1.3f, - PresencePenalty = 1.2f, - MaxTokens = 120, - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent("海滩。") - ])) - ]), - RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", - Usage = new MultimodalTokenUsage - { - OutputTokens = 3, - InputTokens = 3613, - ImageTokens = 3577 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> VlSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - IncrementalOutput = true, - Seed = 1234, - TopK = 100, - TopP = 0.81f - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent( - "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") - ])) - ]), - RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", - Usage = new MultimodalTokenUsage - { - OutputTokens = 85, - InputTokens = 1283, - ImageTokens = 1247 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> VlChatClientSse = - new( - "multimodal-generation-vl", - new ModelRequest - { - Model = "qwen-vl-plus", - Input = new MultimodalInput - { - Messages = - [ - MultimodalMessage.User( - [ - MultimodalMessageContent.ImageContent( - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), - MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") - ]) - ] - }, - Parameters = new MultimodalParameters - { - IncrementalOutput = true, - Seed = 1234, - TopK = 100, - TopP = 0.81f, - } - }, - new ModelResponse - { - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent( - "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") - ])) - ]), - RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", - Usage = new MultimodalTokenUsage - { - 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 ModelRequest - { - Model = "qwen-audio-turbo", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - Seed = 1234, - TopK = 100, - TopP = 0.81f - } - }, - new ModelResponse - { - RequestId = "6b6738bd-dd9d-9e78-958b-02574acbda44", - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent( - "这段音频在说中文,内容是\"没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网\"。") - ])) - ]), - Usage = new MultimodalTokenUsage - { - InputTokens = 786, - OutputTokens = 38, - AudioTokens = 752 - } - }); - - public static readonly RequestSnapshot, - ModelResponse> - AudioSse = new( - "multimodal-generation-audio", - new ModelRequest - { - Model = "qwen-audio-turbo", - Input = new MultimodalInput - { - Messages = - [ - 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 - { - Seed = 1234, - TopK = 100, - TopP = 0.81f, - IncrementalOutput = true - } - }, - new ModelResponse - { - RequestId = "bb6ab962-af57-99f1-9af8-eb7016ebc18e", - Output = new MultimodalOutput( - [ - new MultimodalChoice( - "stop", - MultimodalMessage.Assistant( - [ - MultimodalMessageContent.TextContent("第一句话说了没有我互联网。") - ])) - ]), - 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 - } - }); - } -} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/WanxApiTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/WanxApiTests.cs index 5a2c830..ff05d7c 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/WanxApiTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/WanxApiTests.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; -using Cnblogs.DashScope.Sdk.UnitTests.Utils; using Cnblogs.DashScope.Sdk.Wanx; +using Cnblogs.DashScope.Tests.Shared.Utils; using NSubstitute; using NSubstitute.Extensions; diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs b/test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs index c6b3a98..0c1b445 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs @@ -1,4 +1,4 @@ -using Cnblogs.DashScope.Sdk.UnitTests.Utils; +using Cnblogs.DashScope.Tests.Shared.Utils; using NSubstitute; namespace Cnblogs.DashScope.Sdk.UnitTests; diff --git a/test/Cnblogs.DashScope.Tests.Shared/Cnblogs.DashScope.Tests.Shared.csproj b/test/Cnblogs.DashScope.Tests.Shared/Cnblogs.DashScope.Tests.Shared.csproj new file mode 100644 index 0000000..6c9b008 --- /dev/null +++ b/test/Cnblogs.DashScope.Tests.Shared/Cnblogs.DashScope.Tests.Shared.csproj @@ -0,0 +1,27 @@ + + + + net6.0 + enable + enable + false + + + + + + + + + + + + + + + + Always + + + + diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-message-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-message-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-conversation-generation-session-id-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-memory-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-single-generation-text-with-thought-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/application-workflow-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/application-workflow-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/auth-error-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/auth-error-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/background-generation-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/background-generation-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/batch-text-embedding-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/batch-text-embedding-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/cancel-completed-task-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/cancel-completed-task-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/cancel-completed-task-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/cancel-completed-task-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/cancel-completed-task-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/cancel-completed-task-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/cancel-completed-task-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/cancel-completed-task-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/cancel-completed-task-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/cancel-completed-task-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/cancel-completed-task-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/cancel-completed-task-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-partial-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/conversation-generation-message-with-files-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/conversation-generation-message-with-files-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/delete-file-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/delete-file-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/delete-file-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/delete-file-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/delete-file-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/delete-file-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/delete-file-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/delete-file-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/delete-file-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/delete-file-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/delete-file-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/delete-file-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-file-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-file-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-file-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-file-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-file-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-file-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-file-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-file-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-file-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-file-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-file-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-file-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-background-generation-success-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-background-generation-success-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-background-generation-success-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-background-generation-success-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-background-generation-success-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-background-generation-success-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-batch-text-embedding-success-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-batch-text-embedding-success-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-batch-text-embedding-success-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-batch-text-embedding-success-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-batch-text-embedding-success-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-batch-text-embedding-success-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-batch-text-embedding-success-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-batch-text-embedding-success-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-batch-text-embedding-success-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-batch-text-embedding-success-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-batch-text-embedding-success-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-batch-text-embedding-success-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-generation-success-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-generation-success-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-generation-success-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-generation-success-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-generation-success-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-generation-success-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-synthesis-success-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-synthesis-success-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-synthesis-success-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-image-synthesis-success-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-running-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-running-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-running-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-running-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-running-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-running-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-running-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-running-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-running-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-running-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-running-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-running-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-unknown-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-unknown-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-unknown-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-unknown-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-unknown-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-unknown-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-unknown-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-unknown-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-unknown-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-unknown-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/get-task-unknown-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-unknown-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-generation-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-generation-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/image-synthesis-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/image-synthesis-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-files-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-files-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-files-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-files-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-files-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-files-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-files-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-files-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-files-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-files-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-files-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-files-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-task-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-task-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-task-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-task-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-task-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-task-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-task-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-task-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-task-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-task-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/list-task-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/list-task-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-audio-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-audio-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-ocr-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/multimodal-generation-vl-video-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/parameter-error-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/parameter-error-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-json-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-json-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-reasoning-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.request.body.json similarity index 85% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.request.body.json index 67f0342..7e41d14 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.request.body.json +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.request.body.json @@ -32,13 +32,6 @@ "location": { "type": "string", "description": "要获取天气的省市名称,例如浙江省杭州市" - }, - "unit": { - "description": "温度单位", - "enum": [ - "Celsius", - "Fahrenheit" - ] } }, "required": [ diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-message-with-tools-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-with-tools-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/single-generation-text-sse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-text-sse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/test1.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/test1.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/test1.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/test1.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/test2.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/test2.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/test2.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/test2.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/text-embedding-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/text-embedding-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.request.body.json similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.request.body.json rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.request.body.json diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/tokenization-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/tokenization-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-error-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-error-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-error-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-error-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-error-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-error-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-error-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-error-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-error-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-error-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-error-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-error-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-nosse.request.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-nosse.request.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-nosse.request.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-nosse.request.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-nosse.response.body.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-nosse.response.body.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-nosse.response.body.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-nosse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-nosse.response.header.txt similarity index 100% rename from test/Cnblogs.DashScope.Sdk.UnitTests/RawHttpData/upload-file-nosse.response.header.txt rename to test/Cnblogs.DashScope.Tests.Shared/RawHttpData/upload-file-nosse.response.header.txt diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Cases.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Cases.cs similarity index 69% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Cases.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Cases.cs index 79daec6..88cef2f 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Cases.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Cases.cs @@ -1,8 +1,8 @@ using Cnblogs.DashScope.Core; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; -internal class Cases +public class Cases { public const string CustomModelName = "custom-model"; public const string Prompt = "hello"; @@ -11,5 +11,5 @@ internal class Cases public const string ImageUrl = "https://www.cnblogs.com/image.png"; public static readonly List TextMessages = - [TextChatMessage.System("you are a helpful assistant"), TextChatMessage.User("hello")]; + new() { TextChatMessage.System("you are a helpful assistant"), TextChatMessage.User("hello") }; } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Checkers.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Checkers.cs similarity index 94% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Checkers.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Checkers.cs index c7b6e36..0e66fbd 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Checkers.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Checkers.cs @@ -1,6 +1,6 @@ using System.Text.Json.Nodes; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static class Checkers { diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/EquivalentUtils.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/EquivalentUtils.cs similarity index 69% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/EquivalentUtils.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/EquivalentUtils.cs index 70f6e54..c643ab3 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/EquivalentUtils.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/EquivalentUtils.cs @@ -1,10 +1,10 @@ using FluentAssertions; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static class EquivalentUtils { - internal static bool IsEquivalent(this T left, T right) + public static bool IsEquivalent(this T left, T right) { try { diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/GetCurrentWeatherParameters.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/GetCurrentWeatherParameters.cs new file mode 100644 index 0000000..91f7524 --- /dev/null +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/GetCurrentWeatherParameters.cs @@ -0,0 +1,10 @@ +using Json.Schema.Generation; + +namespace Cnblogs.DashScope.Tests.Shared.Utils; + +public class GetCurrentWeatherParameters +{ + [Required] + [Description("要获取天气的省市名称,例如浙江省杭州市")] + public string Location { get; init; } = string.Empty; +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/MockHttpMessageHandler.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/MockHttpMessageHandler.cs similarity index 93% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/MockHttpMessageHandler.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/MockHttpMessageHandler.cs index 1aa1b78..bf8de9d 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/MockHttpMessageHandler.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/MockHttpMessageHandler.cs @@ -1,4 +1,4 @@ -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public class MockHttpMessageHandler : HttpMessageHandler { diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/RequestSnapshot.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/RequestSnapshot.cs similarity index 96% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/RequestSnapshot.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/RequestSnapshot.cs index 17596ff..4c01bc1 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/RequestSnapshot.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/RequestSnapshot.cs @@ -1,7 +1,7 @@ using System.Net; using System.Text; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public record RequestSnapshot(string Name, TResponse ResponseModel) { diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Application.cs similarity index 92% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Application.cs index 59cfe01..18cd978 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Application.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Application.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static partial class Snapshots { @@ -9,19 +9,19 @@ public static class Application public static readonly RequestSnapshot SinglePromptNoSse = new( "application-single-generation-text", - new ApplicationRequest() + new ApplicationRequest { - Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, - Parameters = new ApplicationParameters() + Input = new ApplicationInput { Prompt = "总结xUnit Test Patterns中的内容" }, + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, Seed = 1234, Temperature = 0.85f, - RagOptions = new ApplicationRagOptions() + RagOptions = new ApplicationRagOptions { - PipelineIds = ["thie5bysoj"], - FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] + PipelineIds = new List { "thie5bysoj" }.AsReadOnly(), + FileIds = new List { "file_d129d632800c45aa9e7421b30561f447_10207234" }.AsReadOnly() } } }, @@ -31,7 +31,8 @@ public static class Application "xUnit Test Patterns 提供了一套全面的指南,用于改进测试自动化和重构测试代码。以下是根据提供的文档内容总结的关键点:\n\n1. 测试自动化的目标包括帮助提高产品质量、帮助我们理解被测系统(SUT)、减少(并且不引入)风险、易于运行、编写和维护[4]。\n2. 在管理共享fixture方面,文档讨论了访问共享fixture以及触发共享fixture构造的方法[2]。\n3. 关于结果验证,文档提供了自我检查测试的方法,验证状态或行为,使用内置断言进行状态验证,以及验证直接输出和替代路径[2]。\n4. 当涉及到数据库时,文档提到了与数据库相关的测试问题、没有数据库的测试、数据库测试、存储过程测试、数据访问层测试,并强调确保开发者独立性[3]。\n5. 文档还涵盖了测试方法组织策略、测试命名约定、测试套件组织、运行测试组或单个测试、测试代码重用、测试文件组织等内容[5]。\n\n这些模式和实践旨在解决测试中的常见问题,如高测试维护成本、不可测试代码最小化、防止生产代码中的错误测试等[1]。通过应用这些模式,开发者可以创建更高效、更易于维护的自动化测试。", "stop", "b7250cba47db463ca851dfb4088e71d8", - [ + new List + { new ApplicationOutputThought( null, "agentRag", @@ -52,18 +53,20 @@ public static class Application "[]", null, "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"总结xUnit Test Patterns中的内容\"}") - ], - [ + }, + new List + { new ApplicationDocReference( "1", "Visual Summary of the Pattern Language", "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:Visual Summary of the Pattern Language\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\n", - [ + new List + { "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648", "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302" - ], + }, null), new ApplicationDocReference( "2", @@ -71,7 +74,7 @@ public static class Application "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", - [], + new List(), null), new ApplicationDocReference( "3", @@ -79,7 +82,7 @@ public static class Application "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", - [], + new List(), null), new ApplicationDocReference( "4", @@ -87,7 +90,7 @@ public static class Application "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", - [], + new List(), null), new ApplicationDocReference( "5", @@ -95,25 +98,31 @@ public static class Application "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n", - [], + new List(), null) - ]), - new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 2591, 290)]))); + }), + new ApplicationUsage( + new List { new ApplicationModelUsage("qwen-plus", 2591, 290) }))); public static readonly RequestSnapshot SinglePromptSse = new( "application-single-generation-text", - new ApplicationRequest() + new ApplicationRequest { - Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, - Parameters = new ApplicationParameters() + Input = new ApplicationInput { Prompt = "总结xUnit Test Patterns中的内容" }, + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, Seed = 1234, Temperature = 0.85f, IncrementalOutput = true, - RagOptions = new ApplicationRagOptions() { PipelineIds = ["thie5bysoj"], Tags = ["xUnit"] } + RagOptions = new ApplicationRagOptions + { + PipelineIds = + new List { "thie5bysoj" }.AsReadOnly(), Tags = + new List { "xUnit" }.AsReadOnly() + } } }, new ApplicationResponse( @@ -123,14 +132,15 @@ public static class Application "stop", "069db8223d514dab91185954dc5108de", null, - [ + new List + { new ApplicationDocReference( "2", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", - [], + new List(), null), new ApplicationDocReference( "3", @@ -138,7 +148,7 @@ public static class Application "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", - [], + new List(), null), new ApplicationDocReference( "4", @@ -146,7 +156,7 @@ public static class Application "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", - [], + new List(), null), new ApplicationDocReference( "5", @@ -154,27 +164,28 @@ public static class Application "file_d129d632800c45aa9e7421b30561f447_10207234", "xUnit Test Patterns", "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\n", - [], + new List(), null), - ]), - new ApplicationUsage([new ApplicationModelUsage("qwen-max-latest", 2304, 244)]))); + }), + new ApplicationUsage( + new List { new ApplicationModelUsage("qwen-max-latest", 2304, 244) }))); public static readonly RequestSnapshot SinglePromptWithThoughtsNoSse = new( "application-single-generation-text-with-thought", - new ApplicationRequest() + new ApplicationRequest { - Input = new ApplicationInput() { Prompt = "总结xUnit Test Patterns中的内容" }, - Parameters = new ApplicationParameters() + Input = new ApplicationInput { Prompt = "总结xUnit Test Patterns中的内容" }, + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, Seed = 1234, Temperature = 0.85f, - RagOptions = new ApplicationRagOptions() + RagOptions = new ApplicationRagOptions { - PipelineIds = ["thie5bysoj"], - FileIds = ["file_d129d632800c45aa9e7421b30561f447_10207234"] + PipelineIds = new List { "thie5bysoj" }.AsReadOnly(), + FileIds = new List { "file_d129d632800c45aa9e7421b30561f447_10207234" }.AsReadOnly() }, HasThoughts = true } @@ -185,7 +196,8 @@ public static class Application "《xUnit Test Patterns》是一本系统介绍单元测试模式与最佳实践的指南,主要帮助开发者设计可维护、高效且可靠的自动化测试。以下是其核心内容的总结:\n\n---\n\n### **核心主题与内容**\n1. **测试模式与反模式**\n - **关键模式**:如共享夹具管理(Shared Fixtures)、自定义断言(Custom Assertions)、预期对象(Expected Objects)等,用于解决测试代码重复、依赖管理等问题。\n - **反模式与问题**:如不可测试代码(Untestable Code)、测试逻辑混入生产代码(Test Logic in Production)、高维护成本(High Test Maintenance Cost)等,分析其成因与规避策略。\n\n2. **测试夹具管理**\n - **共享夹具**:如何构造、触发和访问共享测试环境(如数据库连接),避免测试间的副作用。\n - **数据库测试**:讨论是否依赖数据库进行测试、如何测试数据访问层、存储过程,以及确保开发者独立性的策略(如使用测试替身)。\n\n3. **测试验证策略**\n - **状态验证**:通过断言检查系统状态(如使用内置断言、Delta断言)。\n - **行为验证**:验证系统是否按预期调用方法(如模拟对象、过程式验证)。\n - **减少代码重复**:通过自定义断言、预期对象和验证方法统一结果检查逻辑。\n\n4. **测试自动化哲学与目标**\n - **目标**:提升代码质量、降低风险、易于编写和维护测试。\n - **经济性**:平衡测试投入与收益,优先覆盖关键路径(Happy Path)和替代路径(Alternative Paths)。\n\n5. **测试代码组织**\n - **结构化策略**:按类(Testcase Class per Class)、功能(Testcase Class per Feature)或夹具(Testcase Class per Fixture)组织测试用例。\n - **命名与套件管理**:使用清晰命名约定、分组测试套件(Test Suites)和依赖管理。\n\n6. **测试维护与演进**\n - **最小化维护成本**:通过模式(如测试工具方法、继承复用)适应系统变化。\n - **自检测试(Built-in Self-Test)**:确保测试本身的可信性。\n\n---\n\n### **书籍结构特点**\n- **问题驱动**:每章围绕具体问题(如“如何处理共享夹具?”)展开,提供模式、替代方案和权衡。\n- **视觉化总结**:通过图表展示模式间的关系,帮助读者理解复杂概念。\n- **实践导向**:结合代码示例与真实场景,指导如何应用模式解决测试中的常见痛点。\n\n---\n\n### **适用场景**\n- 开发中遇到测试代码重复、脆弱测试(Fragile Tests)或高维护成本时。\n- 需要设计复杂测试场景(如数据库交互、异步行为)时。\n- 团队希望建立统一的测试实践与规范时。\n\n通过遵循书中模式,开发者能构建更健壮、可维护的测试体系,最终提升软件质量和开发效率。", "stop", "9d81b84e95f844c29ee825ad8bb647bb", - [ + new List + { new ApplicationOutputThought( null, "agentRag", @@ -206,20 +218,21 @@ public static class Application null, "好的,我现在需要总结用户提供的xUnit Test Patterns中的内容。首先,用户给了几个文档片段,每个片段都来自同一本书的不同部分。我需要仔细分析这些片段,看看里面提到的关键点和主题。\n\n第一个文档提到了“Visual Summary of the Pattern Language”,里面有几个关键点,比如Minimize Untestable Code,Buggy Tests,Production Bugs,还有测试维护成本高的问题。可能这本书在讲如何设计和管理单元测试的模式,避免常见的问题,比如不可测试的代码和测试逻辑混入生产环境。\n\n第二个文档片段讲的是“Managing Shared Fixtures”和结果验证(Result Verification)。这里提到共享夹具的管理、触发构建,以及如何验证测试结果,包括状态验证和行为验证,还有减少测试代码重复的方法,比如使用Expected Objects和Custom Assertions。这说明书中详细讨论了测试夹具的设计和如何有效验证测试结果,避免重复代码。\n\n第三个文档涉及数据库测试的问题,比如如何测试数据访问层、存储过程,以及确保开发者独立性的策略。这部分可能讨论在测试中使用数据库的挑战和解决方案,例如是否使用数据库进行测试,或者如何隔离测试以避免依赖。\n\n第四个文档提到了测试自动化的目标和哲学,包括测试的经济性、提高质量、理解系统、降低风险、易于运行和维护等。这说明书中不仅提供技术模式,还强调测试策略和哲学的重要性,指导如何有效实施自动化测试。\n\n第五个文档讨论了测试用例的组织策略,比如按类、功能或夹具组织测试用例类,命名约定,测试套件的管理,以及测试代码的重用方法。这部分可能涉及如何结构化测试代码,提高可维护性和可读性。\n\n综合这些片段,xUnit Test Patterns似乎是一本关于单元测试设计和最佳实践的指南,涵盖测试模式、夹具管理、结果验证、数据库测试、测试自动化策略和测试代码组织。重点在于如何编写可维护、可靠且高效的测试,避免常见陷阱,如不可测试的代码、测试逻辑污染生产代码、高维护成本等。书中可能还讨论了如何在不同情境下选择适当的测试策略,例如是否使用共享夹具,如何处理数据库依赖,以及如何组织测试代码结构以提高复用性。\n\n现在需要将这些分析整理成一个简明扼要的总结,突出主要主题和关键点,确保涵盖各个文档片段提到的内容,并指出这本书的整体目的和结构。可能需要分点说明,让用户清晰了解书中的核心内容。", null) - ], + }, null), - new ApplicationUsage([new ApplicationModelUsage("deepseek-r1", 1129, 1126)]))); + new ApplicationUsage( + new List { new ApplicationModelUsage("deepseek-r1", 1129, 1126) }))); public static readonly RequestSnapshot SinglePromptWithMemoryNoSse = new( "application-single-generation-text-with-memory", - new ApplicationRequest() + new ApplicationRequest { - Input = new ApplicationInput() + Input = new ApplicationInput { Prompt = "我爱吃面食", MemoryId = "ffd8be2352d84c6b9350e91c865b512e" }, - Parameters = new ApplicationParameters() + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, @@ -234,7 +247,8 @@ public static class Application "那您一定会对面条、馒头或者饺子这些美食很感兴趣呢!如果您有特定的面食问题或者需要推荐相关的菜品,可以告诉我,我很乐意为您提供帮助[1]。", "stop", "cd395cb8d4604db786a14555fdcffa1a", - [ + new List + { new ApplicationOutputThought(null, "agentRag", "知识检索", "rag", "{}", null, "[]", null, "{}"), new ApplicationOutputThought( null, @@ -246,21 +260,22 @@ public static class Application "[\"[2025-3-16 20:47:40 周日] 用户喜欢吃面食。\"]", null, "{\"memory_id\":\"ffd8be2352d84c6b9350e91c865b512e\",\"query\":\"我爱吃面食\"}") - ], + }, null), - new ApplicationUsage([new ApplicationModelUsage("qwen-plus", 1201, 43)]))); + new ApplicationUsage( + new List { new ApplicationModelUsage("qwen-plus", 1201, 43) }))); public static readonly RequestSnapshot, ApplicationResponse> WorkflowNoSse = new( "application-workflow", - new ApplicationRequest() + new ApplicationRequest { - Input = new ApplicationInput() + Input = new ApplicationInput { BizParams = new TestApplicationBizParam("code"), Prompt = "请你跟我这样说" }, - Parameters = new ApplicationParameters() + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, @@ -277,13 +292,13 @@ public static readonly RequestSnapshot() + new ApplicationRequest { - Input = new ApplicationInput() + Input = new ApplicationInput { BizParams = new TestApplicationBizParam("code"), Prompt = "请你跟我这样说" }, - Parameters = new ApplicationParameters() + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, @@ -300,22 +315,22 @@ public static readonly RequestSnapshot ConversationSessionIdNoSse = new( "application-conversation-generation-session-id", - new ApplicationRequest() + new ApplicationRequest { Input = - new ApplicationInput() + new ApplicationInput { Prompt = "总结一下第一本书的内容", SessionId = "9995da2046a04b448dc5a562563f4835" }, - Parameters = new ApplicationParameters() + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, Seed = 1234, Temperature = 0.85f, - RagOptions = new ApplicationRagOptions() + RagOptions = new ApplicationRagOptions { - PipelineIds = ["ll6yfcnxjg"], + PipelineIds = new List { "ll6yfcnxjg" }.AsReadOnly(), MetadataFilter = new Dictionary { { "docType", "电子书" } } }, HasThoughts = true @@ -327,7 +342,8 @@ public static readonly RequestSnapshot + { new ApplicationOutputThought( null, "agentRag", @@ -348,34 +364,36 @@ public static readonly RequestSnapshot { new ApplicationModelUsage("deepseek-r1", 1283, 1081) }))); public static readonly RequestSnapshot ConversationMessageNoSse = new( "application-conversation-generation-message", - new ApplicationRequest() + new ApplicationRequest { - Input = new ApplicationInput() + Input = new ApplicationInput { Messages = - [ - ApplicationMessage.System("You are a helpful assistant."), - ApplicationMessage.User("你是谁?"), - ApplicationMessage.Assistant("我是阿里云开发的大规模语言模型,我叫通义千问。"), - ApplicationMessage.User("哪些人的主食偏好是米饭?"), - ], + new List + { + ApplicationMessage.System("You are a helpful assistant."), + ApplicationMessage.User("你是谁?"), + ApplicationMessage.Assistant("我是阿里云开发的大规模语言模型,我叫通义千问。"), + ApplicationMessage.User("哪些人的主食偏好是米饭?"), + }.AsReadOnly(), }, - Parameters = new ApplicationParameters() + Parameters = new ApplicationParameters { TopK = 100, TopP = 0.8f, Seed = 1234, Temperature = 0.85f, - RagOptions = new ApplicationRagOptions() + RagOptions = new ApplicationRagOptions { - PipelineIds = ["e6md69132k"], + PipelineIds = new List { "e6md69132k" }.AsReadOnly(), StructuredFilter = new Dictionary { { "年龄", 14 } } }, HasThoughts = true @@ -387,7 +405,8 @@ public static readonly RequestSnapshot + { new ApplicationOutputThought( null, "agentRag", @@ -408,8 +427,9 @@ public static readonly RequestSnapshot { new ApplicationModelUsage("qwen-plus", 344, 311) }))); } } diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Error.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Error.cs similarity index 84% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Error.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Error.cs index eb4ea63..f199963 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Error.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Error.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static partial class Snapshots { @@ -23,7 +23,7 @@ public static readonly TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = false } @@ -42,7 +42,11 @@ public static readonly new ModelRequest { Model = "qwen-max", - Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, + Input = new TextGenerationInput + { + Prompt = "请问 1+1 是多少?", Messages = + new List().AsReadOnly() + }, Parameters = new TextGenerationParameters { ResultFormat = "text", @@ -52,7 +56,7 @@ public static readonly TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = false } @@ -71,7 +75,11 @@ public static readonly new ModelRequest { Model = "qwen-max", - Input = new TextGenerationInput { Prompt = "请问 1+1 是多少?", Messages = [] }, + Input = new TextGenerationInput + { + Prompt = "请问 1+1 是多少?", Messages = + new List().AsReadOnly() + }, Parameters = new TextGenerationParameters { ResultFormat = "text", @@ -81,7 +89,7 @@ public static readonly TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = true } diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs new file mode 100644 index 0000000..9c6c3b3 --- /dev/null +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs @@ -0,0 +1,567 @@ +using Cnblogs.DashScope.Core; + +namespace Cnblogs.DashScope.Tests.Shared.Utils; + +public static partial class Snapshots +{ + public static class MultimodalGeneration + { + public static readonly RequestSnapshot, + ModelResponse> VlNoSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + new List + { + MultimodalMessage.System( + new List + { + MultimodalMessageContent.TextContent("You are a helpful assistant.") + }.AsReadOnly()), + MultimodalMessage.User( + new List + { + MultimodalMessageContent.ImageContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + }.AsReadOnly()) + }.AsReadOnly() + }, + Parameters = new MultimodalParameters + { + Seed = 1234, + TopK = 100, + TopP = 0.81f, + Temperature = 1.1f, + VlHighResolutionImages = true, + RepetitionPenalty = 1.3f, + PresencePenalty = 1.2f, + MaxTokens = 120, + Stop = "你好" + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + new List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List { MultimodalMessageContent.TextContent("海滩。") } + .AsReadOnly())) + }), + RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", + Usage = new MultimodalTokenUsage + { + OutputTokens = 3, + InputTokens = 3613, + ImageTokens = 3577 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> VlChatClientNoSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + new List + { + MultimodalMessage.User( + new List + { + MultimodalMessageContent.ImageContent( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + }.AsReadOnly()) + }.AsReadOnly() + }, + Parameters = new MultimodalParameters + { + Seed = 1234, + TopK = 100, + TopP = 0.81f, + Temperature = 1.1f, + RepetitionPenalty = 1.3f, + PresencePenalty = 1.2f, + MaxTokens = 120, + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + new List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List { MultimodalMessageContent.TextContent("海滩。") } + .AsReadOnly())) + }), + RequestId = "e81aa922-be6c-9f9d-bd4f-0f43e21fd913", + Usage = new MultimodalTokenUsage + { + OutputTokens = 3, + InputTokens = 3613, + ImageTokens = 3577 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> VlSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + new List + { + MultimodalMessage.System( + new List + { + MultimodalMessageContent.TextContent("You are a helpful assistant.") + }.AsReadOnly()), + MultimodalMessage.User( + new List + { + MultimodalMessageContent.ImageContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/images/dog_and_girl.jpeg"), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + }.AsReadOnly()) + }.AsReadOnly() + }, + Parameters = new MultimodalParameters + { + IncrementalOutput = true, + Seed = 1234, + TopK = 100, + TopP = 0.81f + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + new List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent( + "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") + }.AsReadOnly())) + }), + RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", + Usage = new MultimodalTokenUsage + { + OutputTokens = 85, + InputTokens = 1283, + ImageTokens = 1247 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> VlChatClientSse = + new( + "multimodal-generation-vl", + new ModelRequest + { + Model = "qwen-vl-plus", + Input = new MultimodalInput + { + Messages = + new List + { + MultimodalMessage.User( + new List + { + MultimodalMessageContent.ImageContent( + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="), + MultimodalMessageContent.TextContent("这个图片是哪里,请用简短的语言回答") + }.AsReadOnly()) + }.AsReadOnly() + }, + Parameters = new MultimodalParameters + { + IncrementalOutput = true, + Seed = 1234, + TopK = 100, + TopP = 0.81f, + } + }, + new ModelResponse + { + Output = new MultimodalOutput( + new List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent( + "这是一个海滩,有沙滩和海浪。在前景中坐着一个女人与她的宠物狗互动。背景中有海水、阳光及远处的海岸线。由于没有具体标识物或地标信息,我无法提供更精确的位置描述。这可能是一个公共海滩或是私人区域。重要的是要注意不要泄露任何个人隐私,并遵守当地的规定和法律法规。欣赏自然美景的同时请尊重环境和其他访客。") + }.AsReadOnly())) + }), + RequestId = "13c5644d-339c-928a-a09a-e0414bfaa95c", + Usage = new MultimodalTokenUsage + { + 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 = + new List + { + MultimodalMessage.User( + new List + { + 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.") + }.AsReadOnly()), + }.AsReadOnly() + }, + 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 List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent( + "读者对象 如果你是Linux环境下的系统管理员,那么学会编写shell脚本将让你受益匪浅。本书并未细述安装 Linux系统的每个步骤,但只要系统已安装好Linux并能运行起来,你就可以开始考虑如何让一些日常 的系统管理任务实现自动化。这时shell脚本编程就能发挥作用了,这也正是本书的作用所在。本书将 演示如何使用shell脚本来自动处理系统管理任务,包括从监测系统统计数据和数据文件到为你的老板 生成报表。 如果你是家用Linux爱好者,同样能从本书中获益。现今,用户很容易在诸多部件堆积而成的图形环境 中迷失。大多数桌面Linux发行版都尽量向一般用户隐藏系统的内部细节。但有时你确实需要知道内部 发生了什么。本书将告诉你如何启动Linux命令行以及接下来要做什么。通常,如果是执行一些简单任 务(比如文件管理) , 在命令行下操作要比在华丽的图形界面下方便得多。在命令行下有大量的命令 可供使用,本书将会展示如何使用它们。") + }.AsReadOnly())) + }), + 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 = + new List + { + MultimodalMessage.User( + new List + { + 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.") + }.AsReadOnly()), + }.AsReadOnly() + }, + 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 List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent( + "读者对象 如果你是Linux环境下的系统管理员,那么学会编写shell脚本将让你受益匪浅。本书并未细述安装 Linux系统的每个步骤,但只要系统已安装好Linux并能运行起来,你就可以开始考虑如何让一些日常 的系统管理任务实现自动化。这时shell脚本编程就能发挥作用了,这也正是本书的作用所在。本书将 演示如何使用shell脚本来自动处理系统管理任务,包括从监测系统统计数据和数据文件到为你的老板 生成报表。 如果你是家用Linux爱好者,同样能从本书中获益。现今,用户很容易在诸多部件堆积而成的图形环境 中迷失。大多数桌面Linux发行版都尽量向一般用户隐藏系统的内部细节。但有时你确实需要知道内部 发生了什么。本书将告诉你如何启动Linux命令行以及接下来要做什么。通常,如果是执行一些简单任 务(比如文件管理) , 在命令行下操作要比在华丽的图形界面下方便得多。在命令行下有大量的命令 可供使用,本书将会展示如何使用它们。") + }.AsReadOnly())) + }), + Usage = new MultimodalTokenUsage + { + InputTokens = 1248, + OutputTokens = 225, + ImageTokens = 1219 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + AudioNoSse = new( + "multimodal-generation-audio", + new ModelRequest + { + Model = "qwen-audio-turbo", + Input = new MultimodalInput + { + Messages = + new List + { + MultimodalMessage.System( + new List + { + MultimodalMessageContent.TextContent("You are a helpful assistant.") + }.AsReadOnly()), + MultimodalMessage.User( + new List + { + MultimodalMessageContent.AudioContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/2channel_16K.wav"), + MultimodalMessageContent.TextContent("这段音频在说什么,请用简短的语言回答") + }.AsReadOnly()) + }.AsReadOnly() + }, + Parameters = new MultimodalParameters + { + Seed = 1234, + TopK = 100, + TopP = 0.81f + } + }, + new ModelResponse + { + RequestId = "6b6738bd-dd9d-9e78-958b-02574acbda44", + Output = new MultimodalOutput( + new List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent( + "这段音频在说中文,内容是\"没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网未来没有我互联网\"。") + }.AsReadOnly())) + }), + Usage = new MultimodalTokenUsage + { + InputTokens = 786, + OutputTokens = 38, + AudioTokens = 752 + } + }); + + public static readonly RequestSnapshot, + ModelResponse> + AudioSse = new( + "multimodal-generation-audio", + new ModelRequest + { + Model = "qwen-audio-turbo", + Input = new MultimodalInput + { + Messages = + new List + { + MultimodalMessage.System( + new List + { + MultimodalMessageContent.TextContent("You are a helpful assistant.") + }.AsReadOnly()), + MultimodalMessage.User( + new List + { + MultimodalMessageContent.AudioContent( + "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/2channel_16K.wav"), + MultimodalMessageContent.TextContent("这段音频的第一句话说了什么?") + }.AsReadOnly()) + }.AsReadOnly() + }, + Parameters = new MultimodalParameters + { + Seed = 1234, + TopK = 100, + TopP = 0.81f, + IncrementalOutput = true + } + }, + new ModelResponse + { + RequestId = "bb6ab962-af57-99f1-9af8-eb7016ebc18e", + Output = new MultimodalOutput( + new List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent("第一句话说了没有我互联网。") + }.AsReadOnly())) + }), + 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 = + new List + { + MultimodalMessage.User( + new List + { + MultimodalMessageContent.VideoContent( + new List + { + "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" + }.AsReadOnly()), + MultimodalMessageContent.TextContent("描述这个视频的具体过程") + }.AsReadOnly()), + }.AsReadOnly() + }, + 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 List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent( + "这段视频展示了一场足球比赛的精彩瞬间。具体过程如下:\n\n1. **背景**:画面中是一个大型体育场,观众席上坐满了观众,气氛热烈。\n2. **球员位置**:球场上有两队球员,一队穿着红色球衣,另一队穿着蓝色球衣。守门员穿着绿色球衣,站在球门前准备防守。\n3. **射门动作**:一名身穿红色球衣的球员在禁区内接到队友传球后,迅速起脚射门。\n4. **守门员扑救**:守门员看到对方射门后,立即做出反应,向左侧跃出试图扑救。\n5. **进球瞬间**:尽管守门员尽力扑救,但皮球还是从他的右侧飞入了球网。\n\n整个过程充满了紧张和刺激,展示了足球比赛中的精彩时刻。") + }.AsReadOnly())) + }), + 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 = + new List + { + MultimodalMessage.User( + new List + { + MultimodalMessageContent.VideoContent( + new List + { + "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" + }.AsReadOnly()), + MultimodalMessageContent.TextContent("描述这个视频的具体过程") + }.AsReadOnly()), + }.AsReadOnly() + }, + 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 List + { + new MultimodalChoice( + "stop", + MultimodalMessage.Assistant( + new List + { + MultimodalMessageContent.TextContent( + "这段视频展示了一场足球比赛的精彩瞬间。具体过程如下:\n\n1. **背景**:画面中是一个大型体育场,观众席上坐满了观众,气氛热烈。\n2. **球员位置**:场上有两队球员,一队穿着红色球衣,另一队穿着蓝色球衣。守门员穿着绿色球衣,站在球门前准备防守。\n3. **射门动作**:一名身穿红色球衣的球员在禁区内接到队友传球后,迅速起脚射门。\n4. **扑救尝试**:守门员看到射门后立即做出反应,向左侧跃出试图扑救。\n5. **进球瞬间**:尽管守门员尽力扑救,但皮球还是从他的右侧飞入了球网。\n\n整个过程充满了紧张和刺激,展示了足球比赛中的精彩时刻。") + }.AsReadOnly())) + }), + Usage = new MultimodalTokenUsage + { + VideoTokens = 1440, + InputTokens = 1466, + OutputTokens = 176 + } + }); + } +} diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Tasks.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Tasks.cs similarity index 83% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Tasks.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Tasks.cs index 90b68ff..e0e20d1 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.Tasks.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Tasks.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static partial class Snapshots { @@ -58,16 +58,17 @@ public static readonly RequestSnapshot + { + new ImageSynthesisResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/1d/d4/20240301/8d820c8d/4c48fa53-2907-499b-b9ac-76477fe8d299-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=bEfLmd%2BarXgZyhxcVYOWs%2BovJb8%3D"), + new ImageSynthesisResult( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=fdPScmRkIXyH3TSaSaWwvVjxREQ%3D"), + new ImageSynthesisResult( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/0f/20240301/3ab595ad/ecfe06b3-b91c-4950-a932-49ea1619a1f9-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=gNuVAt8iy4X8Nl2l3K4Gu4f0ydw%3D"), + new ImageSynthesisResult( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/3d/20240301/3ab595ad/3fca748e-d491-458a-bb72-73649af33209-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=Mx5TueC9I9yfDno9rjzi48opHtM%3D") + }, TaskMetrics = new DashScopeTaskMetrics(4, 4, 0) }, new ImageSynthesisUsage(4))); @@ -89,10 +90,11 @@ public static readonly RequestSnapshot + { + new ImageGenerationResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-03-02/ac5d435a-9ea9-4287-8666-e1be7bbba943/20240302222213528791_style3_jxdf6o4zwy.jpg?Expires=1709475741&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=LM26fy1Pk8rCfPzihzpUqa3Vst8%3D") + } }, new ImageGenerationUsage(1))); @@ -109,25 +111,29 @@ public static readonly RequestSnapshot + { + new BackgroundGenerationResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_0_02dc0bba-8b1d-4648-8b95-eb2b92fe715d.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=OYstgSxWOl%2FOxYTLa2Mx3bi2RWw%3D"), + new BackgroundGenerationResult( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_1_e1af86ec-152a-4ebe-b2a0-b40a592043b2.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=p0UXTUdXfp0tFlt0K5tDsA%2Fxl1M%3D") + }, TaskMetrics = new DashScopeTaskMetrics(2, 2, 0), TextResults = new BackgroundGenerationTextResult( - [ + new List + { new BackgroundGenerationTextResultUrl( "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_0_4645005c-713d-4e92-9629-b12cbe5f3671.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=kmZGXc2s8P4uI%2BVrADITyrPz82U%3D"), new BackgroundGenerationTextResultUrl( "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_1_b1979b75-c553-4d9b-9c9f-80f401a0d124.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=cb1Qg%2FkIuZyI7XQqWHjP712N0ak%3D") - ], - [ + }, + new List + { new BackgroundGenerationTextResultParams( 0, - [ + new List + { new BackgroundGenerationTextResultLayer( 0, "text_mask", @@ -141,14 +147,15 @@ public static readonly RequestSnapshot + { new BackgroundGenerationTextResultGradientColorStop( "#521b0800", 0), new BackgroundGenerationTextResultGradientColorStop( "#521b08ff", 1) - ]) + }) { Coords = new Dictionary { @@ -194,14 +201,15 @@ public static readonly RequestSnapshot + { new BackgroundGenerationTextResultGradientColorStop( "#e6baa7ff", 0), new BackgroundGenerationTextResultGradientColorStop( "#e6baa7ff", 1) - ]) + }) { Coords = new Dictionary { @@ -232,10 +240,11 @@ public static readonly RequestSnapshot + { new BackgroundGenerationTextResultLayer( 0, "text_mask", @@ -247,14 +256,15 @@ public static readonly RequestSnapshot + { new BackgroundGenerationTextResultGradientColorStop( "#efeae400", 0), new BackgroundGenerationTextResultGradientColorStop( "#efeae4ff", 1) - ]) + }) { Coords = new Dictionary { @@ -299,14 +309,15 @@ public static readonly RequestSnapshot + { new BackgroundGenerationTextResultGradientColorStop( "#421f12ff", 0), new BackgroundGenerationTextResultGradientColorStop( "#421f12ff", 1) - ]) + }) { Coords = new Dictionary { @@ -340,8 +351,8 @@ public static readonly RequestSnapshot { - Input = new TextEmbeddingInput { Texts = ["代码改变世界"] }, + Input = new TextEmbeddingInput { Texts = new List { "代码改变世界" }.AsReadOnly() }, Model = "text-embedding-v2", Parameters = new TextEmbeddingParameters { TextType = "query" } }, new ModelResponse { - Output = new TextEmbeddingOutput([new TextEmbeddingItem(0, [])]), + Output = new TextEmbeddingOutput(new List { new TextEmbeddingItem(0, new float[0]) }), RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", Usage = new TextEmbeddingTokenUsage(3) }); @@ -27,13 +27,13 @@ public static class TextEmbedding "text-embedding", new ModelRequest { - Input = new TextEmbeddingInput { Texts = ["代码改变世界"] }, + Input = new TextEmbeddingInput { Texts = new List { "代码改变世界" }.AsReadOnly() }, Model = "text-embedding-v3", Parameters = new TextEmbeddingParameters { Dimension = 1024 } }, new ModelResponse { - Output = new TextEmbeddingOutput([new TextEmbeddingItem(0, [])]), + Output = new TextEmbeddingOutput(new List { new TextEmbeddingItem(0, new float[0]) }), RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", Usage = new TextEmbeddingTokenUsage(3) }); diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs similarity index 57% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs index eca1ed8..2c03649 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.TextGeneration.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs @@ -1,8 +1,9 @@ using Cnblogs.DashScope.Core; +using Cnblogs.DashScope.Sdk; using Json.Schema; using Json.Schema.Generation; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static partial class Snapshots { @@ -27,17 +28,15 @@ public static class TextFormat TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = false } }, new ModelResponse { - Output = new TextGenerationOutput - { - FinishReason = "stop", Text = "1+1等于2。这是最基本的数学加法运算之一。" - }, + Output = + new TextGenerationOutput { FinishReason = "stop", Text = "1+1等于2。这是最基本的数学加法运算之一。" }, RequestId = "7e3d5586-cb70-98ce-97bf-8a2ac0091c3f", Usage = new TextGenerationTokenUsage { @@ -65,7 +64,7 @@ public static class TextFormat TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = true } @@ -93,7 +92,11 @@ public static class MessageFormat { Model = "qwen-max", Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() + }, Parameters = new TextGenerationParameters { ResultFormat = "message", @@ -103,7 +106,7 @@ public static class MessageFormat TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = false } @@ -113,14 +116,15 @@ public static class MessageFormat Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") + } } - ] }, RequestId = "e764bfe3-c0b7-97a0-ae57-cd99e1580960", Usage = new TextGenerationTokenUsage @@ -139,26 +143,29 @@ public static class MessageFormat { Model = "deepseek-r1", Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, - Parameters = new TextGenerationParameters - { - IncrementalOutput = false - } + new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() + }, + Parameters = new TextGenerationParameters { IncrementalOutput = false } }, new ModelResponse { Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1 + 1 等于 **2**。这是基础的算术加法,当我们将一个单位与另一个单位相加时,总和为两个单位。", - reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但可能有一些需要注意的地方。首先,我得确认用户是不是真的在问基本的数学问题,还是有其他的意图,比如测试我的反应或者开玩笑。\n\n1加1在基础算术里确实是2,但有时候可能会有不同的解释,比如在二进制中1+1等于10,或者在逻辑学中有时候表示为1,如果是布尔代数的话。不过通常情况下,用户可能只需要最直接的答案,也就是2。\n\n不过也有可能用户想考察我是否能够处理更复杂的情况,或者是否有隐藏的意思。比如,在某些情况下,1加1可能被用来比喻合作的效果,比如“1+1大于2”,但这可能超出了当前问题的范围。\n\n我需要考虑用户的背景。如果用户是小学生,那么直接回答2是正确的,并且可能需要鼓励的话。如果是成年人,可能还是同样的答案,但不需要额外的解释。如果用户来自数学或计算机领域,可能需要确认是否需要其他进制的答案,但通常默认是十进制。\n\n另外,检查是否有拼写错误或非阿拉伯数字的情况,比如罗马数字的I+I,但问题里明确写的是1+1,所以应该是阿拉伯数字。\n\n总结下来,最安全也是最正确的答案就是2。不过为了确保,可以简短地确认用户的意图,但按照常规问题处理,直接回答即可。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = + TextChatMessage.Assistant( + "1 + 1 等于 **2**。这是基础的算术加法,当我们将一个单位与另一个单位相加时,总和为两个单位。", + reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但可能有一些需要注意的地方。首先,我得确认用户是不是真的在问基本的数学问题,还是有其他的意图,比如测试我的反应或者开玩笑。\n\n1加1在基础算术里确实是2,但有时候可能会有不同的解释,比如在二进制中1+1等于10,或者在逻辑学中有时候表示为1,如果是布尔代数的话。不过通常情况下,用户可能只需要最直接的答案,也就是2。\n\n不过也有可能用户想考察我是否能够处理更复杂的情况,或者是否有隐藏的意思。比如,在某些情况下,1加1可能被用来比喻合作的效果,比如“1+1大于2”,但这可能超出了当前问题的范围。\n\n我需要考虑用户的背景。如果用户是小学生,那么直接回答2是正确的,并且可能需要鼓励的话。如果是成年人,可能还是同样的答案,但不需要额外的解释。如果用户来自数学或计算机领域,可能需要确认是否需要其他进制的答案,但通常默认是十进制。\n\n另外,检查是否有拼写错误或非阿拉伯数字的情况,比如罗马数字的I+I,但问题里明确写的是1+1,所以应该是阿拉伯数字。\n\n总结下来,最安全也是最正确的答案就是2。不过为了确保,可以简短地确认用户的意图,但按照常规问题处理,直接回答即可。") + } } - ] }, RequestId = "7039d8ff-89e0-9191-b4d3-0d258a7d70e1", Usage = new TextGenerationTokenUsage @@ -177,7 +184,11 @@ public static class MessageFormat { Model = "qwen-max", Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() + }, Parameters = new TextGenerationParameters { ResultFormat = "message", @@ -195,14 +206,15 @@ public static class MessageFormat Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何两个相同的数字相加都等于该数字的二倍。") + } } - ] }, RequestId = "e764bfe3-c0b7-97a0-ae57-cd99e1580960", Usage = new TextGenerationTokenUsage @@ -221,7 +233,12 @@ public static class MessageFormat { Model = "qwen-max", Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?用 JSON 格式输出。")] }, + new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("请问 1+1 是多少?用 JSON 格式输出。") } + .AsReadOnly() + }, Parameters = new TextGenerationParameters { ResultFormat = "message", @@ -231,7 +248,7 @@ public static class MessageFormat TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = false, ResponseFormat = DashScopeResponseFormat.Json @@ -242,13 +259,14 @@ public static class MessageFormat Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant("{\n \"result\": 2\n}") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant("{\n \"result\": 2\n}") + } } - ] }, RequestId = "6af9571b-1033-98f9-a287-c06f2e9d6f7f", Usage = new TextGenerationTokenUsage @@ -267,7 +285,11 @@ public static class MessageFormat { Model = "qwen-max", Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() + }, Parameters = new TextGenerationParameters { ResultFormat = "message", @@ -277,7 +299,7 @@ public static class MessageFormat TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = true } @@ -287,14 +309,15 @@ public static class MessageFormat Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") + } } - ] }, RequestId = "d272255f-82d7-9cc7-93c5-17ff77024349", Usage = new TextGenerationTokenUsage @@ -304,6 +327,7 @@ public static class MessageFormat InputTokens = 8 } }); + public static readonly RequestSnapshot, ModelResponse> SingleMessageReasoningIncremental = new( @@ -312,26 +336,28 @@ public static class MessageFormat { Model = "deepseek-r1", Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, - Parameters = new TextGenerationParameters - { - IncrementalOutput = true - } + new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() + }, + Parameters = new TextGenerationParameters { IncrementalOutput = true } }, new ModelResponse { Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 在基础算术中的答案是 **2**。\n\n不过,根据不同的数学或逻辑系统,结果可能不同:\n- **二进制**:1+1 = 10(读作“一零”)。\n- **布尔代数**:1+1 = 1(逻辑“或”运算)。\n- **抽象场景**:如“1滴水 + 1滴水 = 1大滴水”(非数学意义的合并)。\n\n日常问题中默认使用十进制算术,因此答案是 **2** \ud83d\ude0a。", - reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但其实可能有很多种情况需要考虑。首先,我得确定用户是不是在问数学上的基本加法。通常来说,1加1等于2,这是数学里的基本事实,根据皮亚诺公理或者基本的算术规则。不过,有时候问题可能有隐藏的含义,特别是在不同的语境下,答案可能会不同。比如在二进制中,1+1等于10,或者在布尔代数中,1+1可能等于1,如果是逻辑或运算的话。不过大部分情况下,尤其是在日常交流中,人们提到1+1的时候都是指十进制加法,结果自然是2。不过也有可能用户是在测试我的反应,或者想看看我会不会考虑其他可能性。比如在特定的谜语或笑话中,答案可能不是2,比如“1滴水加1滴水还是1滴水”,或者类似的文字游戏。但根据常规问题,我应该先给出正确的数学答案,再补充可能的其他情况,这样既准确又全面。所以可能先回答2,然后解释其他可能性。不过用户的问题看起来直接,可能不需要太复杂的解释,但为了保险起见,还是确认一下是否有其他意图比较好。或者用户可能只是单纯想知道答案,所以直接回答2即可。需要平衡简洁和全面性。可能先给出直接答案,然后简单说明其他情况的存在,这样既满足需求,又避免信息过载。总之,核心答案应该是2,但根据情况适当扩展。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 在基础算术中的答案是 **2**。\n\n不过,根据不同的数学或逻辑系统,结果可能不同:\n- **二进制**:1+1 = 10(读作“一零”)。\n- **布尔代数**:1+1 = 1(逻辑“或”运算)。\n- **抽象场景**:如“1滴水 + 1滴水 = 1大滴水”(非数学意义的合并)。\n\n日常问题中默认使用十进制算术,因此答案是 **2** \ud83d\ude0a。", + reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但其实可能有很多种情况需要考虑。首先,我得确定用户是不是在问数学上的基本加法。通常来说,1加1等于2,这是数学里的基本事实,根据皮亚诺公理或者基本的算术规则。不过,有时候问题可能有隐藏的含义,特别是在不同的语境下,答案可能会不同。比如在二进制中,1+1等于10,或者在布尔代数中,1+1可能等于1,如果是逻辑或运算的话。不过大部分情况下,尤其是在日常交流中,人们提到1+1的时候都是指十进制加法,结果自然是2。不过也有可能用户是在测试我的反应,或者想看看我会不会考虑其他可能性。比如在特定的谜语或笑话中,答案可能不是2,比如“1滴水加1滴水还是1滴水”,或者类似的文字游戏。但根据常规问题,我应该先给出正确的数学答案,再补充可能的其他情况,这样既准确又全面。所以可能先回答2,然后解释其他可能性。不过用户的问题看起来直接,可能不需要太复杂的解释,但为了保险起见,还是确认一下是否有其他意图比较好。或者用户可能只是单纯想知道答案,所以直接回答2即可。需要平衡简洁和全面性。可能先给出直接答案,然后简单说明其他情况的存在,这样既满足需求,又避免信息过载。总之,核心答案应该是2,但根据情况适当扩展。") + } } - ] }, RequestId = "e4ad5d0f-8019-9716-adc6-eae1411d3c9a", Usage = new TextGenerationTokenUsage @@ -350,7 +376,11 @@ public static class MessageFormat { Model = "qwen-max", Input = - new TextGenerationInput { Messages = [TextChatMessage.User("请问 1+1 是多少?")] }, + new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() + }, Parameters = new TextGenerationParameters { ResultFormat = "message", @@ -370,14 +400,15 @@ public static class MessageFormat Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "1+1 等于 2。这是最基本的数学加法之一,在十进制计数体系中,任何情况下 1 加上另一个 1 的结果都是 2。") + } } - ] }, RequestId = "d272255f-82d7-9cc7-93c5-17ff77024349", Usage = new TextGenerationTokenUsage @@ -396,8 +427,12 @@ public static readonly new ModelRequest { Model = "qwen-max", - Input = new TextGenerationInput { Messages = [TextChatMessage.User("杭州现在的天气如何?")] }, - Parameters = new TextGenerationParameters() + Input = new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("杭州现在的天气如何?") }.AsReadOnly() + }, + Parameters = new TextGenerationParameters { ResultFormat = "message", Seed = 1234, @@ -411,19 +446,21 @@ public static readonly EnableSearch = false, IncrementalOutput = false, Tools = - [ - new ToolDefinition( - "function", - new FunctionDefinition( - "get_current_weather", - "获取现在的天气", - new JsonSchemaBuilder().FromType( - new SchemaGeneratorConfiguration - { - PropertyNameResolver = PropertyNameResolvers.LowerSnakeCase - }) - .Build())) - ], + new List + { + new( + "function", + new FunctionDefinition( + "get_current_weather", + "获取现在的天气", + new JsonSchemaBuilder().FromType( + new SchemaGeneratorConfiguration + { + PropertyNameResolver = + PropertyNameResolvers.LowerSnakeCase + }) + .Build())) + }.AsReadOnly(), ToolChoice = ToolChoice.FunctionChoice("get_current_weather") } }, @@ -432,24 +469,26 @@ public static readonly Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - string.Empty, - toolCalls: - [ - new ToolCall( - "call_cec4c19d27624537b583af", - ToolTypes.Function, - 0, - new FunctionCall( - "get_current_weather", - """{"location": "浙江省杭州市"}""")) - ]) + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + string.Empty, + toolCalls: + new List + { + new ToolCall( + "call_cec4c19d27624537b583af", + ToolTypes.Function, + 0, + new FunctionCall( + "get_current_weather", + "{\"location\": \"浙江省杭州市\"}")) + }) + } } - ] }, RequestId = "67300049-c108-9987-b1c1-8e0ee2de6b5d", Usage = new TextGenerationTokenUsage @@ -468,8 +507,12 @@ public static readonly new ModelRequest { Model = "qwen-max", - Input = new TextGenerationInput { Messages = [TextChatMessage.User("杭州现在的天气如何?")] }, - Parameters = new TextGenerationParameters() + Input = new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("杭州现在的天气如何?") }.AsReadOnly() + }, + Parameters = new TextGenerationParameters { ResultFormat = "message", Seed = 1234, @@ -480,19 +523,21 @@ public static readonly PresencePenalty = 1.2f, Temperature = 0.85f, Tools = - [ - new ToolDefinition( - "function", - new FunctionDefinition( - "get_current_weather", - "获取现在的天气", - new JsonSchemaBuilder().FromType( - new SchemaGeneratorConfiguration - { - PropertyNameResolver = PropertyNameResolvers.LowerSnakeCase - }) - .Build())) - ], + new List + { + new ToolDefinition( + "function", + new FunctionDefinition( + "get_current_weather", + "获取现在的天气", + new JsonSchemaBuilder().FromType( + new SchemaGeneratorConfiguration + { + PropertyNameResolver = + PropertyNameResolvers.LowerSnakeCase + }) + .Build())) + }.AsReadOnly(), ToolChoice = ToolChoice.FunctionChoice("get_current_weather") } }, @@ -501,24 +546,26 @@ public static readonly Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - string.Empty, - toolCalls: - [ - new ToolCall( - "call_cec4c19d27624537b583af", - ToolTypes.Function, - 0, - new FunctionCall( - "get_current_weather", - """{"location": "浙江省杭州市"}""")) - ]) + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + string.Empty, + toolCalls: + new List + { + new ToolCall( + "call_cec4c19d27624537b583af", + ToolTypes.Function, + 0, + new FunctionCall( + "get_current_weather", + "{\"location\": \"浙江省杭州市\"}")) + }) + } } - ] }, RequestId = "67300049-c108-9987-b1c1-8e0ee2de6b5d", Usage = new TextGenerationTokenUsage @@ -533,18 +580,19 @@ public static readonly ModelResponse> ConversationPartialMessageNoSse = new( "conversation-generation-message-partial", - new ModelRequest() + new ModelRequest { Model = "qwen-max", - Input = new TextGenerationInput() + Input = new TextGenerationInput { Messages = - [ - TextChatMessage.User("请对“春天来了,大地”这句话进行续写,来表达春天的美好和作者的喜悦之情"), - TextChatMessage.Assistant("春天来了,大地", true) - ] + new List + { + TextChatMessage.User("请对“春天来了,大地”这句话进行续写,来表达春天的美好和作者的喜悦之情"), + TextChatMessage.Assistant("春天来了,大地", true) + }.AsReadOnly() }, - Parameters = new TextGenerationParameters() + Parameters = new TextGenerationParameters { ResultFormat = ResultFormats.Message, Seed = 1234, @@ -552,27 +600,28 @@ public static readonly TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false } }, - new ModelResponse() + new ModelResponse { RequestId = "4c45d7fd-3158-9ff4-96a0-6e92c710df2c", - Output = new TextGenerationOutput() + Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice() + new List { - FinishReason = "stop", - Message = - TextChatMessage.Assistant( - "仿佛从漫长的冬眠中苏醒过来,万物复苏。嫩绿的小草悄悄地探出了头,争先恐后地想要沐浴在温暖的阳光下;五彩斑斓的花朵也不甘示弱,竞相绽放着自己最美丽的姿态,将田野、山林装扮得分外妖娆。微风轻轻吹过,带来了泥土的气息与花香混合的独特香味,让人心旷神怡。小鸟们开始忙碌起来,在枝头欢快地歌唱,似乎也在庆祝这个充满希望的新季节的到来。这一切美好景象不仅让人感受到了大自然的魅力所在,更激发了人们对生活无限热爱和向往的心情。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = + TextChatMessage.Assistant( + "仿佛从漫长的冬眠中苏醒过来,万物复苏。嫩绿的小草悄悄地探出了头,争先恐后地想要沐浴在温暖的阳光下;五彩斑斓的花朵也不甘示弱,竞相绽放着自己最美丽的姿态,将田野、山林装扮得分外妖娆。微风轻轻吹过,带来了泥土的气息与花香混合的独特香味,让人心旷神怡。小鸟们开始忙碌起来,在枝头欢快地歌唱,似乎也在庆祝这个充满希望的新季节的到来。这一切美好景象不仅让人感受到了大自然的魅力所在,更激发了人们对生活无限热爱和向往的心情。") + } } - ] }, - Usage = new TextGenerationTokenUsage() + Usage = new TextGenerationTokenUsage { TotalTokens = 165, OutputTokens = 131, @@ -591,11 +640,12 @@ public static readonly new TextGenerationInput { Messages = - [ - TextChatMessage.User("现在请你记住一个数字,42"), - TextChatMessage.Assistant("好的,我已经记住了这个数字。"), - TextChatMessage.User("请问我刚才提到的数字是多少?") - ] + new List + { + TextChatMessage.User("现在请你记住一个数字,42"), + TextChatMessage.Assistant("好的,我已经记住了这个数字。"), + TextChatMessage.User("请问我刚才提到的数字是多少?") + }.AsReadOnly() }, Parameters = new TextGenerationParameters { @@ -606,7 +656,7 @@ public static readonly TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = true } @@ -616,12 +666,14 @@ public static readonly Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", Message = TextChatMessage.Assistant("您刚才提到的数字是42。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant("您刚才提到的数字是42。") + } } - ] }, RequestId = "9188e907-56c2-9849-97f6-23f130f7fed7", Usage = new TextGenerationTokenUsage @@ -643,11 +695,16 @@ public static readonly new TextGenerationInput { Messages = - [ - TextChatMessage.File( - ["file-fe-WTTG89tIUTd4ByqP3K48R3bn", "file-fe-l92iyRvJm9vHCCfonLckf1o2"]), - TextChatMessage.User("这两个文件是相同的吗?") - ] + new List + { + TextChatMessage.File( + new List + { + "file-fe-WTTG89tIUTd4ByqP3K48R3bn", + "file-fe-l92iyRvJm9vHCCfonLckf1o2" + }.AsReadOnly()), + TextChatMessage.User("这两个文件是相同的吗?") + }.AsReadOnly() }, Parameters = new TextGenerationParameters { @@ -658,7 +715,7 @@ public static readonly TopK = 100, RepetitionPenalty = 1.1f, Temperature = 0.85f, - Stop = new int[][] { [37763, 367] }, + Stop = new[] { new[] { 37763, 367 } }, EnableSearch = false, IncrementalOutput = true } @@ -668,14 +725,15 @@ public static readonly Output = new TextGenerationOutput { Choices = - [ - new TextGenerationChoice + new List { - FinishReason = "stop", - Message = TextChatMessage.Assistant( - "你上传的两个文件并不相同。第一个文件`test1.txt`包含两行文本,每行都是“测试”。而第二个文件`test2.txt`只有一行文本,“测试2”。尽管它们都含有“测试”这个词,但具体内容和结构不同。") + new TextGenerationChoice + { + FinishReason = "stop", + Message = TextChatMessage.Assistant( + "你上传的两个文件并不相同。第一个文件`test1.txt`包含两行文本,每行都是“测试”。而第二个文件`test2.txt`只有一行文本,“测试2”。尽管它们都含有“测试”这个词,但具体内容和结构不同。") + } } - ] }, RequestId = "7865ae43-8379-9c79-bef6-95050868bc52", Usage = new TextGenerationTokenUsage diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs similarity index 89% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs index ab61622..6bfb059 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs @@ -1,6 +1,6 @@ using Cnblogs.DashScope.Core; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static partial class Snapshots { @@ -12,13 +12,29 @@ public static readonly "tokenization", new ModelRequest { - Input = new TextGenerationInput { Messages = [TextChatMessage.User("代码改变世界")] }, + Input = new TextGenerationInput + { + Messages = + new List { TextChatMessage.User("代码改变世界") }.AsReadOnly() + }, Model = "qwen-max", Parameters = new TextGenerationParameters { Seed = 1234 } }, new ModelResponse { - Output = new TokenizationOutput([46100, 101933, 99489], ["代码", "改变", "世界"]), + Output = new TokenizationOutput( + new List + { + 46100, + 101933, + 99489 + }, + new List + { + "代码", + "改变", + "世界" + }), Usage = new TokenizationUsage(3), RequestId = "6615ba01-081d-9147-93ff-7bd26f3adf93" }); @@ -134,7 +150,8 @@ public static class File new DashScopeFileList( "list", false, - [ + new List + { new DashScopeFile( "file-fe-qBKjZKfTx64R9oYmwyovNHBH", "file", @@ -149,7 +166,7 @@ public static class File 1720535665, "test1.txt", "file-extract") - ])); + })); public static readonly RequestSnapshot DeleteFileNoSse = new( "delete-file", diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Sut.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Sut.cs similarity index 94% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Sut.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/Sut.cs index b6f1755..cb42ce2 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Sut.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Sut.cs @@ -2,7 +2,7 @@ using NSubstitute; using NSubstitute.Extensions; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public static class Sut { diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/TestApplicationBizParam.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/TestApplicationBizParam.cs similarity index 75% rename from test/Cnblogs.DashScope.Sdk.UnitTests/Utils/TestApplicationBizParam.cs rename to test/Cnblogs.DashScope.Tests.Shared/Utils/TestApplicationBizParam.cs index a1274f4..66c6a27 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Utils/TestApplicationBizParam.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/TestApplicationBizParam.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace Cnblogs.DashScope.Sdk.UnitTests.Utils; +namespace Cnblogs.DashScope.Tests.Shared.Utils; public record TestApplicationBizParam( [property: JsonPropertyName("sourceCode")] From 71b80795da5de2fe41ad7cf58bd3340239d0ae83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:13:12 +0800 Subject: [PATCH 26/35] chore: remove invalid access key id --- ...generation-success-nosse.response.body.txt | 2 +- ...generation-success-nosse.response.body.txt | 2 +- ...-synthesis-success-nosse.response.body.txt | 2 +- .../Utils/Snapshots.Application.cs | 50 ++++++------- .../Utils/Snapshots.MultimodalGeneration.cs | 20 +++--- .../Utils/Snapshots.Tasks.cs | 72 +++++++++---------- .../Utils/Snapshots.TextEmbedding.cs | 4 +- .../Utils/Snapshots.TextGeneration.cs | 30 ++++---- .../Utils/Snapshots.cs | 6 +- 9 files changed, 94 insertions(+), 94 deletions(-) diff --git a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.body.txt index 75aba2c..98e695b 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.body.txt +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-background-generation-success-nosse.response.body.txt @@ -1 +1 @@ -{"request_id":"8b22164d-c784-9a31-bda3-3c26259d4213","output":{"task_id":"b2e98d78-c79b-431c-b2d7-c7bcd54465da","task_status":"SUCCEEDED","submit_time":"2024-03-04 10:08:57.333","scheduled_time":"2024-03-04 10:08:57.363","end_time":"2024-03-04 10:09:07.727","text_results":{"urls":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_0_4645005c-713d-4e92-9629-b12cbe5f3671.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=kmZGXc2s8P4uI%2BVrADITyrPz82U%3D"},{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_1_b1979b75-c553-4d9b-9c9f-80f401a0d124.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=cb1Qg%2FkIuZyI7XQqWHjP712N0ak%3D"}],"params":[{"sample_idx":0,"layers":[{"color":"#521b08","top":0,"left":0,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#521b0800"},{"offset":1,"color":"#521b08ff"}],"gradient_units":"pixels","coords":{"y1":257,"x1":0,"y2":0,"x2":0}},"width":1024,"type":"text_mask","idx":0,"opacity":0.8,"radius":0,"height":257},{"font_weight":"Regular","font_size":67,"type":"text","content":"分享好时光","font_under_line":false,"line_height":1,"font_italic":false,"top":25,"sub_type":"Title","font_color":"#e6baa7","left":319,"text_stroke":"1px #fffffff0","width":385,"text_shadow":"1px 0px #80808080","font_family":"站酷文艺体","idx":1,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":77},{"color":"#e6baa7","top":118,"left":395,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#e6baa7ff"},{"offset":1,"color":"#e6baa7ff"}],"gradient_units":"pixels","coords":{"y1":0,"x1":0,"y2":50,"x2":0}},"width":233,"type":"text_mask","idx":2,"opacity":1,"radius":37,"box_shadow":"2px 1px #80808080","height":50},{"font_weight":"Medium","font_size":27,"type":"text","content":"只为不一样的你","font_under_line":false,"line_height":1,"font_italic":false,"top":118,"sub_type":"SubTitle","font_color":"#223629","left":395,"width":233,"text_shadow":0,"font_family":"阿里巴巴普惠体","idx":3,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":50}]},{"sample_idx":1,"layers":[{"color":"#efeae4","top":0,"left":0,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#efeae400"},{"offset":1,"color":"#efeae4ff"}],"gradient_units":"pixels","coords":{"y1":257,"x1":0,"y2":0,"x2":0}},"width":1024,"type":"text_mask","idx":0,"opacity":0.8,"radius":0,"height":257},{"font_weight":"Regular","font_size":67,"type":"text","content":"分享好时光","font_under_line":false,"line_height":1,"font_italic":false,"top":25,"sub_type":"Title","font_color":"#421f12","left":319,"text_stroke":"1px #fffffff0","width":385,"text_shadow":"0px 2px #80808080","font_family":"钉钉进步体","idx":1,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":77},{"color":"#421f12","top":118,"left":395,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#421f12ff"},{"offset":1,"color":"#421f12ff"}],"gradient_units":"pixels","coords":{"y1":0,"x1":0,"y2":50,"x2":0}},"width":233,"type":"text_mask","idx":2,"opacity":1,"radius":37,"box_shadow":"0px 0px #80808080","height":50},{"font_weight":"Regular","font_size":27,"type":"text","content":"只为不一样的你","font_under_line":false,"line_height":1,"font_italic":false,"top":118,"sub_type":"SubTitle","font_color":"#f1eeec","left":395,"width":233,"text_shadow":0,"font_family":"阿里巴巴普惠体","idx":3,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":50}]}]},"results":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_0_02dc0bba-8b1d-4648-8b95-eb2b92fe715d.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=OYstgSxWOl%2FOxYTLa2Mx3bi2RWw%3D"},{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_1_e1af86ec-152a-4ebe-b2a0-b40a592043b2.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=p0UXTUdXfp0tFlt0K5tDsA%2Fxl1M%3D"}],"task_metrics":{"TOTAL":2,"SUCCEEDED":2,"FAILED":0}},"usage":{"image_count":2}} +{"request_id":"8b22164d-c784-9a31-bda3-3c26259d4213","output":{"task_id":"b2e98d78-c79b-431c-b2d7-c7bcd54465da","task_status":"SUCCEEDED","submit_time":"2024-03-04 10:08:57.333","scheduled_time":"2024-03-04 10:08:57.363","end_time":"2024-03-04 10:09:07.727","text_results":{"urls":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_0_4645005c-713d-4e92-9629-b12cbe5f3671.png"},{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_1_b1979b75-c553-4d9b-9c9f-80f401a0d124.png"}],"params":[{"sample_idx":0,"layers":[{"color":"#521b08","top":0,"left":0,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#521b0800"},{"offset":1,"color":"#521b08ff"}],"gradient_units":"pixels","coords":{"y1":257,"x1":0,"y2":0,"x2":0}},"width":1024,"type":"text_mask","idx":0,"opacity":0.8,"radius":0,"height":257},{"font_weight":"Regular","font_size":67,"type":"text","content":"分享好时光","font_under_line":false,"line_height":1,"font_italic":false,"top":25,"sub_type":"Title","font_color":"#e6baa7","left":319,"text_stroke":"1px #fffffff0","width":385,"text_shadow":"1px 0px #80808080","font_family":"站酷文艺体","idx":1,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":77},{"color":"#e6baa7","top":118,"left":395,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#e6baa7ff"},{"offset":1,"color":"#e6baa7ff"}],"gradient_units":"pixels","coords":{"y1":0,"x1":0,"y2":50,"x2":0}},"width":233,"type":"text_mask","idx":2,"opacity":1,"radius":37,"box_shadow":"2px 1px #80808080","height":50},{"font_weight":"Medium","font_size":27,"type":"text","content":"只为不一样的你","font_under_line":false,"line_height":1,"font_italic":false,"top":118,"sub_type":"SubTitle","font_color":"#223629","left":395,"width":233,"text_shadow":0,"font_family":"阿里巴巴普惠体","idx":3,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":50}]},{"sample_idx":1,"layers":[{"color":"#efeae4","top":0,"left":0,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#efeae400"},{"offset":1,"color":"#efeae4ff"}],"gradient_units":"pixels","coords":{"y1":257,"x1":0,"y2":0,"x2":0}},"width":1024,"type":"text_mask","idx":0,"opacity":0.8,"radius":0,"height":257},{"font_weight":"Regular","font_size":67,"type":"text","content":"分享好时光","font_under_line":false,"line_height":1,"font_italic":false,"top":25,"sub_type":"Title","font_color":"#421f12","left":319,"text_stroke":"1px #fffffff0","width":385,"text_shadow":"0px 2px #80808080","font_family":"钉钉进步体","idx":1,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":77},{"color":"#421f12","top":118,"left":395,"gradient":{"type":"linear","color_stops":[{"offset":0,"color":"#421f12ff"},{"offset":1,"color":"#421f12ff"}],"gradient_units":"pixels","coords":{"y1":0,"x1":0,"y2":50,"x2":0}},"width":233,"type":"text_mask","idx":2,"opacity":1,"radius":37,"box_shadow":"0px 0px #80808080","height":50},{"font_weight":"Regular","font_size":27,"type":"text","content":"只为不一样的你","font_under_line":false,"line_height":1,"font_italic":false,"top":118,"sub_type":"SubTitle","font_color":"#f1eeec","left":395,"width":233,"text_shadow":0,"font_family":"阿里巴巴普惠体","idx":3,"alignment":"center","opacity":1,"font_line_through":false,"direction":"horizontal","height":50}]}]},"results":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_0_02dc0bba-8b1d-4648-8b95-eb2b92fe715d.png"},{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_1_e1af86ec-152a-4ebe-b2a0-b40a592043b2.png"}],"task_metrics":{"TOTAL":2,"SUCCEEDED":2,"FAILED":0}},"usage":{"image_count":2}} diff --git a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.body.txt index 1cbff88..55681d4 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.body.txt +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-generation-success-nosse.response.body.txt @@ -1 +1 @@ -{"request_id":"f927c766-5079-90f8-9354-6a87d2167897","output":{"task_id":"c4f94e00-5899-431b-9579-eb1ebe686379","task_status":"SUCCEEDED","submit_time":"2024-03-02 22:22:13.026","scheduled_time":"2024-03-02 22:22:13.051","end_time":"2024-03-02 22:22:21","error_message":"Success","start_time":"2024-03-02 22:22:13","style_index":3,"error_code":0,"results":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-03-02/ac5d435a-9ea9-4287-8666-e1be7bbba943/20240302222213528791_style3_jxdf6o4zwy.jpg?Expires=1709475741&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=LM26fy1Pk8rCfPzihzpUqa3Vst8%3D"}]},"usage":{"image_count":1}} +{"request_id":"f927c766-5079-90f8-9354-6a87d2167897","output":{"task_id":"c4f94e00-5899-431b-9579-eb1ebe686379","task_status":"SUCCEEDED","submit_time":"2024-03-02 22:22:13.026","scheduled_time":"2024-03-02 22:22:13.051","end_time":"2024-03-02 22:22:21","error_message":"Success","start_time":"2024-03-02 22:22:13","style_index":3,"error_code":0,"results":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-03-02/ac5d435a-9ea9-4287-8666-e1be7bbba943/20240302222213528791_style3_jxdf6o4zwy.jpg"}]},"usage":{"image_count":1}} diff --git a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt index 43c0bb2..f9ffba2 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/get-task-image-synthesis-success-nosse.response.body.txt @@ -1 +1 @@ -{"request_id":"6662e925-4846-9afe-a3af-0d131805d378","output":{"task_id":"9e2b6ef6-285d-4efa-8651-4dbda7d571fa","task_status":"SUCCEEDED","submit_time":"2024-03-01 17:38:24.817","scheduled_time":"2024-03-01 17:38:24.831","end_time":"2024-03-01 17:38:55.565","results":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/1d/d4/20240301/8d820c8d/4c48fa53-2907-499b-b9ac-76477fe8d299-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=bEfLmd%2BarXgZyhxcVYOWs%2BovJb8%3D"},{"url":"https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=fdPScmRkIXyH3TSaSaWwvVjxREQ%3D"},{"url":"https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/0f/20240301/3ab595ad/ecfe06b3-b91c-4950-a932-49ea1619a1f9-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=gNuVAt8iy4X8Nl2l3K4Gu4f0ydw%3D"},{"url":"https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/3d/20240301/3ab595ad/3fca748e-d491-458a-bb72-73649af33209-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=Mx5TueC9I9yfDno9rjzi48opHtM%3D"}],"task_metrics":{"TOTAL":4,"SUCCEEDED":4,"FAILED":0}},"usage":{"image_count":4}} +{"request_id":"6662e925-4846-9afe-a3af-0d131805d378","output":{"task_id":"9e2b6ef6-285d-4efa-8651-4dbda7d571fa","task_status":"SUCCEEDED","submit_time":"2024-03-01 17:38:24.817","scheduled_time":"2024-03-01 17:38:24.831","end_time":"2024-03-01 17:38:55.565","results":[{"url":"https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/1d/d4/20240301/8d820c8d/4c48fa53-2907-499b-b9ac-76477fe8d299-1.png"},{"url":"https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png"},{"url":"https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png"},{"url":"https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/3d/20240301/3ab595ad/3fca748e-d491-458a-bb72-73649af33209-1.png"}],"task_metrics":{"TOTAL":4,"SUCCEEDED":4,"FAILED":0}},"usage":{"image_count":4}} diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Application.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Application.cs index 18cd978..fc467e9 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Application.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Application.cs @@ -33,7 +33,7 @@ public static class Application "b7250cba47db463ca851dfb4088e71d8", new List { - new ApplicationOutputThought( + new( null, "agentRag", "知识检索", @@ -43,7 +43,7 @@ public static class Application "[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=89B%2FoauA6i4g34LikZ06Z0PUHY4%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]", null, "{}"), - new ApplicationOutputThought( + new( null, "api", "长期记忆检索", @@ -56,7 +56,7 @@ public static class Application }, new List { - new ApplicationDocReference( + new( "1", "Visual Summary of the Pattern Language", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -68,7 +68,7 @@ public static class Application "http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742655907&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=3VwzeegSrkzfQIcMDz2F3C2bTdg%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302" }, null), - new ApplicationDocReference( + new( "2", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -76,7 +76,7 @@ public static class Application "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", new List(), null), - new ApplicationDocReference( + new( "3", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -84,7 +84,7 @@ public static class Application "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", new List(), null), - new ApplicationDocReference( + new( "4", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -92,7 +92,7 @@ public static class Application "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", new List(), null), - new ApplicationDocReference( + new( "5", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -102,7 +102,7 @@ public static class Application null) }), new ApplicationUsage( - new List { new ApplicationModelUsage("qwen-plus", 2591, 290) }))); + new List { new("qwen-plus", 2591, 290) }))); public static readonly RequestSnapshot SinglePromptSse = new( @@ -134,7 +134,7 @@ public static class Application null, new List { - new ApplicationDocReference( + new( "2", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -142,7 +142,7 @@ public static class Application "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\n", new List(), null), - new ApplicationDocReference( + new( "3", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -150,7 +150,7 @@ public static class Application "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\n", new List(), null), - new ApplicationDocReference( + new( "4", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -158,7 +158,7 @@ public static class Application "【文档名】:xUnit Test Patterns\n【标题】:xUnit Test Patterns\n文档类型:[\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\",\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\"]\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\n", new List(), null), - new ApplicationDocReference( + new( "5", "xUnit Test Patterns", "file_d129d632800c45aa9e7421b30561f447_10207234", @@ -168,7 +168,7 @@ public static class Application null), }), new ApplicationUsage( - new List { new ApplicationModelUsage("qwen-max-latest", 2304, 244) }))); + new List { new("qwen-max-latest", 2304, 244) }))); public static readonly RequestSnapshot SinglePromptWithThoughtsNoSse = new( @@ -198,7 +198,7 @@ public static class Application "9d81b84e95f844c29ee825ad8bb647bb", new List { - new ApplicationOutputThought( + new( null, "agentRag", "知识检索", @@ -208,7 +208,7 @@ public static class Application "[{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:Visual Summary of the Pattern Language\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Minimize Untestable Code Buggy Tests Production Bugs Keep Test Logic Out of Production Developers Not Writing Tests Ensure Commensurate Effort and Responsibility High Test Maintenance CostKey to Visual Summary of the Pattern Language Chapter Name Chapter Name Sub-Category, Altemative Pattern Smell Pattern 1Pattern 2from Other Chapter'Cause of Smell Sub-Category variation, of Altemative Pattem十Pattem 1Smell Variation of Pattern used with Pattern leads toi Smell Variation described each other Alternative Pattem 2separatelyVISUAL SUMMARY OF THE PATTERN LANGUAGE\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_1_3\",\"images\":[\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742716762&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=4CddPVeeyxgrXe5axUspV6zXnS8%3D&x-oss-process=image%2Fcrop%2Cx_232%2Cy_610%2Cw_964%2Ch_648\",\"http://docmind-api-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/1257896666798445/publicDocStructure/docmind-20250315-ee118d3555104aba9200f6cf525bae0a/19.png?Expires=1742716762&OSSAccessKeyId=LTAI5tFEK2uEApeeYzxNMEci&Signature=hRkFcnwAiV7LSHw69WvJJ6fXEV0%3D&x-oss-process=image%2Fcrop%2Cx_227%2Cy_1305%2Cw_991%2Ch_302\"],\"referenceIndex\":1,\"score\":0.5756075978279114,\"title\":\"Visual Summary of the Pattern Language\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Managing Shared Fixtures...103Accessing Shared Fixtures...103Triggering Shared Fixture Construction...104What's Next?...106Chapter 10. Result Verification...107About This Chapter ...107Making Tests Self-Checking...107Verify State or Behavior?...108State Verification...109Using Built-in Assertions ...110Delta Assertions...111External Result Verification ...111Verifying Behavior...112Procedural Behavior Verification...113Expected Behavior Specification . . ...113CONTENTSReducing Test Code Duplication...114Expected Objects...115Custom Assertions...116Outcome-Describing Verification Method ...117\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_33\",\"images\":[],\"referenceIndex\":2,\"score\":0.5756075978279114,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?...168Issues with Databases...168Testing without Databases...169Testing the Database...171Testing Stored Procedures...172Testing the Data Access Layer...172Ensuring Developer Independence...173Testing with Databases (Again!)...173What's Next? ...174Chapter 14. A Roadmap to Effective Test Automation ...175About This Chapter...175Test Automation Difficulty .. ...175Roadmap to Highly Maintainable Automated Tests...176Exercise the Happy Path Code ...177Verify Direct Outputs of the Happy Path...178CONTENTSVerify Alternative Paths...178Verify Indirect Output Behavior...179\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_37\",\"images\":[],\"referenceIndex\":3,\"score\":0.5697553753852844,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:?..17viiiCONTENTSChapter 3. Goals of Test Automation ...19About This Chapter...19Why Test?...19Economics of Test Automation20Goals of Test Automation...21Tests Should Help Us Improve Quality...22Tests Should Help Us Understand the SUT. . ...23Tests Should Reduce (and Not Introduce) Risk...23Tests Should Be Easy to Run ...25Tests Should Be Easy to Write and Maintain ...27Tests Should Require Minimal Maintenance asthe System Evolves Around Them ...29What's Next? .29Chapter 4. Philosophy of Test Automation ...31About This Chapter...31Why Is Philosophy Important?...31\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_28\",\"images\":[],\"referenceIndex\":4,\"score\":0.5639580488204956,\"title\":\"xUnit Test Patterns\",\"webSearch\":false},{\"content\":\"【文档名】:xUnit Test Patterns\\n【标题】:xUnit Test Patterns\\n文档类型:[\\\"xUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\",\\\"XUNIT TEST Yoog PATTERNS REFACTORING TEST CODE GERARD)1MESZAROS\\\"]\\n【正文】:Testcase Class per Class... ...155Testcase Class per Feature. ...156Testcase Class per Fixture...156Choosing a Test Method Organization Strategy...158Test Naming Conventions...158Organizing Test Suites.. . ...160Running Groups of Tests ...160Running a Single Test...161Test Code Reuse...162Test Utility Method Locations ...163TestCase Inheritance and Reuse...163Test File Organization...164Built-in Self-Test...164Test Packages. ...164Test Dependencies ...165What's Next? ...165Chapter 13. Testing with Databases...167About This Chapter...167Testing with Databases...167Why Test with Databases?...168\\n\",\"dataId\":\"file_d129d632800c45aa9e7421b30561f447_10207234\",\"dataName\":\"xUnit Test Patterns\",\"display\":true,\"id\":\"llm-lposod7dkhzvfgmy_thie5bysoj_file_d129d632800c45aa9e7421b30561f447_10207234_0_36\",\"images\":[],\"referenceIndex\":5,\"score\":0.563438355922699,\"title\":\"xUnit Test Patterns\",\"webSearch\":false}]", null, "{}"), - new ApplicationOutputThought( + new( "好的,我现在需要总结用户提供的xUnit Test Patterns中的内容。首先,用户给了几个文档片段,每个片段都来自同一本书的不同部分。我需要仔细分析这些片段,看看里面提到的关键点和主题。\n\n第一个文档提到了“Visual Summary of the Pattern Language”,里面有几个关键点,比如Minimize Untestable Code,Buggy Tests,Production Bugs,还有测试维护成本高的问题。可能这本书在讲如何设计和管理单元测试的模式,避免常见的问题,比如不可测试的代码和测试逻辑混入生产环境。\n\n第二个文档片段讲的是“Managing Shared Fixtures”和结果验证(Result Verification)。这里提到共享夹具的管理、触发构建,以及如何验证测试结果,包括状态验证和行为验证,还有减少测试代码重复的方法,比如使用Expected Objects和Custom Assertions。这说明书中详细讨论了测试夹具的设计和如何有效验证测试结果,避免重复代码。\n\n第三个文档涉及数据库测试的问题,比如如何测试数据访问层、存储过程,以及确保开发者独立性的策略。这部分可能讨论在测试中使用数据库的挑战和解决方案,例如是否使用数据库进行测试,或者如何隔离测试以避免依赖。\n\n第四个文档提到了测试自动化的目标和哲学,包括测试的经济性、提高质量、理解系统、降低风险、易于运行和维护等。这说明书中不仅提供技术模式,还强调测试策略和哲学的重要性,指导如何有效实施自动化测试。\n\n第五个文档讨论了测试用例的组织策略,比如按类、功能或夹具组织测试用例类,命名约定,测试套件的管理,以及测试代码的重用方法。这部分可能涉及如何结构化测试代码,提高可维护性和可读性。\n\n综合这些片段,xUnit Test Patterns似乎是一本关于单元测试设计和最佳实践的指南,涵盖测试模式、夹具管理、结果验证、数据库测试、测试自动化策略和测试代码组织。重点在于如何编写可维护、可靠且高效的测试,避免常见陷阱,如不可测试的代码、测试逻辑污染生产代码、高维护成本等。书中可能还讨论了如何在不同情境下选择适当的测试策略,例如是否使用共享夹具,如何处理数据库依赖,以及如何组织测试代码结构以提高复用性。\n\n现在需要将这些分析整理成一个简明扼要的总结,突出主要主题和关键点,确保涵盖各个文档片段提到的内容,并指出这本书的整体目的和结构。可能需要分点说明,让用户清晰了解书中的核心内容。", "reasoning", "思考过程", @@ -221,7 +221,7 @@ public static class Application }, null), new ApplicationUsage( - new List { new ApplicationModelUsage("deepseek-r1", 1129, 1126) }))); + new List { new("deepseek-r1", 1129, 1126) }))); public static readonly RequestSnapshot SinglePromptWithMemoryNoSse = new( @@ -249,8 +249,8 @@ public static class Application "cd395cb8d4604db786a14555fdcffa1a", new List { - new ApplicationOutputThought(null, "agentRag", "知识检索", "rag", "{}", null, "[]", null, "{}"), - new ApplicationOutputThought( + new(null, "agentRag", "知识检索", "rag", "{}", null, "[]", null, "{}"), + new( null, "api", "长期记忆检索", @@ -263,7 +263,7 @@ public static class Application }, null), new ApplicationUsage( - new List { new ApplicationModelUsage("qwen-plus", 1201, 43) }))); + new List { new("qwen-plus", 1201, 43) }))); public static readonly RequestSnapshot, ApplicationResponse> WorkflowNoSse = @@ -344,7 +344,7 @@ public static readonly RequestSnapshot { - new ApplicationOutputThought( + new( null, "agentRag", "知识检索", @@ -354,7 +354,7 @@ public static readonly RequestSnapshot { new ApplicationModelUsage("deepseek-r1", 1283, 1081) }))); + new List { new("deepseek-r1", 1283, 1081) }))); public static readonly RequestSnapshot ConversationMessageNoSse = new( @@ -407,7 +407,7 @@ public static readonly RequestSnapshot { - new ApplicationOutputThought( + new( null, "agentRag", "知识检索", @@ -417,7 +417,7 @@ public static readonly RequestSnapshot { new ApplicationModelUsage("qwen-plus", 344, 311) }))); + new List { new("qwen-plus", 344, 311) }))); } } diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs index 9c6c3b3..f413959 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.MultimodalGeneration.cs @@ -50,7 +50,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List { MultimodalMessageContent.TextContent("海滩。") } @@ -102,7 +102,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List { MultimodalMessageContent.TextContent("海滩。") } @@ -156,7 +156,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List @@ -208,7 +208,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List @@ -263,7 +263,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List @@ -318,7 +318,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List @@ -374,7 +374,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List @@ -431,7 +431,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List @@ -488,7 +488,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List @@ -547,7 +547,7 @@ public static class MultimodalGeneration Output = new MultimodalOutput( new List { - new MultimodalChoice( + new( "stop", MultimodalMessage.Assistant( new List diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Tasks.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Tasks.cs index e0e20d1..01eb965 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Tasks.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.Tasks.cs @@ -60,14 +60,14 @@ public static readonly RequestSnapshot { - new ImageSynthesisResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/1d/d4/20240301/8d820c8d/4c48fa53-2907-499b-b9ac-76477fe8d299-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=bEfLmd%2BarXgZyhxcVYOWs%2BovJb8%3D"), - new ImageSynthesisResult( - "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=fdPScmRkIXyH3TSaSaWwvVjxREQ%3D"), - new ImageSynthesisResult( - "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/0f/20240301/3ab595ad/ecfe06b3-b91c-4950-a932-49ea1619a1f9-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=gNuVAt8iy4X8Nl2l3K4Gu4f0ydw%3D"), - new ImageSynthesisResult( - "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/3d/20240301/3ab595ad/3fca748e-d491-458a-bb72-73649af33209-1.png?Expires=1709372333&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=Mx5TueC9I9yfDno9rjzi48opHtM%3D") + new( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/1d/d4/20240301/8d820c8d/4c48fa53-2907-499b-b9ac-76477fe8d299-1.png"), + new( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png"), + new( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/79/20240301/3ab595ad/aa3e6d8d-884d-4431-b9c2-3684edeb072e-1.png"), + new( + "https://dashscope-result-sh.oss-cn-shanghai.aliyuncs.com/1d/3d/20240301/3ab595ad/3fca748e-d491-458a-bb72-73649af33209-1.png") }, TaskMetrics = new DashScopeTaskMetrics(4, 4, 0) }, @@ -92,8 +92,8 @@ public static readonly RequestSnapshot { - new ImageGenerationResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-03-02/ac5d435a-9ea9-4287-8666-e1be7bbba943/20240302222213528791_style3_jxdf6o4zwy.jpg?Expires=1709475741&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=LM26fy1Pk8rCfPzihzpUqa3Vst8%3D") + new( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/viapi-video/2024-03-02/ac5d435a-9ea9-4287-8666-e1be7bbba943/20240302222213528791_style3_jxdf6o4zwy.jpg") } }, new ImageGenerationUsage(1))); @@ -113,28 +113,28 @@ public static readonly RequestSnapshot { - new BackgroundGenerationResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_0_02dc0bba-8b1d-4648-8b95-eb2b92fe715d.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=OYstgSxWOl%2FOxYTLa2Mx3bi2RWw%3D"), - new BackgroundGenerationResult( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_1_e1af86ec-152a-4ebe-b2a0-b40a592043b2.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=p0UXTUdXfp0tFlt0K5tDsA%2Fxl1M%3D") + new( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_0_02dc0bba-8b1d-4648-8b95-eb2b92fe715d.png"), + new( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100905_1_e1af86ec-152a-4ebe-b2a0-b40a592043b2.png") }, TaskMetrics = new DashScopeTaskMetrics(2, 2, 0), TextResults = new BackgroundGenerationTextResult( new List { - new BackgroundGenerationTextResultUrl( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_0_4645005c-713d-4e92-9629-b12cbe5f3671.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=kmZGXc2s8P4uI%2BVrADITyrPz82U%3D"), - new BackgroundGenerationTextResultUrl( - "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_1_b1979b75-c553-4d9b-9c9f-80f401a0d124.png?Expires=1709604547&OSSAccessKeyId=LTAI5tQZd8AEcZX6KZV4G8qL&Signature=cb1Qg%2FkIuZyI7XQqWHjP712N0ak%3D") + new( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_0_4645005c-713d-4e92-9629-b12cbe5f3671.png"), + new( + "https://dashscope-result-bj.oss-cn-beijing.aliyuncs.com/466b5214/20240304/100901_1_b1979b75-c553-4d9b-9c9f-80f401a0d124.png") }, new List { - new BackgroundGenerationTextResultParams( + new( 0, new List { - new BackgroundGenerationTextResultLayer( + new( 0, "text_mask", 0, @@ -149,10 +149,10 @@ public static readonly RequestSnapshot { - new BackgroundGenerationTextResultGradientColorStop( + new( "#521b0800", 0), - new BackgroundGenerationTextResultGradientColorStop( + new( "#521b08ff", 1) }) @@ -165,7 +165,7 @@ public static readonly RequestSnapshot { - new BackgroundGenerationTextResultGradientColorStop( + new( "#e6baa7ff", 0), - new BackgroundGenerationTextResultGradientColorStop( + new( "#e6baa7ff", 1) }) @@ -219,7 +219,7 @@ public static readonly RequestSnapshot { - new BackgroundGenerationTextResultLayer( + new( 0, "text_mask", 0, @@ -258,10 +258,10 @@ public static readonly RequestSnapshot { - new BackgroundGenerationTextResultGradientColorStop( + new( "#efeae400", 0), - new BackgroundGenerationTextResultGradientColorStop( + new( "#efeae4ff", 1) }) @@ -276,7 +276,7 @@ public static readonly RequestSnapshot { - new BackgroundGenerationTextResultGradientColorStop( + new( "#421f12ff", 0), - new BackgroundGenerationTextResultGradientColorStop( + new( "#421f12ff", 1) }) @@ -330,7 +330,7 @@ public static readonly RequestSnapshot { - Output = new TextEmbeddingOutput(new List { new TextEmbeddingItem(0, new float[0]) }), + Output = new TextEmbeddingOutput(new List { new(0, new float[0]) }), RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", Usage = new TextEmbeddingTokenUsage(3) }); @@ -33,7 +33,7 @@ public static class TextEmbedding }, new ModelResponse { - Output = new TextEmbeddingOutput(new List { new TextEmbeddingItem(0, new float[0]) }), + Output = new TextEmbeddingOutput(new List { new(0, new float[0]) }), RequestId = "1773f7b2-2148-9f74-b335-b413e398a116", Usage = new TextEmbeddingTokenUsage(3) }); diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs index 2c03649..c53e968 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs @@ -118,7 +118,7 @@ public static class MessageFormat Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( @@ -157,7 +157,7 @@ public static class MessageFormat Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = @@ -208,7 +208,7 @@ public static class MessageFormat Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( @@ -261,7 +261,7 @@ public static class MessageFormat Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant("{\n \"result\": 2\n}") @@ -311,7 +311,7 @@ public static class MessageFormat Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( @@ -350,7 +350,7 @@ public static class MessageFormat Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( @@ -402,7 +402,7 @@ public static class MessageFormat Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( @@ -471,7 +471,7 @@ public static readonly Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( @@ -479,7 +479,7 @@ public static readonly toolCalls: new List { - new ToolCall( + new( "call_cec4c19d27624537b583af", ToolTypes.Function, 0, @@ -525,7 +525,7 @@ public static readonly Tools = new List { - new ToolDefinition( + new( "function", new FunctionDefinition( "get_current_weather", @@ -548,7 +548,7 @@ public static readonly Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( @@ -556,7 +556,7 @@ public static readonly toolCalls: new List { - new ToolCall( + new( "call_cec4c19d27624537b583af", ToolTypes.Function, 0, @@ -612,7 +612,7 @@ public static readonly Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = @@ -668,7 +668,7 @@ public static readonly Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant("您刚才提到的数字是42。") @@ -727,7 +727,7 @@ public static readonly Choices = new List { - new TextGenerationChoice + new() { FinishReason = "stop", Message = TextChatMessage.Assistant( diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs index 6bfb059..fcd442d 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs @@ -135,7 +135,7 @@ public static readonly public static class File { - public static readonly FileInfo TestFile = new FileInfo("RawHttpData/test1.txt"); + public static readonly FileInfo TestFile = new("RawHttpData/test1.txt"); public static readonly RequestSnapshot UploadFileNoSse = new( "upload-file", @@ -152,14 +152,14 @@ public static class File false, new List { - new DashScopeFile( + new( "file-fe-qBKjZKfTx64R9oYmwyovNHBH", "file", 6, 1720582024, "test1.txt", "file-extract"), - new DashScopeFile( + new( "file-fe-WTTG89tIUTd4ByqP3K48R3bn", "file", 6, From da5f2cb16cc99b2c64fe47de9354e654f73dfeb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:15:43 +0800 Subject: [PATCH 27/35] ci: update project route --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd8d6b8..5520755 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,9 +15,9 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Build - run: dotnet build Cnblogs.DashScope.AspNetCore -c Release + run: dotnet build src/Cnblogs.DashScope.AspNetCore -c Release - name: Test - run: dotnet test Cnblogs.Sdk.UnitTests -c Release + run: dotnet test src/Cnblogs.Sdk.UnitTests -c Release test-net8: runs-on: ubuntu-latest container: mcr.microsoft.com/dotnet/sdk:8.0 @@ -25,7 +25,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Build - run: dotnet build Cnblogs.DashScope.AI -c Release + run: dotnet build src/Cnblogs.DashScope.AI -c Release - name: Test - run: dotnet test Cnblogs.DashScope.AI.UnitTests -c Release + run: dotnet test src/Cnblogs.DashScope.AI.UnitTests -c Release From 0879d27cf5036b581c711bceddad13c75c009fec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:16:55 +0800 Subject: [PATCH 28/35] ci: fix typo --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5520755..bbcbce2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - name: Build run: dotnet build src/Cnblogs.DashScope.AspNetCore -c Release - name: Test - run: dotnet test src/Cnblogs.Sdk.UnitTests -c Release + run: dotnet test test/Cnblogs.Sdk.UnitTests -c Release test-net8: runs-on: ubuntu-latest container: mcr.microsoft.com/dotnet/sdk:8.0 @@ -27,5 +27,5 @@ jobs: - name: Build run: dotnet build src/Cnblogs.DashScope.AI -c Release - name: Test - run: dotnet test src/Cnblogs.DashScope.AI.UnitTests -c Release + run: dotnet test test/Cnblogs.DashScope.AI.UnitTests -c Release From 1476be1dcc23e44f80c4a5dd8a3d5e7b217a4010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:17:15 +0800 Subject: [PATCH 29/35] ci: test in net6 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bbcbce2..5901e61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ on: jobs: test-net6: runs-on: ubuntu-latest - container: mcr.microsoft.com/dotnet/sdk:8.0 + container: mcr.microsoft.com/dotnet/sdk:6.0 steps: - name: Checkout From 8f3a5f936832e0d0114e2d580cd18cc3aba535bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:18:32 +0800 Subject: [PATCH 30/35] ci: fix project name --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5901e61..0af6bf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - name: Build run: dotnet build src/Cnblogs.DashScope.AspNetCore -c Release - name: Test - run: dotnet test test/Cnblogs.Sdk.UnitTests -c Release + run: dotnet test test/Cnblogs.DashScope.Sdk.UnitTests -c Release test-net8: runs-on: ubuntu-latest container: mcr.microsoft.com/dotnet/sdk:8.0 From 549770e2f792cb49579d9f493ffe4e0fac50d1d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:21:49 +0800 Subject: [PATCH 31/35] chore: drop target framework for test project --- .../Cnblogs.DashScope.Sdk.UnitTests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj index efc5f63..94a3a5e 100644 --- a/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj +++ b/test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj @@ -1,7 +1,7 @@ - net8.0 + net6.0 false true From 5a6b8212124789281c898c8b7ec37bd1f5979918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Sun, 8 Jun 2025 01:38:40 +0800 Subject: [PATCH 32/35] docs: update README --- README.md | 2 +- README.zh-Hans.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 02f3ff3..590496e 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ public class YourService(IDashScopeClient client) # Examples -Visit [snapshots](./test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs) for calling samples. +Visit [snapshots](./test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs) for calling samples. Visit [tests](./test/Cnblogs.DashScope.Sdk.UnitTests) for more usage of each api. diff --git a/README.zh-Hans.md b/README.zh-Hans.md index f275d76..41346da 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -82,7 +82,7 @@ public class YourService(IDashScopeClient client) # 示例 -查看 [Snapshots.cs](./test/Cnblogs.DashScope.Sdk.UnitTests/Utils/Snapshots.cs) 获得 API 调用参数示例. +查看 [快照文件](./test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.cs) 获得 API 调用参数示例. 查看 [测试](./test) 获得更多 API 使用示例。 From 1b7dd4c814600267201ab3347d84c12a8068d6e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 9 Jun 2025 13:30:06 +0800 Subject: [PATCH 33/35] feat: support reasoning switch for qwen3 models --- .../ITextGenerationParameters.cs | 5 + .../TextGenerationOutputTokenDetails.cs | 7 + .../TextGenerationParameters.cs | 3 + .../TextGenerationPromptTokenDetails.cs | 7 + .../TextGenerationTokenDetails.cs | 7 - .../TextGenerationTokenUsage.cs | 7 +- ...-message-reasoning-nosse.request.body.json | 3 +- ...on-message-reasoning-sse.request.body.json | 6 +- ...on-message-reasoning-sse.response.body.txt | 1681 +---------------- ...-message-reasoning-sse.response.header.txt | 12 +- .../Utils/Snapshots.TextGeneration.cs | 35 +- 11 files changed, 162 insertions(+), 1611 deletions(-) create mode 100644 src/Cnblogs.DashScope.Core/TextGenerationOutputTokenDetails.cs create mode 100644 src/Cnblogs.DashScope.Core/TextGenerationPromptTokenDetails.cs delete mode 100644 src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs diff --git a/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs b/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs index d7774f2..37a3849 100644 --- a/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs +++ b/src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs @@ -40,6 +40,11 @@ public interface ITextGenerationParameters /// public bool? EnableSearch { get; } + /// + /// Thinking option. Valid for supported models.(e.g. qwen3) + /// + public bool? EnableThinking { get; } + /// /// Available tools for model to call. /// diff --git a/src/Cnblogs.DashScope.Core/TextGenerationOutputTokenDetails.cs b/src/Cnblogs.DashScope.Core/TextGenerationOutputTokenDetails.cs new file mode 100644 index 0000000..8e3f49b --- /dev/null +++ b/src/Cnblogs.DashScope.Core/TextGenerationOutputTokenDetails.cs @@ -0,0 +1,7 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Output details for text generation api. +/// +/// Token count of reasoning content. +public record TextGenerationOutputTokenDetails(int ReasoningTokens); diff --git a/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs b/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs index b6a6fe9..49800ed 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs +++ b/src/Cnblogs.DashScope.Core/TextGenerationParameters.cs @@ -38,6 +38,9 @@ public class TextGenerationParameters : ITextGenerationParameters /// public bool? EnableSearch { get; set; } + /// + public bool? EnableThinking { get; set; } + /// public IEnumerable? Tools { get; set; } diff --git a/src/Cnblogs.DashScope.Core/TextGenerationPromptTokenDetails.cs b/src/Cnblogs.DashScope.Core/TextGenerationPromptTokenDetails.cs new file mode 100644 index 0000000..0b4cef6 --- /dev/null +++ b/src/Cnblogs.DashScope.Core/TextGenerationPromptTokenDetails.cs @@ -0,0 +1,7 @@ +namespace Cnblogs.DashScope.Core; + +/// +/// Token usage details. +/// +/// Token count of cached input. +public record TextGenerationPromptTokenDetails(int CachedTokens); diff --git a/src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs b/src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs deleted file mode 100644 index d8e5b18..0000000 --- a/src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Cnblogs.DashScope.Core; - -/// -/// Token usage details. -/// -/// Token count of cached input tokens -public record TextGenerationTokenDetails(int CachedTokens); diff --git a/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs b/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs index 7662d7d..c908e55 100644 --- a/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs +++ b/src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs @@ -14,7 +14,12 @@ public class TextGenerationTokenUsage /// /// Input token details. /// - public TextGenerationTokenDetails? PromptTokensDetails { get; set; } + public TextGenerationPromptTokenDetails? PromptTokensDetails { get; set; } + + /// + /// Output token details. + /// + public TextGenerationOutputTokenDetails? OutputTokensDetails { get; set; } /// /// The number of output token. diff --git a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.body.json index 1d17aaa..079da7b 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.body.json +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-nosse.request.body.json @@ -9,6 +9,7 @@ ] }, "parameters": { - "incremental_output": false + "incremental_output": false, + "result_format": "message" } } diff --git a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.body.json b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.body.json index 9e514e1..cfe607c 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.body.json +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.request.body.json @@ -1,5 +1,5 @@ { - "model": "deepseek-r1", + "model": "qwen-plus-latest", "input": { "messages": [ { @@ -9,6 +9,8 @@ ] }, "parameters": { - "incremental_output": true + "incremental_output": true, + "result_format": "message", + "enable_thinking": true } } diff --git a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.body.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.body.txt index 40e024f..cc433c4 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.body.txt +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.body.txt @@ -1,1975 +1,490 @@ id:1 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"嗯","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":14,"input_tokens":11,"output_tokens":3},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"嗯","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":19,"output_tokens":3,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":1}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:2 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":15,"input_tokens":11,"output_tokens":4},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":20,"output_tokens":4,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":2}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:3 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":16,"input_tokens":11,"output_tokens":5},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":21,"output_tokens":5,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":3}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:4 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":17,"input_tokens":11,"output_tokens":6},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问的是“1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":25,"output_tokens":9,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":7}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:5 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":18,"input_tokens":11,"output_tokens":7},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+1是多少?”","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":29,"output_tokens":13,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":11}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:6 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":19,"input_tokens":11,"output_tokens":8},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这个问题看起来很简单,","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":33,"output_tokens":17,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":15}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:7 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":20,"input_tokens":11,"output_tokens":9},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但可能需要考虑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":37,"output_tokens":21,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":19}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:8 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":21,"input_tokens":11,"output_tokens":10},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不同的上下文。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":41,"output_tokens":25,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":23}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:9 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"多少","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":22,"input_tokens":11,"output_tokens":11},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"首先,在数学中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":45,"output_tokens":29,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":27}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:10 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":23,"input_tokens":11,"output_tokens":12},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",1+1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":49,"output_tokens":33,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":31}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:11 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这个问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":24,"input_tokens":11,"output_tokens":13},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"显然等于2,","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":53,"output_tokens":37,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":35}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:12 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"看起来","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":25,"input_tokens":11,"output_tokens":14},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这是基本的算","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":57,"output_tokens":41,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":39}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:13 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"很简单","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":26,"input_tokens":11,"output_tokens":15},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"术。不过有时候","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":61,"output_tokens":45,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":43}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:14 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":27,"input_tokens":11,"output_tokens":16},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能会有其他解释","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":65,"output_tokens":49,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":47}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:15 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但其实","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":28,"input_tokens":11,"output_tokens":17},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",比如在编程","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":69,"output_tokens":53,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":51}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:16 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":29,"input_tokens":11,"output_tokens":18},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"里,字符串拼","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":73,"output_tokens":57,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":55}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:17 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"有很多","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":30,"input_tokens":11,"output_tokens":19},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"接的话结果可能是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":77,"output_tokens":61,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":59}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:18 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"种","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":31,"input_tokens":11,"output_tokens":20},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"“11”。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":81,"output_tokens":65,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":63}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:19 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":32,"input_tokens":11,"output_tokens":21},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者在某些比喻","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":85,"output_tokens":69,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":67}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:20 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需要考虑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":33,"input_tokens":11,"output_tokens":22},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的情况下,比如两个人","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":89,"output_tokens":73,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":71}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:21 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":34,"input_tokens":11,"output_tokens":23},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"合作,可能会有不同的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":93,"output_tokens":77,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":75}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:22 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"首先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":35,"input_tokens":11,"output_tokens":24},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"解释。不过用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":97,"output_tokens":81,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":79}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:23 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":36,"input_tokens":11,"output_tokens":25},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"没有给出具体的场景","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":101,"output_tokens":85,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":83}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:24 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我得","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":37,"input_tokens":11,"output_tokens":26},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",所以应该默认","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":105,"output_tokens":89,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":87}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:25 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"确定","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":38,"input_tokens":11,"output_tokens":27},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是数学问题。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":109,"output_tokens":93,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":91}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:26 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":39,"input_tokens":11,"output_tokens":28},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"\n\n接下来,我需要","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":113,"output_tokens":97,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":95}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:27 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是不是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":40,"input_tokens":11,"output_tokens":29},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"确认用户的需求。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":117,"output_tokens":101,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":99}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:28 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":41,"input_tokens":11,"output_tokens":30},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能的情况是:","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":121,"output_tokens":105,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":103}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:29 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":42,"input_tokens":11,"output_tokens":31},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"他们真的在问","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":125,"output_tokens":109,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":107}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:30 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":43,"input_tokens":11,"output_tokens":32},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"数学问题,或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":129,"output_tokens":113,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":111}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:31 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"上的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":44,"input_tokens":11,"output_tokens":33},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"测试我的回答是否","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":133,"output_tokens":117,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":115}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:32 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"基本","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":45,"input_tokens":11,"output_tokens":34},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"正确,或者想","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":137,"output_tokens":121,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":119}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:33 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加法","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":46,"input_tokens":11,"output_tokens":35},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"看看我会不会考虑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":141,"output_tokens":125,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":123}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:34 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":47,"input_tokens":11,"output_tokens":36},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他可能性。比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":145,"output_tokens":129,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":127}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:35 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"通常","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":48,"input_tokens":11,"output_tokens":37},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",有些时候人们","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":149,"output_tokens":133,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":131}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:36 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"来说","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":49,"input_tokens":11,"output_tokens":38},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"会开玩笑说1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":153,"output_tokens":137,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":135}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:37 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":50,"input_tokens":11,"output_tokens":39},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+1等于3","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":157,"output_tokens":141,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":139}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:38 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":51,"input_tokens":11,"output_tokens":40},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",指的是家庭组成","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":161,"output_tokens":145,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":143}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:39 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":52,"input_tokens":11,"output_tokens":41},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",但这种情况可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":165,"output_tokens":149,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":147}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:40 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":53,"input_tokens":11,"output_tokens":42},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需要更多上下文","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":169,"output_tokens":153,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":151}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:41 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":54,"input_tokens":11,"output_tokens":43},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。\n\n另外,用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":173,"output_tokens":157,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":155}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:42 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":55,"input_tokens":11,"output_tokens":44},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能有不同的教育背景","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":177,"output_tokens":161,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":159}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:43 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":56,"input_tokens":11,"output_tokens":45},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",比如小孩子刚开始","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":181,"output_tokens":165,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":163}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:44 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":57,"input_tokens":11,"output_tokens":46},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"学数学,可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":185,"output_tokens":169,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":167}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:45 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":58,"input_tokens":11,"output_tokens":47},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需要更详细的解释","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":189,"output_tokens":173,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":171}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:46 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"里的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":59,"input_tokens":11,"output_tokens":48},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",但问题本身","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":193,"output_tokens":177,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":175}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:47 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"基本","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":60,"input_tokens":11,"output_tokens":49},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"太基础,可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":197,"output_tokens":181,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":179}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:48 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"事实","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":61,"input_tokens":11,"output_tokens":50},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不需要深入。或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":201,"output_tokens":185,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":183}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:49 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":62,"input_tokens":11,"output_tokens":51},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户可能是在检查","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":205,"output_tokens":189,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":187}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:50 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"根据","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":63,"input_tokens":11,"output_tokens":52},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我的基本功能是否","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":209,"output_tokens":193,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":191}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:51 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"皮","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":64,"input_tokens":11,"output_tokens":53},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"正常,所以回答","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":213,"output_tokens":197,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":195}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:52 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"亚","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":65,"input_tokens":11,"output_tokens":54},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"要简洁准确。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":217,"output_tokens":201,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":199}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:53 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"诺","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":66,"input_tokens":11,"output_tokens":55},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"\n\n还要考虑是否存在其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":221,"output_tokens":205,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":203}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:54 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"公","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":67,"input_tokens":11,"output_tokens":56},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能的答案,比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":225,"output_tokens":209,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":207}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:55 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"理","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":68,"input_tokens":11,"output_tokens":57},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"在二进制","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":229,"output_tokens":213,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":211}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:56 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":69,"input_tokens":11,"output_tokens":58},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中,1+","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":233,"output_tokens":217,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":215}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:57 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"基本的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":70,"input_tokens":11,"output_tokens":59},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1是10","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":237,"output_tokens":221,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":219}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:58 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"算术","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":71,"input_tokens":11,"output_tokens":60},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",但通常在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":241,"output_tokens":225,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":223}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:59 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"规则","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":72,"input_tokens":11,"output_tokens":61},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"十进制环境下","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":245,"output_tokens":229,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":227}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:60 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":73,"input_tokens":11,"output_tokens":62},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"还是回答2。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":249,"output_tokens":233,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":231}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:61 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":74,"input_tokens":11,"output_tokens":63},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过如果用户有","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":253,"output_tokens":237,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":235}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:62 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":75,"input_tokens":11,"output_tokens":64},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"特定领域的需求,","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":257,"output_tokens":241,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":239}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:63 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"有时候","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":76,"input_tokens":11,"output_tokens":65},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能需要进一步询问","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":261,"output_tokens":245,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":243}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:64 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":77,"input_tokens":11,"output_tokens":66},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。但根据问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":265,"output_tokens":249,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":247}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:65 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能有","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":78,"input_tokens":11,"output_tokens":67},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"本身,没有提示","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":269,"output_tokens":253,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":251}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:66 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"隐藏","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":79,"input_tokens":11,"output_tokens":68},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他进制或","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":273,"output_tokens":257,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":255}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:67 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的含义","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":80,"input_tokens":11,"output_tokens":69},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"特殊情境,所以","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":277,"output_tokens":261,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":259}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:68 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":81,"input_tokens":11,"output_tokens":70},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"应该以常规回答","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":281,"output_tokens":265,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":263}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:69 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"特别是在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":82,"input_tokens":11,"output_tokens":71},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"为主。\n\n总结下来","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":285,"output_tokens":269,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":267}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:70 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不同的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":83,"input_tokens":11,"output_tokens":72},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",最稳妥的回答","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":289,"output_tokens":273,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":271}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:71 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"语境","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":84,"input_tokens":11,"output_tokens":73},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是先给出数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":293,"output_tokens":277,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":275}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:72 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"下","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":85,"input_tokens":11,"output_tokens":74},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"上的答案2,","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":297,"output_tokens":281,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":279}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:73 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":86,"input_tokens":11,"output_tokens":75},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"然后简要提到","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":301,"output_tokens":285,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":283}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:74 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":87,"input_tokens":11,"output_tokens":76},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能的其他情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":305,"output_tokens":289,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":287}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:75 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能会","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":88,"input_tokens":11,"output_tokens":77},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",但说明通常","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":309,"output_tokens":293,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":291}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:76 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不同","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":89,"input_tokens":11,"output_tokens":78},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"默认是指数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":313,"output_tokens":297,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":295}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:77 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":90,"input_tokens":11,"output_tokens":79},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加法。这样","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":317,"output_tokens":301,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":299}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:78 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":91,"input_tokens":11,"output_tokens":80},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"既准确又全面","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":321,"output_tokens":305,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":303}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:79 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":92,"input_tokens":11,"output_tokens":81},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",避免误解。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":325,"output_tokens":309,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":307}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:80 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"二进制","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":93,"input_tokens":11,"output_tokens":82},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"在数学","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":329,"output_tokens":313,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:81 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":94,"input_tokens":11,"output_tokens":83},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"中,**1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":333,"output_tokens":317,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:82 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":95,"input_tokens":11,"output_tokens":84},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":" + 1 =","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":337,"output_tokens":321,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:83 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":96,"input_tokens":11,"output_tokens":85},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":" 2**,","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":341,"output_tokens":325,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:84 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":97,"input_tokens":11,"output_tokens":86},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"这是基本的算","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":345,"output_tokens":329,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:85 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":98,"input_tokens":11,"output_tokens":87},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"术加法运算","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":349,"output_tokens":333,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:86 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":99,"input_tokens":11,"output_tokens":88},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"。 \n如果是在","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":353,"output_tokens":337,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:87 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"10","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":100,"input_tokens":11,"output_tokens":89},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"其他特殊语境","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":357,"output_tokens":341,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:88 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":101,"input_tokens":11,"output_tokens":90},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"下(例如编程","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":361,"output_tokens":345,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:89 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":102,"input_tokens":11,"output_tokens":91},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"中的字符串拼接","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":365,"output_tokens":349,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:90 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"布尔","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":103,"input_tokens":11,"output_tokens":92},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"、二进制","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":369,"output_tokens":353,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:91 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"代数","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":104,"input_tokens":11,"output_tokens":93},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"计算,或比喻","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":373,"output_tokens":357,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:92 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":105,"input_tokens":11,"output_tokens":94},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"性表达),答案","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":377,"output_tokens":361,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:93 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":106,"input_tokens":11,"output_tokens":95},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"可能不同,但","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":381,"output_tokens":365,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:94 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":107,"input_tokens":11,"output_tokens":96},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"通常默认情况下,","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":385,"output_tokens":369,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:95 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":108,"input_tokens":11,"output_tokens":97},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"1+1的结果","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":389,"output_tokens":373,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:96 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":109,"input_tokens":11,"output_tokens":98},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"是**2**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":393,"output_tokens":377,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:97 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":110,"input_tokens":11,"output_tokens":99},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":394,"output_tokens":378,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} id:98 event:result :HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"等于","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":111,"input_tokens":11,"output_tokens":100},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:99 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":112,"input_tokens":11,"output_tokens":101},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:100 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":113,"input_tokens":11,"output_tokens":102},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:101 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"如果是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":114,"input_tokens":11,"output_tokens":103},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:102 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"逻辑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":115,"input_tokens":11,"output_tokens":104},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:103 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":116,"input_tokens":11,"output_tokens":105},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:104 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"运算","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":117,"input_tokens":11,"output_tokens":106},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:105 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的话","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":118,"input_tokens":11,"output_tokens":107},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:106 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":119,"input_tokens":11,"output_tokens":108},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:107 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":120,"input_tokens":11,"output_tokens":109},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:108 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"大部分","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":121,"input_tokens":11,"output_tokens":110},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:109 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况下","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":122,"input_tokens":11,"output_tokens":111},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:110 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":123,"input_tokens":11,"output_tokens":112},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:111 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"尤其是在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":124,"input_tokens":11,"output_tokens":113},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:112 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"日常","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":125,"input_tokens":11,"output_tokens":114},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:113 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"交流","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":126,"input_tokens":11,"output_tokens":115},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:114 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":127,"input_tokens":11,"output_tokens":116},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:115 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":128,"input_tokens":11,"output_tokens":117},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:116 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"人们","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":129,"input_tokens":11,"output_tokens":118},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:117 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"提到","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":130,"input_tokens":11,"output_tokens":119},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:118 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":131,"input_tokens":11,"output_tokens":120},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:119 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"+","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":132,"input_tokens":11,"output_tokens":121},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:120 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":133,"input_tokens":11,"output_tokens":122},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:121 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的时候","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":134,"input_tokens":11,"output_tokens":123},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:122 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"都是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":135,"input_tokens":11,"output_tokens":124},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:123 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"指","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":136,"input_tokens":11,"output_tokens":125},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:124 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"十进制","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":137,"input_tokens":11,"output_tokens":126},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:125 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加法","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":138,"input_tokens":11,"output_tokens":127},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:126 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":139,"input_tokens":11,"output_tokens":128},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:127 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"结果","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":140,"input_tokens":11,"output_tokens":129},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:128 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"自然是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":141,"input_tokens":11,"output_tokens":130},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:129 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":142,"input_tokens":11,"output_tokens":131},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:130 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":143,"input_tokens":11,"output_tokens":132},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:131 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":144,"input_tokens":11,"output_tokens":133},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:132 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"也有可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":145,"input_tokens":11,"output_tokens":134},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:133 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":146,"input_tokens":11,"output_tokens":135},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:134 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":147,"input_tokens":11,"output_tokens":136},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:135 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"测试","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":148,"input_tokens":11,"output_tokens":137},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:136 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":149,"input_tokens":11,"output_tokens":138},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:137 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"反应","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":150,"input_tokens":11,"output_tokens":139},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:138 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":151,"input_tokens":11,"output_tokens":140},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:139 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":152,"input_tokens":11,"output_tokens":141},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:140 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"想","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":153,"input_tokens":11,"output_tokens":142},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:141 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"看看","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":154,"input_tokens":11,"output_tokens":143},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:142 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我会","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":155,"input_tokens":11,"output_tokens":144},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:143 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不会","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":156,"input_tokens":11,"output_tokens":145},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:144 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"考虑","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":157,"input_tokens":11,"output_tokens":146},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:145 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":158,"input_tokens":11,"output_tokens":147},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:146 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能性","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":159,"input_tokens":11,"output_tokens":148},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:147 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":160,"input_tokens":11,"output_tokens":149},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:148 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":161,"input_tokens":11,"output_tokens":150},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:149 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":162,"input_tokens":11,"output_tokens":151},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:150 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"特定的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":163,"input_tokens":11,"output_tokens":152},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:151 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"谜","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":164,"input_tokens":11,"output_tokens":153},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:152 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"语","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":165,"input_tokens":11,"output_tokens":154},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:153 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":166,"input_tokens":11,"output_tokens":155},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:154 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"笑话","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":167,"input_tokens":11,"output_tokens":156},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:155 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"中","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":168,"input_tokens":11,"output_tokens":157},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:156 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":169,"input_tokens":11,"output_tokens":158},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:157 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":170,"input_tokens":11,"output_tokens":159},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:158 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":171,"input_tokens":11,"output_tokens":160},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:159 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":172,"input_tokens":11,"output_tokens":161},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:160 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":173,"input_tokens":11,"output_tokens":162},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:161 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":174,"input_tokens":11,"output_tokens":163},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:162 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比如","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":175,"input_tokens":11,"output_tokens":164},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:163 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"“","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":176,"input_tokens":11,"output_tokens":165},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:164 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":177,"input_tokens":11,"output_tokens":166},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:165 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"滴水","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":178,"input_tokens":11,"output_tokens":167},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:166 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"加","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":179,"input_tokens":11,"output_tokens":168},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:167 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":180,"input_tokens":11,"output_tokens":169},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:168 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"滴水","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":181,"input_tokens":11,"output_tokens":170},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:169 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"还是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":182,"input_tokens":11,"output_tokens":171},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:170 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"1","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":183,"input_tokens":11,"output_tokens":172},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:171 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"滴水","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":184,"input_tokens":11,"output_tokens":173},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:172 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"”,","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":185,"input_tokens":11,"output_tokens":174},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:173 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":186,"input_tokens":11,"output_tokens":175},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:174 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"类似的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":187,"input_tokens":11,"output_tokens":176},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:175 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"文字","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":188,"input_tokens":11,"output_tokens":177},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:176 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"游戏","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":189,"input_tokens":11,"output_tokens":178},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:177 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":190,"input_tokens":11,"output_tokens":179},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:178 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":191,"input_tokens":11,"output_tokens":180},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:179 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"根据","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":192,"input_tokens":11,"output_tokens":181},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:180 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"常规","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":193,"input_tokens":11,"output_tokens":182},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:181 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":194,"input_tokens":11,"output_tokens":183},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:182 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":195,"input_tokens":11,"output_tokens":184},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:183 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"我应该","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":196,"input_tokens":11,"output_tokens":185},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:184 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":197,"input_tokens":11,"output_tokens":186},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:185 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"给出","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":198,"input_tokens":11,"output_tokens":187},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:186 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"正确的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":199,"input_tokens":11,"output_tokens":188},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:187 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"数学","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":200,"input_tokens":11,"output_tokens":189},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:188 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":201,"input_tokens":11,"output_tokens":190},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:189 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":202,"input_tokens":11,"output_tokens":191},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:190 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"再","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":203,"input_tokens":11,"output_tokens":192},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:191 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"补充","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":204,"input_tokens":11,"output_tokens":193},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:192 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":205,"input_tokens":11,"output_tokens":194},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:193 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":206,"input_tokens":11,"output_tokens":195},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:194 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":207,"input_tokens":11,"output_tokens":196},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:195 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":208,"input_tokens":11,"output_tokens":197},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:196 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这样","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":209,"input_tokens":11,"output_tokens":198},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:197 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"既","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":210,"input_tokens":11,"output_tokens":199},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:198 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"准确","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":211,"input_tokens":11,"output_tokens":200},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:199 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"又","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":212,"input_tokens":11,"output_tokens":201},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:200 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"全面","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":213,"input_tokens":11,"output_tokens":202},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:201 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":214,"input_tokens":11,"output_tokens":203},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:202 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"所以","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":215,"input_tokens":11,"output_tokens":204},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:203 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":216,"input_tokens":11,"output_tokens":205},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:204 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":217,"input_tokens":11,"output_tokens":206},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:205 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"回答","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":218,"input_tokens":11,"output_tokens":207},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:206 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":219,"input_tokens":11,"output_tokens":208},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:207 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":220,"input_tokens":11,"output_tokens":209},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:208 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"然后","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":221,"input_tokens":11,"output_tokens":210},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:209 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"解释","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":222,"input_tokens":11,"output_tokens":211},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:210 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":223,"input_tokens":11,"output_tokens":212},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:211 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能性","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":224,"input_tokens":11,"output_tokens":213},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:212 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":225,"input_tokens":11,"output_tokens":214},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:213 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":226,"input_tokens":11,"output_tokens":215},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:214 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":227,"input_tokens":11,"output_tokens":216},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:215 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的问题","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":228,"input_tokens":11,"output_tokens":217},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:216 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"看起来","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":229,"input_tokens":11,"output_tokens":218},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:217 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"直接","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":230,"input_tokens":11,"output_tokens":219},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:218 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":231,"input_tokens":11,"output_tokens":220},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:219 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":232,"input_tokens":11,"output_tokens":221},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:220 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"不需要","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":233,"input_tokens":11,"output_tokens":222},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:221 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"太","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":234,"input_tokens":11,"output_tokens":223},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:222 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"复杂的","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":235,"input_tokens":11,"output_tokens":224},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:223 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"解释","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":236,"input_tokens":11,"output_tokens":225},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:224 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":237,"input_tokens":11,"output_tokens":226},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:225 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":238,"input_tokens":11,"output_tokens":227},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:226 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"为了","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":239,"input_tokens":11,"output_tokens":228},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:227 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"保险","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":240,"input_tokens":11,"output_tokens":229},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:228 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"起见","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":241,"input_tokens":11,"output_tokens":230},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:229 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":242,"input_tokens":11,"output_tokens":231},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:230 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"还是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":243,"input_tokens":11,"output_tokens":232},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:231 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"确认","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":244,"input_tokens":11,"output_tokens":233},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:232 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"一下","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":245,"input_tokens":11,"output_tokens":234},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:233 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"是否有","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":246,"input_tokens":11,"output_tokens":235},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:234 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":247,"input_tokens":11,"output_tokens":236},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:235 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"意图","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":248,"input_tokens":11,"output_tokens":237},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:236 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"比较好","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":249,"input_tokens":11,"output_tokens":238},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:237 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":250,"input_tokens":11,"output_tokens":239},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:238 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"或者","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":251,"input_tokens":11,"output_tokens":240},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:239 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"用户","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":252,"input_tokens":11,"output_tokens":241},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:240 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":253,"input_tokens":11,"output_tokens":242},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:241 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"只是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":254,"input_tokens":11,"output_tokens":243},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:242 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"单纯","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":255,"input_tokens":11,"output_tokens":244},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:243 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"想知道","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":256,"input_tokens":11,"output_tokens":245},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:244 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":257,"input_tokens":11,"output_tokens":246},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:245 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":258,"input_tokens":11,"output_tokens":247},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:246 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"所以","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":259,"input_tokens":11,"output_tokens":248},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:247 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"直接","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":260,"input_tokens":11,"output_tokens":249},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:248 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"回答","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":261,"input_tokens":11,"output_tokens":250},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:249 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":262,"input_tokens":11,"output_tokens":251},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:250 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"即可","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":263,"input_tokens":11,"output_tokens":252},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:251 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":264,"input_tokens":11,"output_tokens":253},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:252 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需要","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":265,"input_tokens":11,"output_tokens":254},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:253 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"平衡","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":266,"input_tokens":11,"output_tokens":255},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:254 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"简洁","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":267,"input_tokens":11,"output_tokens":256},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:255 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"和","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":268,"input_tokens":11,"output_tokens":257},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:256 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"全面","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":269,"input_tokens":11,"output_tokens":258},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:257 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"性","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":270,"input_tokens":11,"output_tokens":259},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:258 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":271,"input_tokens":11,"output_tokens":260},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:259 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"可能","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":272,"input_tokens":11,"output_tokens":261},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:260 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"先","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":273,"input_tokens":11,"output_tokens":262},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:261 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"给出","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":274,"input_tokens":11,"output_tokens":263},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:262 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"直接","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":275,"input_tokens":11,"output_tokens":264},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:263 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":276,"input_tokens":11,"output_tokens":265},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:264 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":277,"input_tokens":11,"output_tokens":266},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:265 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"然后","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":278,"input_tokens":11,"output_tokens":267},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:266 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"简单","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":279,"input_tokens":11,"output_tokens":268},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:267 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"说明","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":280,"input_tokens":11,"output_tokens":269},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:268 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"其他","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":281,"input_tokens":11,"output_tokens":270},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:269 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":282,"input_tokens":11,"output_tokens":271},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:270 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"的存在","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":283,"input_tokens":11,"output_tokens":272},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:271 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":284,"input_tokens":11,"output_tokens":273},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:272 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"这样","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":285,"input_tokens":11,"output_tokens":274},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:273 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"既","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":286,"input_tokens":11,"output_tokens":275},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:274 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"满足","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":287,"input_tokens":11,"output_tokens":276},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:275 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"需求","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":288,"input_tokens":11,"output_tokens":277},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:276 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":289,"input_tokens":11,"output_tokens":278},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:277 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"又","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":290,"input_tokens":11,"output_tokens":279},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:278 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"避免","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":291,"input_tokens":11,"output_tokens":280},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:279 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"信息","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":292,"input_tokens":11,"output_tokens":281},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:280 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"过","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":293,"input_tokens":11,"output_tokens":282},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:281 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"载","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":294,"input_tokens":11,"output_tokens":283},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:282 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":295,"input_tokens":11,"output_tokens":284},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:283 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"总之","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":296,"input_tokens":11,"output_tokens":285},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:284 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":297,"input_tokens":11,"output_tokens":286},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:285 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"核心","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":298,"input_tokens":11,"output_tokens":287},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:286 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"答案","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":299,"input_tokens":11,"output_tokens":288},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:287 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"应该是","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":300,"input_tokens":11,"output_tokens":289},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:288 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"2","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":301,"input_tokens":11,"output_tokens":290},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:289 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":",","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":302,"input_tokens":11,"output_tokens":291},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:290 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"但","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":303,"input_tokens":11,"output_tokens":292},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:291 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"根据","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":304,"input_tokens":11,"output_tokens":293},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:292 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"情况","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":305,"input_tokens":11,"output_tokens":294},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:293 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"适当","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":306,"input_tokens":11,"output_tokens":295},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:294 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"扩展","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":307,"input_tokens":11,"output_tokens":296},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:295 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"。","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":308,"input_tokens":11,"output_tokens":297},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:296 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":311,"input_tokens":11,"output_tokens":300},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:297 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"+","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":312,"input_tokens":11,"output_tokens":301},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:298 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":313,"input_tokens":11,"output_tokens":302},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:299 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" 在","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":315,"input_tokens":11,"output_tokens":304},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:300 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"基础","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":316,"input_tokens":11,"output_tokens":305},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:301 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"算术","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":317,"input_tokens":11,"output_tokens":306},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:302 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"中的","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":318,"input_tokens":11,"output_tokens":307},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:303 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"答案是","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":319,"input_tokens":11,"output_tokens":308},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:304 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":320,"input_tokens":11,"output_tokens":309},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:305 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"2","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":321,"input_tokens":11,"output_tokens":310},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:306 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":322,"input_tokens":11,"output_tokens":311},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:307 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":323,"input_tokens":11,"output_tokens":312},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:308 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"\n\n不过","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":325,"input_tokens":11,"output_tokens":314},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:309 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":",","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":326,"input_tokens":11,"output_tokens":315},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:310 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"根据","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":327,"input_tokens":11,"output_tokens":316},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:311 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"不同的","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":328,"input_tokens":11,"output_tokens":317},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:312 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"数学","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":329,"input_tokens":11,"output_tokens":318},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:313 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"或","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":330,"input_tokens":11,"output_tokens":319},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:314 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"逻辑","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":331,"input_tokens":11,"output_tokens":320},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:315 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"系统","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":332,"input_tokens":11,"output_tokens":321},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:316 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":",","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":333,"input_tokens":11,"output_tokens":322},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:317 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"结果","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":334,"input_tokens":11,"output_tokens":323},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:318 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"可能","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":335,"input_tokens":11,"output_tokens":324},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:319 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"不同","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":336,"input_tokens":11,"output_tokens":325},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:320 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":337,"input_tokens":11,"output_tokens":326},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:321 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"\n-","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":338,"input_tokens":11,"output_tokens":327},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:322 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":339,"input_tokens":11,"output_tokens":328},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:323 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"二进制","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":340,"input_tokens":11,"output_tokens":329},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:324 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":341,"input_tokens":11,"output_tokens":330},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:325 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":342,"input_tokens":11,"output_tokens":331},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:326 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":343,"input_tokens":11,"output_tokens":332},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:327 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"+","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":344,"input_tokens":11,"output_tokens":333},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:328 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":345,"input_tokens":11,"output_tokens":334},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:329 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" =","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":346,"input_tokens":11,"output_tokens":335},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:330 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" 10","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":348,"input_tokens":11,"output_tokens":337},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:331 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"(","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":349,"input_tokens":11,"output_tokens":338},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:332 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"读","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":350,"input_tokens":11,"output_tokens":339},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:333 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"作","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":351,"input_tokens":11,"output_tokens":340},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:334 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"“","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":352,"input_tokens":11,"output_tokens":341},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:335 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"一","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":353,"input_tokens":11,"output_tokens":342},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:336 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"零","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":354,"input_tokens":11,"output_tokens":343},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:337 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"”","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":355,"input_tokens":11,"output_tokens":344},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:338 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":")。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":356,"input_tokens":11,"output_tokens":345},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:339 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"\n-","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":357,"input_tokens":11,"output_tokens":346},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:340 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":358,"input_tokens":11,"output_tokens":347},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:341 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"布尔","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":359,"input_tokens":11,"output_tokens":348},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:342 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"代数","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":360,"input_tokens":11,"output_tokens":349},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:343 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":361,"input_tokens":11,"output_tokens":350},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:344 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":362,"input_tokens":11,"output_tokens":351},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:345 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":363,"input_tokens":11,"output_tokens":352},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:346 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"+","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":364,"input_tokens":11,"output_tokens":353},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:347 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":365,"input_tokens":11,"output_tokens":354},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:348 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" =","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":366,"input_tokens":11,"output_tokens":355},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:349 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" 1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":368,"input_tokens":11,"output_tokens":357},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:350 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"(","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":369,"input_tokens":11,"output_tokens":358},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:351 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"逻辑","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":370,"input_tokens":11,"output_tokens":359},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:352 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"“","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":371,"input_tokens":11,"output_tokens":360},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:353 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"或","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":372,"input_tokens":11,"output_tokens":361},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:354 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"”","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":373,"input_tokens":11,"output_tokens":362},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:355 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"运算","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":374,"input_tokens":11,"output_tokens":363},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:356 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":")。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":375,"input_tokens":11,"output_tokens":364},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:357 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"\n-","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":376,"input_tokens":11,"output_tokens":365},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:358 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":377,"input_tokens":11,"output_tokens":366},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:359 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"抽象","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":378,"input_tokens":11,"output_tokens":367},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:360 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"场景","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":379,"input_tokens":11,"output_tokens":368},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:361 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":380,"input_tokens":11,"output_tokens":369},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:362 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":":","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":381,"input_tokens":11,"output_tokens":370},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:363 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"如","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":382,"input_tokens":11,"output_tokens":371},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:364 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"“","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":383,"input_tokens":11,"output_tokens":372},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:365 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":384,"input_tokens":11,"output_tokens":373},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:366 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"滴水","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":385,"input_tokens":11,"output_tokens":374},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:367 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" +","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":386,"input_tokens":11,"output_tokens":375},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:368 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" 1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":388,"input_tokens":11,"output_tokens":377},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:369 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"滴水","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":389,"input_tokens":11,"output_tokens":378},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:370 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" =","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":390,"input_tokens":11,"output_tokens":379},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:371 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" 1","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":392,"input_tokens":11,"output_tokens":381},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:372 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"大","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":393,"input_tokens":11,"output_tokens":382},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:373 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"滴水","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":394,"input_tokens":11,"output_tokens":383},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:374 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"”(","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":395,"input_tokens":11,"output_tokens":384},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:375 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"非","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":396,"input_tokens":11,"output_tokens":385},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:376 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"数学","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":397,"input_tokens":11,"output_tokens":386},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:377 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"意义的","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":398,"input_tokens":11,"output_tokens":387},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:378 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"合并","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":399,"input_tokens":11,"output_tokens":388},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:379 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":")。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":400,"input_tokens":11,"output_tokens":389},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:380 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"\n\n日常","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":401,"input_tokens":11,"output_tokens":390},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:381 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"问题","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":402,"input_tokens":11,"output_tokens":391},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:382 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"中","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":403,"input_tokens":11,"output_tokens":392},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:383 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"默认","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":404,"input_tokens":11,"output_tokens":393},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:384 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"使用","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":405,"input_tokens":11,"output_tokens":394},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:385 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"十进制","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":406,"input_tokens":11,"output_tokens":395},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:386 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"算术","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":407,"input_tokens":11,"output_tokens":396},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:387 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":",","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":408,"input_tokens":11,"output_tokens":397},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:388 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"因此","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":409,"input_tokens":11,"output_tokens":398},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:389 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"答案是","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":410,"input_tokens":11,"output_tokens":399},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:390 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" **","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":411,"input_tokens":11,"output_tokens":400},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:391 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"2","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":412,"input_tokens":11,"output_tokens":401},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:392 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"**","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":413,"input_tokens":11,"output_tokens":402},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:393 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":" 😊","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":416,"input_tokens":11,"output_tokens":405},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:394 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"。","reasoning_content":"","role":"assistant"},"finish_reason":"null"}]},"usage":{"total_tokens":417,"input_tokens":11,"output_tokens":406},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} - -id:395 -event:result -:HTTP_STATUS/200 -data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"","role":"assistant"},"finish_reason":"stop"}]},"usage":{"total_tokens":417,"input_tokens":11,"output_tokens":406},"request_id":"e4ad5d0f-8019-9716-adc6-eae1411d3c9a"} +data:{"output":{"choices":[{"message":{"content":"","reasoning_content":"","role":"assistant"},"finish_reason":"stop"}]},"usage":{"total_tokens":394,"output_tokens":378,"input_tokens":16,"output_tokens_details":{"reasoning_tokens":306}},"request_id":"d21851a2-675b-97a3-9132-2935c31d6ee3"} diff --git a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.header.txt b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.header.txt index 668bf11..6cec27f 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.header.txt +++ b/test/Cnblogs.DashScope.Tests.Shared/RawHttpData/single-generation-message-reasoning-sse.response.header.txt @@ -1,14 +1,14 @@ HTTP/1.1 200 OK vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers -x-request-id: e4ad5d0f-8019-9716-adc6-eae1411d3c9a +x-request-id: d21851a2-675b-97a3-9132-2935c31d6ee3 content-type: text/event-stream;charset=UTF-8 x-dashscope-call-gateway: true x-dashscope-timeout: 180 x-dashscope-finished: false -req-cost-time: 500 -req-arrive-time: 1742405632039 -resp-start-time: 1742405632540 -x-envoy-upstream-service-time: 490 -date: Wed, 19 Mar 2025 17:33:52 GMT +req-cost-time: 482 +req-arrive-time: 1749445556927 +resp-start-time: 1749445557410 +x-envoy-upstream-service-time: 474 +date: Mon, 09 Jun 2025 05:05:57 GMT server: istio-envoy transfer-encoding: chunked diff --git a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs index c53e968..2bf4461 100644 --- a/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs +++ b/test/Cnblogs.DashScope.Tests.Shared/Utils/Snapshots.TextGeneration.cs @@ -43,7 +43,7 @@ public static class TextFormat InputTokens = 16, OutputTokens = 14, TotalTokens = 30, - PromptTokensDetails = new TextGenerationTokenDetails(0) + PromptTokensDetails = new TextGenerationPromptTokenDetails(0) } }); @@ -148,7 +148,10 @@ public static class MessageFormat Messages = new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() }, - Parameters = new TextGenerationParameters { IncrementalOutput = false } + Parameters = new TextGenerationParameters + { + IncrementalOutput = false, ResultFormat = ResultFormats.Message + } }, new ModelResponse { @@ -163,7 +166,9 @@ public static class MessageFormat Message = TextChatMessage.Assistant( "1 + 1 等于 **2**。这是基础的算术加法,当我们将一个单位与另一个单位相加时,总和为两个单位。", - reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但可能有一些需要注意的地方。首先,我得确认用户是不是真的在问基本的数学问题,还是有其他的意图,比如测试我的反应或者开玩笑。\n\n1加1在基础算术里确实是2,但有时候可能会有不同的解释,比如在二进制中1+1等于10,或者在逻辑学中有时候表示为1,如果是布尔代数的话。不过通常情况下,用户可能只需要最直接的答案,也就是2。\n\n不过也有可能用户想考察我是否能够处理更复杂的情况,或者是否有隐藏的意思。比如,在某些情况下,1加1可能被用来比喻合作的效果,比如“1+1大于2”,但这可能超出了当前问题的范围。\n\n我需要考虑用户的背景。如果用户是小学生,那么直接回答2是正确的,并且可能需要鼓励的话。如果是成年人,可能还是同样的答案,但不需要额外的解释。如果用户来自数学或计算机领域,可能需要确认是否需要其他进制的答案,但通常默认是十进制。\n\n另外,检查是否有拼写错误或非阿拉伯数字的情况,比如罗马数字的I+I,但问题里明确写的是1+1,所以应该是阿拉伯数字。\n\n总结下来,最安全也是最正确的答案就是2。不过为了确保,可以简短地确认用户的意图,但按照常规问题处理,直接回答即可。") + null, + null, + "嗯,用户问1加1等于多少。这个问题看起来很简单,但可能有一些需要注意的地方。首先,我得确认用户是不是真的在问基本的数学问题,还是有其他的意图,比如测试我的反应或者开玩笑。\n\n1加1在基础算术里确实是2,但有时候可能会有不同的解释,比如在二进制中1+1等于10,或者在逻辑学中有时候表示为1,如果是布尔代数的话。不过通常情况下,用户可能只需要最直接的答案,也就是2。\n\n不过也有可能用户想考察我是否能够处理更复杂的情况,或者是否有隐藏的意思。比如,在某些情况下,1加1可能被用来比喻合作的效果,比如“1+1大于2”,但这可能超出了当前问题的范围。\n\n我需要考虑用户的背景。如果用户是小学生,那么直接回答2是正确的,并且可能需要鼓励的话。如果是成年人,可能还是同样的答案,但不需要额外的解释。如果用户来自数学或计算机领域,可能需要确认是否需要其他进制的答案,但通常默认是十进制。\n\n另外,检查是否有拼写错误或非阿拉伯数字的情况,比如罗马数字的I+I,但问题里明确写的是1+1,所以应该是阿拉伯数字。\n\n总结下来,最安全也是最正确的答案就是2。不过为了确保,可以简短地确认用户的意图,但按照常规问题处理,直接回答即可。") } } }, @@ -334,14 +339,19 @@ public static class MessageFormat "single-generation-message-reasoning", new ModelRequest { - Model = "deepseek-r1", + Model = "qwen-plus-latest", Input = new TextGenerationInput { Messages = new List { TextChatMessage.User("请问 1+1 是多少?") }.AsReadOnly() }, - Parameters = new TextGenerationParameters { IncrementalOutput = true } + Parameters = new TextGenerationParameters + { + IncrementalOutput = true, + ResultFormat = ResultFormats.Message, + EnableThinking = true + } }, new ModelResponse { @@ -354,17 +364,20 @@ public static class MessageFormat { FinishReason = "stop", Message = TextChatMessage.Assistant( - "1+1 在基础算术中的答案是 **2**。\n\n不过,根据不同的数学或逻辑系统,结果可能不同:\n- **二进制**:1+1 = 10(读作“一零”)。\n- **布尔代数**:1+1 = 1(逻辑“或”运算)。\n- **抽象场景**:如“1滴水 + 1滴水 = 1大滴水”(非数学意义的合并)。\n\n日常问题中默认使用十进制算术,因此答案是 **2** \ud83d\ude0a。", - reasoningContent: "嗯,用户问1加1等于多少。这个问题看起来很简单,但其实可能有很多种情况需要考虑。首先,我得确定用户是不是在问数学上的基本加法。通常来说,1加1等于2,这是数学里的基本事实,根据皮亚诺公理或者基本的算术规则。不过,有时候问题可能有隐藏的含义,特别是在不同的语境下,答案可能会不同。比如在二进制中,1+1等于10,或者在布尔代数中,1+1可能等于1,如果是逻辑或运算的话。不过大部分情况下,尤其是在日常交流中,人们提到1+1的时候都是指十进制加法,结果自然是2。不过也有可能用户是在测试我的反应,或者想看看我会不会考虑其他可能性。比如在特定的谜语或笑话中,答案可能不是2,比如“1滴水加1滴水还是1滴水”,或者类似的文字游戏。但根据常规问题,我应该先给出正确的数学答案,再补充可能的其他情况,这样既准确又全面。所以可能先回答2,然后解释其他可能性。不过用户的问题看起来直接,可能不需要太复杂的解释,但为了保险起见,还是确认一下是否有其他意图比较好。或者用户可能只是单纯想知道答案,所以直接回答2即可。需要平衡简洁和全面性。可能先给出直接答案,然后简单说明其他情况的存在,这样既满足需求,又避免信息过载。总之,核心答案应该是2,但根据情况适当扩展。") + "在数学中,**1 + 1 = 2**,这是基本的算术加法运算。 \n如果是在其他特殊语境下(例如编程中的字符串拼接、二进制计算,或比喻性表达),答案可能不同,但通常默认情况下,1+1的结果是**2**。", + null, + null, + "嗯,用户问的是“1+1是多少?”这个问题看起来很简单,但可能需要考虑不同的上下文。首先,在数学中,1+1显然等于2,这是基本的算术。不过有时候可能会有其他解释,比如在编程里,字符串拼接的话结果可能是“11”。或者在某些比喻的情况下,比如两个人合作,可能会有不同的解释。不过用户没有给出具体的场景,所以应该默认是数学问题。\n\n接下来,我需要确认用户的需求。可能的情况是:他们真的在问数学问题,或者测试我的回答是否正确,或者想看看我会不会考虑其他可能性。比如,有些时候人们会开玩笑说1+1等于3,指的是家庭组成,但这种情况可能需要更多上下文。\n\n另外,用户可能有不同的教育背景,比如小孩子刚开始学数学,可能需要更详细的解释,但问题本身太基础,可能不需要深入。或者用户可能是在检查我的基本功能是否正常,所以回答要简洁准确。\n\n还要考虑是否存在其他可能的答案,比如在二进制中,1+1是10,但通常在十进制环境下还是回答2。不过如果用户有特定领域的需求,可能需要进一步询问。但根据问题本身,没有提示其他进制或特殊情境,所以应该以常规回答为主。\n\n总结下来,最稳妥的回答是先给出数学上的答案2,然后简要提到可能的其他情况,但说明通常默认是指数学加法。这样既准确又全面,避免误解。") } } }, - RequestId = "e4ad5d0f-8019-9716-adc6-eae1411d3c9a", + RequestId = "d21851a2-675b-97a3-9132-2935c31d6ee3", Usage = new TextGenerationTokenUsage { - TotalTokens = 417, - OutputTokens = 406, - InputTokens = 11 + TotalTokens = 394, + OutputTokens = 378, + InputTokens = 16, + OutputTokensDetails = new TextGenerationOutputTokenDetails(306) } }); From 2bae32e25d2b587e2d8440079c6c1abc3c9ea655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Mon, 9 Jun 2025 13:45:02 +0800 Subject: [PATCH 34/35] doc: update sample and README --- README.md | 45 +++++++++++++++------- README.zh-Hans.md | 19 ++++++++- sample/Cnblogs.DashScope.Sample/Program.cs | 18 ++++++--- 3 files changed, 62 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 590496e..8af1a64 100644 --- a/README.md +++ b/README.md @@ -123,19 +123,6 @@ var completion = await client.GetQWenCompletionAsync(QWenLlm.QWenMax, prompt); Console.WriteLine(completion.Output.Text); ``` -## Reasoning - -Use `completion.Output.Choices![0].Message.ReasoningContent` to access the reasoning content from model. - -```csharp -var history = new List -{ - ChatMessage.User("Calculate 1+1") -}; -var completion = await client.GetDeepSeekChatCompletionAsync(DeepSeekLlm.DeepSeekR1, history); -Console.WriteLine(completion.Output.Choices[0]!.Message.ReasoningContent); -``` - ## Multi-round chat ```csharp @@ -153,6 +140,36 @@ var completion = await client.GetQWenChatCompletionAsync(QWenLlm.QWenMax, histor Console.WriteLine(completion.Output.Choices[0].Message.Content); // The number is 42 ``` +## Reasoning + +Use `completion.Output.Choices![0].Message.ReasoningContent` to access the thoughts from reasoning model. + +```csharp +var history = new List +{ + ChatMessage.User("Calculate 1+1") +}; +var completion = await client.GetDeepSeekChatCompletionAsync(DeepSeekLlm.DeepSeekR1, history); +Console.WriteLine(completion.Output.Choices[0]!.Message.ReasoningContent); +``` + +### QWen3 + +Use `TextGenerationParameters.EnableThinking` to toggle reasoning. + +```csharp +var stream = dashScopeClient + .GetQWenChatStreamAsync( + QWenLlm.QWenPlusLatest, + history, + new TextGenerationParameters + { + IncrementalOutput = true, + ResultFormat = ResultFormats.Message, + EnableThinking = true + }); +``` + ## Function Call Creates a function with parameters @@ -182,7 +199,7 @@ public enum TemperatureUnit } ``` -Append tool information to chat messages. +Append tool information to chat messages (Here we use `JsonSchema.NET` to generate JSON Schema). ```csharp var tools = new List() diff --git a/README.zh-Hans.md b/README.zh-Hans.md index 41346da..b2545c3 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -157,6 +157,23 @@ var completion = await client.GetDeepSeekChatCompletionAsync(DeepSeekLlm.DeepSee Console.WriteLine(completion.Output.Choices[0]!.Message.ReasoningContent); ``` +### QWen3 + +使用 `TextGenerationParameters.EnableThinking` 决定是否使用模型的推理能力。 + +```csharp +var stream = dashScopeClient + .GetQWenChatStreamAsync( + QWenLlm.QWenPlusLatest, + history, + new TextGenerationParameters + { + IncrementalOutput = true, + ResultFormat = ResultFormats.Message, + EnableThinking = true + }); +``` + ## 工具调用 创建一个可供模型使用的方法。 @@ -182,7 +199,7 @@ public enum TemperatureUnit } ``` -对话时带上方法的名称、描述和参数列表,参数列表以 JSON Schema 的形式提供。 +对话时带上方法的名称、描述和参数列表,参数列表以 JSON Schema 的形式提供(这里使用 `JsonSchema.Net` 库,您也可以使用其它具有类似功能的库)。 ```csharp var tools = new List() diff --git a/sample/Cnblogs.DashScope.Sample/Program.cs b/sample/Cnblogs.DashScope.Sample/Program.cs index d003cd3..87bfe69 100644 --- a/sample/Cnblogs.DashScope.Sample/Program.cs +++ b/sample/Cnblogs.DashScope.Sample/Program.cs @@ -32,12 +32,12 @@ switch (type) { case SampleType.TextCompletion: - Console.WriteLine("Prompt > "); + Console.Write("Prompt > "); userInput = Console.ReadLine()!; await TextCompletionAsync(userInput); break; case SampleType.TextCompletionSse: - Console.WriteLine("Prompt > "); + Console.Write("Prompt > "); userInput = Console.ReadLine()!; await TextCompletionStreamAsync(userInput); break; @@ -97,9 +97,14 @@ async Task ChatStreamAsync() history.Add(TextChatMessage.User(input)); var stream = dashScopeClient .GetQWenChatStreamAsync( - QWenLlm.QWenMax, + QWenLlm.QWenPlusLatest, history, - new TextGenerationParameters { IncrementalOutput = true, ResultFormat = ResultFormats.Message }); + new TextGenerationParameters + { + IncrementalOutput = true, + ResultFormat = ResultFormats.Message, + EnableThinking = true + }); var role = string.Empty; var message = new StringBuilder(); await foreach (var modelResponse in stream) @@ -112,7 +117,10 @@ async Task ChatStreamAsync() } message.Append(chunk.Message.Content); - Console.Write(chunk.Message.Content); + var write = string.IsNullOrEmpty(chunk.Message.ReasoningContent) + ? chunk.Message.Content + : chunk.Message.ReasoningContent; + Console.Write(write); } Console.WriteLine(); From 67e777851656936af46515dea575178415bbd393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B2=88=E6=98=9F=E7=B9=81?= Date: Thu, 12 Jun 2025 00:41:00 +0800 Subject: [PATCH 35/35] fix: require system.text.json 8.0 for compatibility issur --- .../Cnblogs.DashScope.Core.csproj | 1 + .../DashScopeClientCore.cs | 2 +- .../Internals/JsonSeparatorNamingPolicy.cs | 128 ------------------ .../JsonSnakeCaseLowerNamingPolicy.cs | 11 -- 4 files changed, 2 insertions(+), 140 deletions(-) delete mode 100644 src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs delete mode 100644 src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs diff --git a/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj b/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj index 7d46d37..b164ed0 100644 --- a/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj +++ b/src/Cnblogs.DashScope.Core/Cnblogs.DashScope.Core.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs index fdbed71..e0f3159 100644 --- a/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs +++ b/src/Cnblogs.DashScope.Core/DashScopeClientCore.cs @@ -18,7 +18,7 @@ public class DashScopeClientCore : IDashScopeClient new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - PropertyNamingPolicy = JsonSnakeCaseLowerNamingPolicy.SnakeCaseLower, + PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower }; private readonly HttpClient _httpClient; diff --git a/src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs b/src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs deleted file mode 100644 index 761ae20..0000000 --- a/src/Cnblogs.DashScope.Core/Internals/JsonSeparatorNamingPolicy.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System.Buffers; -using System.Globalization; -using System.Runtime.CompilerServices; -using System.Text.Json; - -namespace Cnblogs.DashScope.Core.Internals; - -// back-porting from dotnet/runtime -internal abstract class JsonSeparatorNamingPolicy : JsonNamingPolicy -{ - private readonly bool _lowercase; - private readonly char _separator; - - internal JsonSeparatorNamingPolicy(bool lowercase, char separator) - { - _lowercase = lowercase; - _separator = separator; - } - - public sealed override string ConvertName(string? name) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } - - return ConvertNameCore(_separator, _lowercase, name.AsSpan()); - } - - private static string ConvertNameCore(char separator, bool lowercase, ReadOnlySpan chars) - { - var rentedBuffer = (char[]?)null; - var minimumLength = (int)(1.2 * chars.Length); - var destination = minimumLength > 128 /*0x80*/ - ? (Span)(rentedBuffer = ArrayPool.Shared.Rent(minimumLength)) - : stackalloc char[128 /*0x80*/]; - var separatorState = SeparatorState.NotStarted; - var charsWritten = 0; - for (var index = 0; index < chars.Length; ++index) - { - var c = chars[index]; - var unicodeCategory = char.GetUnicodeCategory(c); - switch (unicodeCategory) - { - case UnicodeCategory.UppercaseLetter: - switch (separatorState) - { - case SeparatorState.UppercaseLetter: - if (index + 1 < chars.Length && char.IsLower(chars[index + 1])) - { - WriteChar(separator, ref destination); - } - - break; - case SeparatorState.LowercaseLetterOrDigit: - case SeparatorState.SpaceSeparator: - WriteChar(separator, ref destination); - break; - } - - if (lowercase) - c = char.ToLowerInvariant(c); - WriteChar(c, ref destination); - separatorState = SeparatorState.UppercaseLetter; - break; - case UnicodeCategory.LowercaseLetter: - case UnicodeCategory.DecimalDigitNumber: - if (separatorState == SeparatorState.SpaceSeparator) - WriteChar(separator, ref destination); - if (!lowercase && unicodeCategory == UnicodeCategory.LowercaseLetter) - c = char.ToUpperInvariant(c); - WriteChar(c, ref destination); - separatorState = SeparatorState.LowercaseLetterOrDigit; - break; - case UnicodeCategory.SpaceSeparator: - if (separatorState != SeparatorState.NotStarted) - { - separatorState = SeparatorState.SpaceSeparator; - } - - break; - default: - WriteChar(c, ref destination); - separatorState = SeparatorState.NotStarted; - break; - } - } - - var str = destination.Slice(0, charsWritten).ToString(); - if (rentedBuffer != null) - { - destination.Slice(0, charsWritten).Clear(); - ArrayPool.Shared.Return(rentedBuffer); - } - - return str; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - void WriteChar(char value, ref Span destination) - { - if (charsWritten == destination.Length) - ExpandBuffer(ref destination); - destination[charsWritten++] = value; - } - - void ExpandBuffer(ref Span destination) - { - var destination1 = ArrayPool.Shared.Rent(checked(destination.Length * 2)); - destination.CopyTo((Span)destination1); - if (rentedBuffer != null) - { - destination.Slice(0, charsWritten).Clear(); - ArrayPool.Shared.Return(rentedBuffer); - } - - rentedBuffer = destination1; - destination = (Span)rentedBuffer; - } - } - - private enum SeparatorState - { - NotStarted, - UppercaseLetter, - LowercaseLetterOrDigit, - SpaceSeparator, - } -} diff --git a/src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs b/src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs deleted file mode 100644 index 23d1f48..0000000 --- a/src/Cnblogs.DashScope.Core/Internals/JsonSnakeCaseLowerNamingPolicy.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Cnblogs.DashScope.Core.Internals; - -internal class JsonSnakeCaseLowerNamingPolicy : JsonSeparatorNamingPolicy -{ - public static readonly JsonSnakeCaseLowerNamingPolicy SnakeCaseLower = new(); - - private JsonSnakeCaseLowerNamingPolicy() - : base(true, '_') - { - } -}