Skip to content
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
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ Console.WriteLine(completion.Output.Text);
```csharp
var history = new List<ChatMessage>
{
new("user", "Please remember this number, 42"),
new("assistant", "I have remembered this number."),
new("user", "What was the number I metioned before?")
ChatMessage.User("Please remember this number, 42"),
ChatMessage.Assistant("I have remembered this number."),
ChatMessage.User("What was the number I metioned before?")
}
var parameters = new TextGenerationParameters()
{
Expand Down Expand Up @@ -137,7 +137,7 @@ var tools = new List<ToolDefinition>()

var history = new List<ChatMessage>
{
new("user", "What is the weather today in C.A?")
ChatMessage.User("What is the weather today in C.A?")
};

var parameters = new TextGenerationParamters()
Expand All @@ -155,7 +155,7 @@ Console.WriteLine(completion.Output.Choice[0].Message.ToolCalls[0].Function.Name

// calling tool that model requests and append result into history.
var result = GetCurrentWeather(JsonSerializer.Deserialize<GetCurrentWeatherParameters>(completion.Output.Choice[0].Message.ToolCalls[0].Function.Arguments));
history.Add(new("tool", result, nameof(GetCurrentWeather)));
history.Add(ChatMessage.Tool(result, nameof(GetCurrentWeather)));

// get back answers.
completion = await client.GetQWenChatCompletionAsync(QWenLlm.QWenMax, history, parameters);
Expand All @@ -179,8 +179,8 @@ Using uploaded file id in messages.
```csharp
var history = new List<ChatMessage>
{
new(uploadedFile.Id), // use array for multiple files, e.g. [file1.Id, file2.Id]
new("user", "Summarize the content of file.")
ChatMessage.File(uploadedFile.Id), // use array for multiple files, e.g. [file1.Id, file2.Id]
ChatMessage.User("Summarize the content of file.")
}
var parameters = new TextGenerationParameters()
{
Expand Down
16 changes: 8 additions & 8 deletions README.zh-Hans.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

# Cnblogs.DashScopeSDK

由博客园维护并使用的非官方灵积服务 SDK。
由博客园维护并使用的非官方灵积(百炼)服务 SDK。

使用前注意:当前项目正在积极开发中,小版本也可能包含破坏性更改,升级前请查看对应版本 Release Note 进行迁移。

Expand Down Expand Up @@ -63,7 +63,7 @@ public class YourService(IDashScopeClient client)
- 人像风格重绘 - `CreateWanxImageGenerationTaskAsync()` and `GetWanxImageGenerationTaskAsync()`
- 图像背景生成 - `CreateWanxBackgroundGenerationTaskAsync()` and `GetWanxBackgroundGenerationTaskAsync()`
- 适用于 QWen-Long 的文件 API `dashScopeClient.UploadFileAsync()` and `dashScopeClient.DeleteFileAsync`

- 其他使用相同 Endpoint 的模型

# 示例

Expand All @@ -82,9 +82,9 @@ Console.WriteLine(completion.Output.Text);
```csharp
var history = new List<ChatMessage>
{
new("user", "Please remember this number, 42"),
new("assistant", "I have remembered this number."),
new("user", "What was the number I metioned before?")
ChatMessage.User("Please remember this number, 42"),
ChatMessage.Assistant("I have remembered this number."),
ChatMessage.User("What was the number I metioned before?")
}
var parameters = new TextGenerationParameters()
{
Expand Down Expand Up @@ -134,7 +134,7 @@ var tools = new List<ToolDefinition>()

var history = new List<ChatMessage>
{
new("user", "杭州现在天气如何?")
ChatMessage.User("What is the weather today in C.A?")
};

var parameters = new TextGenerationParamters()
Expand Down Expand Up @@ -175,8 +175,8 @@ var uploadedFile = await dashScopeClient.UploadFileAsync(file.OpenRead(), file.N
```csharp
var history = new List<ChatMessage>
{
new(uploadedFile.Id), // 多文件情况下可以直接传入文件 Id 数组, 例如:[file1.Id, file2.Id]
new("user", "总结一下文件的内容。")
ChatMessage.File(uploadedFile.Id), // 多文件情况下可以直接传入文件 Id 数组, 例如:[file1.Id, file2.Id]
ChatMessage.User("总结一下文件的内容。")
}
var parameters = new TextGenerationParameters()
{
Expand Down
10 changes: 5 additions & 5 deletions sample/Cnblogs.DashScope.Sample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ async Task ChatStreamAsync()
{
Console.Write("user > ");
var input = Console.ReadLine()!;
history.Add(new ChatMessage("user", input));
history.Add(ChatMessage.User(input));
var stream = dashScopeClient.GetQWenChatStreamAsync(
QWenLlm.QWenMax,
history,
Expand Down Expand Up @@ -109,10 +109,10 @@ async Task ChatWithFilesAsync()
Console.WriteLine("file uploaded, id: " + uploadedFile.Id);
Console.WriteLine();

var fileMessage = new ChatMessage(uploadedFile.Id);
var fileMessage = ChatMessage.File(uploadedFile.Id);
history.Add(fileMessage);
Console.WriteLine("system > " + fileMessage.Content);
var userPrompt = new ChatMessage("user", "该文件的内容是什么");
var userPrompt = ChatMessage.User("该文件的内容是什么");
history.Add(userPrompt);
Console.WriteLine("user > " + userPrompt.Content);
var stream = dashScopeClient.GetQWenChatStreamAsync(
Expand Down Expand Up @@ -156,7 +156,7 @@ async Task ChatWithToolsAsync()
new JsonSchemaBuilder().FromType<WeatherReportParameters>().Build()))
};
var chatParameters = new TextGenerationParameters() { ResultFormat = ResultFormats.Message, Tools = tools };
var question = new ChatMessage("user", "请问现在杭州的天气如何?");
var question = ChatMessage.User("请问现在杭州的天气如何?");
history.Add(question);
Console.WriteLine($"{question.Role} > {question.Content}");

Expand All @@ -168,7 +168,7 @@ async Task ChatWithToolsAsync()

var toolResponse = GetWeather(
JsonSerializer.Deserialize<WeatherReportParameters>(toolCallMessage.ToolCalls[0].Function!.Arguments!)!);
var toolMessage = new ChatMessage("tool", toolResponse, nameof(GetWeather));
var toolMessage = ChatMessage.Tool(toolResponse, nameof(GetWeather));
history.Add(toolMessage);
Console.WriteLine($"{toolMessage.Role} > {toolMessage.Content}");

Expand Down
67 changes: 67 additions & 0 deletions src/Cnblogs.DashScope.Core/ChatMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ namespace Cnblogs.DashScope.Core;
/// <param name="Role">The role of this message.</param>
/// <param name="Content">The content of this message.</param>
/// <param name="Name">Used when role is tool, represents the function name of this message generated by.</param>
/// <param name="Partial">Notify model that next message should use this message as prefix.</param>
/// <param name="ToolCalls">Calls to the function.</param>
[method: JsonConstructor]
public record ChatMessage(
string Role,
string Content,
string? Name = null,
bool? Partial = null,
List<ToolCall>? ToolCalls = null) : IMessage<string>
{
/// <summary>
Expand All @@ -34,4 +36,69 @@ public ChatMessage(IEnumerable<DashScopeFileId> fileIds)
: this("system", string.Join(',', fileIds.Select(f => f.ToUrl())))
{
}

/// <summary>
/// Creates a file message.
/// </summary>
/// <param name="fileId">The id of the file.</param>
/// <returns></returns>
public static ChatMessage File(DashScopeFileId fileId)
{
return new ChatMessage(fileId);
}

/// <summary>
/// Creates a file message.
/// </summary>
/// <param name="fileIds">The file id list.</param>
/// <returns></returns>
public static ChatMessage File(IEnumerable<DashScopeFileId> fileIds)
{
return new ChatMessage(fileIds);
}

/// <summary>
/// Create a user message.
/// </summary>
/// <param name="content">Content of the message.</param>
/// <param name="name">Author name.</param>
/// <returns></returns>
public static ChatMessage User(string content, string? name = null)
{
return new ChatMessage(DashScopeRoleNames.User, content, name);
}

/// <summary>
/// Create a system message.
/// </summary>
/// <param name="content">The content of the message.</param>
/// <returns></returns>
public static ChatMessage System(string content)
{
return new ChatMessage(DashScopeRoleNames.System, content);
}

/// <summary>
/// Create an assistant message
/// </summary>
/// <param name="content">The content of the message.</param>
/// <param name="partial">When set to true, content of this message would be the prefix of next model output.</param>
/// <param name="name">Author name.</param>
/// <param name="toolCalls">Tool calls by model.</param>
/// <returns></returns>
public static ChatMessage Assistant(string content, bool? partial = null, string? name = null, List<ToolCall>? toolCalls = null)
{
return new ChatMessage(DashScopeRoleNames.Assistant, content, name, partial, toolCalls);
}

/// <summary>
/// Create a tool message.
/// </summary>
/// <param name="content">The output from tool.</param>
/// <param name="name">The name of the tool.</param>
/// <returns></returns>
public static ChatMessage Tool(string content, string? name = null)
{
return new ChatMessage(DashScopeRoleNames.Tool, content, name);
}
}
17 changes: 17 additions & 0 deletions src/Cnblogs.DashScope.Core/DashScopeResponseFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Cnblogs.DashScope.Core;

/// <summary>
/// Available formats for <see cref="ITextGenerationParameters"/>.<see cref="ITextGenerationParameters.ResponseFormat"/>
/// </summary>
public record DashScopeResponseFormat(string Type)
{
/// <summary>
/// Output should be text.
/// </summary>
public static readonly DashScopeResponseFormat Text = new("text");

/// <summary>
/// Output should be json object.
/// </summary>
public static readonly DashScopeResponseFormat Json = new("json_object");
}
27 changes: 27 additions & 0 deletions src/Cnblogs.DashScope.Core/DashScopeRoleNames.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Cnblogs.DashScope.Core;

/// <summary>
/// Common role name.
/// </summary>
public static class DashScopeRoleNames
{
/// <summary>
/// User inputs.
/// </summary>
public const string User = "user";

/// <summary>
/// Model outputs.
/// </summary>
public const string Assistant = "assistant";

/// <summary>
/// System message.
/// </summary>
public const string System = "system";

/// <summary>
/// Tool outputs.
/// </summary>
public const string Tool = "tool";
}
22 changes: 21 additions & 1 deletion src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,34 @@ public interface ITextGenerationParameters
: IIncrementalOutputParameter, ISeedParameter, IProbabilityParameter, IPenaltyParameter, IMaxTokenParameter, IStopTokenParameter
{
/// <summary>
/// The format of the result message, must be <c>text</c> or <c>message</c>.
/// The format of the result, must be <c>text</c> or <c>message</c>.
/// </summary>
/// <remarks>
/// <c>text</c> - original text format.
/// <para><c>message</c> - OpenAI compatible message format</para>
/// </remarks>
/// <example>
/// Sets <c>result_format</c> to <c>message</c>
/// <code>
/// parameter.ResultFormat = ResultFormats.Message;
/// </code>
/// </example>
public string? ResultFormat { get; }

/// <summary>
/// The format of response message, must be <c>text</c> or <c>json_object</c>
/// </summary>
/// <remarks>
/// This property is not <see cref="ResultFormat"/>. Be sure not to confuse them.
/// </remarks>
/// <example>
/// Set response format to <c>json_object</c>.
/// <code>
/// parameter.ResponseFormat = DashScopeResponseFormat.Json;
/// </code>
/// </example>
public DashScopeResponseFormat? ResponseFormat { get; }

/// <summary>
/// Enable internet search when generation. Defaults to false.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Cnblogs.DashScope.Core;
namespace Cnblogs.DashScope.Core.Internals;

/// <summary>
/// JSON convertor for <see cref="TextGenerationStop"/>.
/// </summary>
public class TextGenerationStopConvertor : JsonConverter<TextGenerationStop>
internal class TextGenerationStopConvertor : JsonConverter<TextGenerationStop>
{
/// <inheritdoc />
public override TextGenerationStop? Read(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Cnblogs.DashScope.Core;
namespace Cnblogs.DashScope.Core.Internals;

/// <summary>
/// The converter for <see cref="ToolChoice"/>
/// </summary>
public class ToolChoiceJsonConverter : JsonConverter<ToolChoice>
internal class ToolChoiceJsonConverter : JsonConverter<ToolChoice>
{
/// <inheritdoc />
public override ToolChoice? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Expand Down
33 changes: 32 additions & 1 deletion src/Cnblogs.DashScope.Core/MultimodalMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,35 @@ namespace Cnblogs.DashScope.Core;
/// <param name="Role">The role associated with this message.</param>
/// <param name="Content">The contents of this message.</param>
public record MultimodalMessage(string Role, IReadOnlyList<MultimodalMessageContent> Content)
: IMessage<IReadOnlyList<MultimodalMessageContent>>;
: IMessage<IReadOnlyList<MultimodalMessageContent>>
{
/// <summary>
/// Create a user message.
/// </summary>
/// <param name="contents">Message contents.</param>
/// <returns></returns>
public static MultimodalMessage User(IReadOnlyList<MultimodalMessageContent> contents)
{
return new MultimodalMessage(DashScopeRoleNames.User, contents);
}

/// <summary>
/// Create a system message.
/// </summary>
/// <param name="contents">Message contents.</param>
/// <returns></returns>
public static MultimodalMessage System(IReadOnlyList<MultimodalMessageContent> contents)
{
return new MultimodalMessage(DashScopeRoleNames.System, contents);
}

/// <summary>
/// Creates an assistant message.
/// </summary>
/// <param name="contents">Message contents.</param>
/// <returns></returns>
public static MultimodalMessage Assistant(IReadOnlyList<MultimodalMessageContent> contents)
{
return new MultimodalMessage(DashScopeRoleNames.Assistant, contents);
}
}
Loading