Skip to content

feat: allow setting workspace id per application request #86

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions src/Cnblogs.DashScope.Core/ApplicationRequest.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
namespace Cnblogs.DashScope.Core;
using System.Text.Json.Serialization;
using Cnblogs.DashScope.Core.Internals;

namespace Cnblogs.DashScope.Core;

/// <summary>
/// Request body for an application all.
/// </summary>
/// <typeparam name="TBizParams">Type of the biz_content</typeparam>
public class ApplicationRequest<TBizParams>
public class ApplicationRequest<TBizParams> : IDashScopeWorkspaceConfig
where TBizParams : class
{
/// <summary>
/// Content of this call.
/// </summary>
public required ApplicationInput<TBizParams> Input { get; init; }
public required ApplicationInput<TBizParams> Input { get; set; }

/// <summary>
/// Optional configurations.
/// </summary>
public ApplicationParameters? Parameters { get; init; }
public ApplicationParameters? Parameters { get; set; }

/// <summary>
/// Optional workspace id.
/// </summary>
[JsonIgnore]
public string? WorkspaceId { get; set; }
}

/// <summary>
Expand Down
11 changes: 6 additions & 5 deletions src/Cnblogs.DashScope.Core/DashScopeClientCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ public async Task<DashScopeFileList> ListFilesAsync(CancellationToken cancellati
}

/// <inheritdoc />
public async Task<DashScopeDeleteFileResult> DeleteFileAsync(DashScopeFileId id, CancellationToken cancellationToken = default)
public async Task<DashScopeDeleteFileResult> DeleteFileAsync(
DashScopeFileId id,
CancellationToken cancellationToken = default)
{
var request = BuildRequest(HttpMethod.Delete, ApiLinks.Files + $"/{id}");
return (await SendCompatibleAsync<DashScopeDeleteFileResult>(request, cancellationToken))!;
Expand All @@ -297,8 +299,7 @@ private static HttpRequestMessage BuildRequest<TPayload>(
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)
Expand All @@ -316,9 +317,9 @@ private static HttpRequestMessage BuildRequest<TPayload>(
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;
Expand Down
12 changes: 12 additions & 0 deletions src/Cnblogs.DashScope.Core/Internals/IDashScopeWorkspaceConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Cnblogs.DashScope.Core.Internals;

/// <summary>
/// Workspace configuration.
/// </summary>
internal interface IDashScopeWorkspaceConfig
{
/// <summary>
/// Unique id of workspace to use.
/// </summary>
public string? WorkspaceId { get; }
}
7 changes: 7 additions & 0 deletions src/Cnblogs.DashScope.Core/TextGenerationTokenDetails.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Cnblogs.DashScope.Core;

/// <summary>
/// Token usage details.
/// </summary>
/// <param name="CachedTokens">Token count of cached input tokens</param>
public record TextGenerationTokenDetails(int CachedTokens);
5 changes: 5 additions & 0 deletions src/Cnblogs.DashScope.Core/TextGenerationTokenUsage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ public class TextGenerationTokenUsage
/// <remarks>This number may larger than input if internet search is enabled.</remarks>
public int InputTokens { get; set; }

/// <summary>
/// Input token details.
/// </summary>
public TextGenerationTokenDetails? PromptTokensDetails { get; set; }

/// <summary>
/// The number of output token.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -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"}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,30 @@ public static readonly RequestSnapshot<ApplicationRequest<TestApplicationBizPara
new ApplicationOutput("code", "stop", "5a20b47dac2f43a7b1cbb8924ca66c47", null, null),
new ApplicationUsage(null)));

public static readonly RequestSnapshot<ApplicationRequest<TestApplicationBizParam>, ApplicationResponse>
WorkflowInDifferentWorkSpaceNoSse =
new(
"application-workflow",
new ApplicationRequest<TestApplicationBizParam>()
{
Input = new ApplicationInput<TestApplicationBizParam>()
{
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<ApplicationRequest, ApplicationResponse> ConversationSessionIdNoSse =
new(
"application-conversation-generation-session-id",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
});

Expand Down
25 changes: 25 additions & 0 deletions test/Cnblogs.DashScope.Sdk.UnitTests/WorkspaceIdTests.cs
Original file line number Diff line number Diff line change
@@ -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<HttpRequestMessage>(
m => m.Headers.GetValues("X-DashScope-WorkSpace").First() == testCase.RequestModel.WorkspaceId),
Arg.Any<CancellationToken>());
}
}