Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 84d7c8d

Browse files
feat: implement text embedding, text generation and chat completion api (#10)
1 parent 57a0142 commit 84d7c8d

27 files changed

+1067
-709
lines changed

‎.editorconfig‎

Lines changed: 159 additions & 135 deletions
Large diffs are not rendered by default.

‎.gitignore‎

Lines changed: 55 additions & 229 deletions
Large diffs are not rendered by default.

‎README.md‎

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,51 @@ Semantic Kernel Connector to DashScope
33

44
## Get started
55
Add the NuGet package to your project.
6-
```shell
6+
```shell
77
dotnet add package Cnblogs.SemanticKernel.Connectors.DashScope
88
```
99

10-
Add the `dashscope` section to the appsettings.json file.
11-
```json
12-
{
13-
"dashscope": {
14-
"modelId": "qwen-max"
15-
}
16-
}
17-
```
18-
Add the api key to the user-secrets.
19-
```shell
20-
dotnet user-secrets init
21-
dotnet user-secrets set "dashscope:apiKey" "sk-xxx"
22-
```
23-
## Usage
24-
Program.cs
2510
```cs
2611
using Microsoft.SemanticKernel;
2712

2813
var builder = Kernel.CreateBuilder();
29-
builder.AddDashScopeChatCompletion<Program>();
14+
builder.Services.AddDashScopeChatCompletion("your-api-key", "qwen-max");
3015
var kernel = builder.Build();
3116

32-
var prompt = @"<message role=""user"">Tell me about the Cnblogs</message>";
33-
var result = await kernel.InvokePromptAsync(prompt);
34-
Console.WriteLine(result);
17+
var prompt = "<message role=\"user\">Tell me about the Cnblogs</message>";
18+
var response = await kernel.InvokePromptAsync(prompt);
19+
Console.WriteLine(response);
20+
```
21+
22+
## ASP.NET Core
23+
24+
`appsettings.json`
3525

36-
public partial class Program
37-
{ }
26+
```json
27+
{
28+
"dashScope": {
29+
"apiKey": "your-key",
30+
"chatCompletionModelId": "qwen-max",
31+
"textEmbeddingModelId": "text-embedding-v2"
32+
}
33+
}
34+
```
35+
36+
`Program.cs`
37+
```csharp
38+
builder.Services.AddDashScopeChatCompletion(builder.Configuration);
39+
builder.Services.AddScoped<Kernel>(sp => new Kernel(sp));
3840
```
3941

42+
Services
43+
44+
```csharp
45+
public class YourService(Kernel kernel)
46+
{
47+
public async Task<string> GetCompletionAsync(string prompt)
48+
{
49+
var chatResult = await kernel.InvokePromptAsync(prompt);
50+
return chatResult.ToString();
51+
}
52+
}
53+
```

‎SemanticKernel.DashScope.sln‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1414
EndProject
1515
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{DAB267DF-F966-4F95-AD12-56CC78D6F274}"
1616
EndProject
17-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SemanticKernel.DashScope.IntegrationTest", "test\SemanticKernel.DashScope.IntegrationTest\SemanticKernel.DashScope.IntegrationTest.csproj", "{FA28DF4A-5A25-46C5-B2BE-614C30797B23}"
17+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SemanticKernel.DashScope.UnitTest", "test\SemanticKernel.DashScope.UnitTest\SemanticKernel.DashScope.UnitTest.csproj", "{648EBC1D-9409-4205-905E-DD06E4443AAA}"
1818
EndProject
1919
Global
2020
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -26,17 +26,17 @@ Global
2626
{B9EF31C7-48D7-4CA8-8D15-D6340450D3F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
2727
{B9EF31C7-48D7-4CA8-8D15-D6340450D3F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
2828
{B9EF31C7-48D7-4CA8-8D15-D6340450D3F5}.Release|Any CPU.Build.0 = Release|Any CPU
29-
{FA28DF4A-5A25-46C5-B2BE-614C30797B23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30-
{FA28DF4A-5A25-46C5-B2BE-614C30797B23}.Debug|Any CPU.Build.0 = Debug|Any CPU
31-
{FA28DF4A-5A25-46C5-B2BE-614C30797B23}.Release|Any CPU.ActiveCfg = Release|Any CPU
32-
{FA28DF4A-5A25-46C5-B2BE-614C30797B23}.Release|Any CPU.Build.0 = Release|Any CPU
29+
{648EBC1D-9409-4205-905E-DD06E4443AAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30+
{648EBC1D-9409-4205-905E-DD06E4443AAA}.Debug|Any CPU.Build.0 = Debug|Any CPU
31+
{648EBC1D-9409-4205-905E-DD06E4443AAA}.Release|Any CPU.ActiveCfg = Release|Any CPU
32+
{648EBC1D-9409-4205-905E-DD06E4443AAA}.Release|Any CPU.Build.0 = Release|Any CPU
3333
EndGlobalSection
3434
GlobalSection(SolutionProperties) = preSolution
3535
HideSolutionNode = FALSE
3636
EndGlobalSection
3737
GlobalSection(NestedProjects) = preSolution
3838
{B9EF31C7-48D7-4CA8-8D15-D6340450D3F5} = {BB73FA18-BBBE-4C34-971A-D4206FC118A2}
39-
{FA28DF4A-5A25-46C5-B2BE-614C30797B23} = {DAB267DF-F966-4F95-AD12-56CC78D6F274}
39+
{648EBC1D-9409-4205-905E-DD06E4443AAA} = {DAB267DF-F966-4F95-AD12-56CC78D6F274}
4040
EndGlobalSection
4141
GlobalSection(ExtensibilityGlobals) = postSolution
4242
SolutionGuid = {D0F2E9A4-9782-4C3F-B459-CFCAD4C9AD9F}
Lines changed: 110 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,144 @@
11
using System.Runtime.CompilerServices;
2-
using Microsoft.Extensions.Options;
2+
using Cnblogs.DashScope.Sdk;
33
using Microsoft.SemanticKernel;
44
using Microsoft.SemanticKernel.ChatCompletion;
55
using Microsoft.SemanticKernel.Services;
6-
using Sdcb.DashScope;
7-
using Sdcb.DashScope.TextGeneration;
6+
using Microsoft.SemanticKernel.TextGeneration;
87

98
namespace Cnblogs.SemanticKernel.Connectors.DashScope;
109

11-
public sealed class DashScopeChatCompletionService : IChatCompletionService
10+
/// <summary>
11+
/// DashScope chat completion service.
12+
/// </summary>
13+
public sealed class DashScopeChatCompletionService : IChatCompletionService, ITextGenerationService
1214
{
13-
private readonly DashScopeClient _dashScopeClient;
15+
private readonly IDashScopeClient _dashScopeClient;
16+
private readonly Dictionary<string, object?> _attributes = new();
1417
private readonly string _modelId;
15-
private readonly Dictionary<string, object?> _attribues = [];
1618

17-
public DashScopeChatCompletionService(
18-
IOptions<DashScopeClientOptions> options,
19-
HttpClient httpClient)
19+
/// <summary>
20+
/// Creates a new DashScope chat completion service.
21+
/// </summary>
22+
/// <param name="modelId"></param>
23+
/// <param name="dashScopeClient"></param>
24+
public DashScopeChatCompletionService(string modelId, IDashScopeClient dashScopeClient)
2025
{
21-
_dashScopeClient = new(options.Value.ApiKey,httpClient);
22-
_modelId = options.Value.ModelId;
23-
_attribues.Add(AIServiceExtensions.ModelIdKey, _modelId);
26+
_dashScopeClient = dashScopeClient;
27+
_modelId = modelId;
28+
_attributes.Add(AIServiceExtensions.ModelIdKey, _modelId);
2429
}
2530

26-
public IReadOnlyDictionary<string, object?> Attributes => _attribues;
27-
28-
public async Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(ChatHistory chatHistory, PromptExecutionSettings? executionSettings = null, Kernel? kernel = null, CancellationToken cancellationToken = default)
31+
/// <inheritdoc />
32+
public async Task<IReadOnlyList<ChatMessageContent>> GetChatMessageContentsAsync(
33+
ChatHistory chatHistory,
34+
PromptExecutionSettings? executionSettings = null,
35+
Kernel? kernel = null,
36+
CancellationToken cancellationToken = default)
2937
{
3038
var chatMessages = chatHistory.ToChatMessages();
31-
var chatParameters = executionSettings?.ToChatParameters();
32-
var response = await _dashScopeClient.TextGeneration.Chat(_modelId, chatMessages, chatParameters, cancellationToken);
39+
var chatParameters = DashScopePromptExecutionSettings.FromPromptExecutionSettings(executionSettings);
40+
chatParameters ??= new DashScopePromptExecutionSettings();
41+
chatParameters.IncrementalOutput = false;
42+
chatParameters.ResultFormat = ResultFormats.Message;
43+
var response = await _dashScopeClient.GetTextCompletionAsync(
44+
new ModelRequest<TextGenerationInput, ITextGenerationParameters>
45+
{
46+
Input = new TextGenerationInput { Messages = chatMessages },
47+
Model = string.IsNullOrEmpty(chatParameters.ModelId) ? _modelId : chatParameters.ModelId,
48+
Parameters = chatParameters
49+
},
50+
cancellationToken);
51+
var message = response.Output.Choices![0].Message;
3352
var chatMessageContent = new ChatMessageContent(
34-
new AuthorRole(chatMessages[0].Role),
35-
response.Output.Text,
36-
metadata: response.Usage.ToMetadata());
53+
new AuthorRole(message.Role),
54+
message.Content,
55+
metadata: response.ToMetaData());
3756
return [chatMessageContent];
3857
}
3958

59+
/// <inheritdoc />
4060
public async IAsyncEnumerable<StreamingChatMessageContent> GetStreamingChatMessageContentsAsync(
4161
ChatHistory chatHistory,
4262
PromptExecutionSettings? executionSettings = null,
4363
Kernel? kernel = null,
4464
[EnumeratorCancellation] CancellationToken cancellationToken = default)
4565
{
4666
var chatMessages = chatHistory.ToChatMessages();
47-
var chatParameters = executionSettings?.ToChatParameters() ?? new ChatParameters();
48-
chatParameters.IncrementalOutput = true;
67+
executionSettings ??= new DashScopePromptExecutionSettings();
68+
var parameters = DashScopePromptExecutionSettings.FromPromptExecutionSettings(executionSettings);
69+
parameters.IncrementalOutput = true;
70+
parameters.ResultFormat = ResultFormats.Message;
71+
var responses = _dashScopeClient.GetTextCompletionStreamAsync(
72+
new ModelRequest<TextGenerationInput, ITextGenerationParameters>
73+
{
74+
Input = new TextGenerationInput { Messages = chatMessages },
75+
Model = string.IsNullOrEmpty(parameters.ModelId) ? _modelId : parameters.ModelId,
76+
Parameters = parameters
77+
},
78+
cancellationToken);
4979

50-
var responses = _dashScopeClient.TextGeneration.ChatStreamed(_modelId, chatMessages, chatParameters, cancellationToken);
5180
await foreach (var response in responses)
5281
{
82+
var message = response.Output.Choices![0].Message;
5383
yield return new StreamingChatMessageContent(
54-
new AuthorRole(chatMessages[0].Role),
84+
new AuthorRole(message.Role),
85+
message.Content,
86+
modelId: _modelId,
87+
metadata: response.ToMetaData());
88+
}
89+
}
90+
91+
/// <inheritdoc />
92+
public IReadOnlyDictionary<string, object?> Attributes => _attributes;
93+
94+
/// <inheritdoc />
95+
public async Task<IReadOnlyList<TextContent>> GetTextContentsAsync(
96+
string prompt,
97+
PromptExecutionSettings? executionSettings = null,
98+
Kernel? kernel = null,
99+
CancellationToken cancellationToken = new())
100+
{
101+
var chatParameters = DashScopePromptExecutionSettings.FromPromptExecutionSettings(executionSettings);
102+
chatParameters ??= new DashScopePromptExecutionSettings();
103+
chatParameters.IncrementalOutput = false;
104+
chatParameters.ResultFormat = ResultFormats.Text;
105+
var response = await _dashScopeClient.GetTextCompletionAsync(
106+
new ModelRequest<TextGenerationInput, ITextGenerationParameters>
107+
{
108+
Input = new TextGenerationInput { Prompt = prompt },
109+
Model = string.IsNullOrEmpty(chatParameters.ModelId) ? _modelId : chatParameters.ModelId,
110+
Parameters = chatParameters
111+
},
112+
cancellationToken);
113+
return [new TextContent(response.Output.Text, _modelId, metadata: response.ToMetaData())];
114+
}
115+
116+
/// <inheritdoc />
117+
public async IAsyncEnumerable<StreamingTextContent> GetStreamingTextContentsAsync(
118+
string prompt,
119+
PromptExecutionSettings? executionSettings = null,
120+
Kernel? kernel = null,
121+
[EnumeratorCancellation] CancellationToken cancellationToken = new())
122+
{
123+
executionSettings ??= new DashScopePromptExecutionSettings();
124+
var parameters = DashScopePromptExecutionSettings.FromPromptExecutionSettings(executionSettings);
125+
parameters.IncrementalOutput = true;
126+
parameters.ResultFormat = ResultFormats.Text;
127+
var responses = _dashScopeClient.GetTextCompletionStreamAsync(
128+
new ModelRequest<TextGenerationInput, ITextGenerationParameters>
129+
{
130+
Input = new TextGenerationInput { Prompt = prompt },
131+
Model = string.IsNullOrEmpty(parameters.ModelId) ? _modelId : parameters.ModelId,
132+
Parameters = parameters
133+
},
134+
cancellationToken);
135+
136+
await foreach (var response in responses)
137+
{
138+
yield return new StreamingTextContent(
55139
response.Output.Text,
56-
metadata: response.Usage.ToMetadata());
140+
modelId: _modelId,
141+
metadata: response.ToMetaData());
57142
}
58143
}
59144
}

‎src/SemanticKernel.DashScope/DashScopeClientOptions.cs‎

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Cnblogs.DashScope.Sdk;
2+
using Microsoft.SemanticKernel.ChatCompletion;
3+
4+
namespace Cnblogs.SemanticKernel.Connectors.DashScope;
5+
6+
internal static class DashScopeMapper
7+
{
8+
public static List<ChatMessage> ToChatMessages(this ChatHistory history)
9+
{
10+
return history.Select(x => new ChatMessage(x.Role.Label, x.Content ?? string.Empty)).ToList();
11+
}
12+
13+
public static Dictionary<string, object?>? ToMetaData<TOutput, TUsage>(
14+
this ModelResponse<TOutput, TUsage>? response)
15+
where TUsage : class
16+
where TOutput : class
17+
{
18+
return response == null
19+
? null
20+
: new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
21+
{
22+
{ "Usage", response.Usage }, { "RequestId", response.RequestId }
23+
};
24+
}
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace Cnblogs.SemanticKernel.Connectors.DashScope;
2+
3+
/// <summary>
4+
/// Options about DashScopeClient
5+
/// </summary>
6+
public class DashScopeOptions
7+
{
8+
/// <summary>
9+
/// The text embedding model id.
10+
/// </summary>
11+
public string TextEmbeddingModelId { get; set; } = string.Empty;
12+
13+
/// <summary>
14+
/// Default model name for chat completion.
15+
/// </summary>
16+
public string ChatCompletionModelId { get; set; } = string.Empty;
17+
18+
/// <summary>
19+
/// The DashScope api key.
20+
/// </summary>
21+
public string ApiKey { get; set; } = string.Empty;
22+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /