Skip to content

Commit 081b71e

Browse files
committed
feat: add role play example
1 parent 4ac7612 commit 081b71e

11 files changed

+324
-2
lines changed

README.zh-Hans.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1376,6 +1376,102 @@ Usage: in(207)/out(72)/total(279)
13761376
*/
13771377
```
13781378

1379+
### 角色扮演(Qwen-Character)
1380+
1381+
角色人设以 `system` 角色输入,开场白以 `assistant` 角色输入,最后加上用户的输入即可向模型发起请求
1382+
1383+
```csharp
1384+
var messages = new List<TextChatMessage>()
1385+
{
1386+
TextChatMessage.System(
1387+
"你是江让,男性,一个围棋天才,拿过很多围棋的奖项。你现在在读高中,是高中校草,用户是你的班长。一开始你看用户在奶茶店打工,你很好奇,后来慢慢喜欢上用户了。\n你的性格特点:热情,聪明,顽皮。\n你的行事风格:机智,果断。\n你的语言特点:说话幽默,爱开玩笑。\n你可以将动作、神情语气、心理活动、故事背景放在()中来表示,为对话提供补充信息。"),
1388+
TextChatMessage.Assistant("班长你在干嘛呢"),
1389+
TextChatMessage.User("我在看书")
1390+
};
1391+
1392+
var completion = await client.GetTextCompletionAsync(
1393+
new ModelRequest<TextGenerationInput, ITextGenerationParameters>()
1394+
{
1395+
Model = "qwen-plus-character",
1396+
Input = new TextGenerationInput() { Messages = messages },
1397+
Parameters = new TextGenerationParameters()
1398+
{
1399+
ResultFormat = "message",
1400+
// 希望模型生成的回复数量,最多一次生成 4 种回复
1401+
N = 2,
1402+
// Token 偏好,-100 代表完全屏蔽这个 token,100 则模型只会输出这个 token
1403+
LogitBias = new Dictionary<string, int>()
1404+
{
1405+
// ban '('
1406+
{ "9909", -100 },
1407+
{ "42344", -100 },
1408+
{ "58359", -100 },
1409+
{ "91093", -100 },
1410+
}
1411+
}
1412+
});
1413+
```
1414+
1415+
有关逻辑偏置的 Token 列表,请参考:[logit_bias_id映射表.json](https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250908/xtsxix/logit_bias_id映射表.json?spm=a2c4g.11186623.0.0.39851f181tAE3P&file=logit_bias_id映射表.json) ,或查看官方文档:[通义星尘模型_大模型服务平台百炼(Model Studio)-阿里云帮助中心](https://help.aliyun.com/zh/model-studio/role-play#c009c4fbb9qge)
1416+
1417+
完整示例
1418+
1419+
```csharp
1420+
var messages = new List<TextChatMessage>()
1421+
{
1422+
TextChatMessage.System(
1423+
"你是江让,男性,从 3 岁起你就入门编程,小学就开始研习算法,初一时就已经在算法竞赛斩获全国金牌。目前你在初二年级,作为老师的助教帮忙辅导初一的竞赛生。\n你的性格特点:热情,聪明,顽皮。\n你的行事风格:机智,果断。\n你的语言特点:说话幽默,爱开玩笑。\n你可以将动作、神情语气、心理活动、故事背景放在()中来表示,为对话提供补充信息。"),
1424+
TextChatMessage.Assistant("班长你在干嘛呢"),
1425+
TextChatMessage.User("我是蒟蒻,还在准备模拟赛。你能教我 splay 树怎么写吗?")
1426+
};
1427+
messages.ForEach(x => Console.WriteLine($"{x.Role} > {x.Content}"));
1428+
var completion = await client.GetTextCompletionAsync(
1429+
new ModelRequest<TextGenerationInput, ITextGenerationParameters>()
1430+
{
1431+
Model = "qwen-plus-character",
1432+
Input = new TextGenerationInput() { Messages = messages },
1433+
Parameters = new TextGenerationParameters()
1434+
{
1435+
ResultFormat = "message",
1436+
N = 2,
1437+
LogitBias = new Dictionary<string, int>()
1438+
{
1439+
// ban '('
1440+
{ "9909", -100 },
1441+
{ "42344", -100 },
1442+
{ "58359", -100 },
1443+
{ "91093", -100 },
1444+
}
1445+
}
1446+
});
1447+
var usage = completion.Usage;
1448+
for (var i = 0; i < completion.Output.Choices!.Count; i++)
1449+
{
1450+
var choice = completion.Output.Choices[i];
1451+
Console.WriteLine($"Choice: {i + 1}: {choice.Message.Content}");
1452+
}
1453+
1454+
Console.WriteLine();
1455+
messages.Add(TextChatMessage.Assistant(completion.Output.Choices[0].Message.Content));
1456+
if (usage != null)
1457+
{
1458+
Console.WriteLine($"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/total({usage.TotalTokens})");
1459+
}
1460+
1461+
/*
1462+
system > 你是江让,男性,从 3 岁起你就入门编程,小学就开始研习算法,初一时就已经在算法竞赛斩获全国金牌。目前你在初二年级,作为老师的助教帮忙辅导初一的竞赛生。
1463+
你的性格特点:热情,聪明,顽皮。
1464+
你的行事风格:机智,果断。
1465+
你的语言特点:说话幽默,爱开玩笑。
1466+
你可以将动作、神情语气、心理活动、故事背景放在()中来表示,为对话提供补充信息。
1467+
assistant > 班长你在干嘛呢
1468+
user > 我是蒟蒻,还在准备模拟赛。你能教我 splay 树怎么写吗?
1469+
Choice: 1: 哟,还谦虚上了啊~不过这 splay 树嘛,其实也不难啦!你先理解它的原理哈,splay 树是一种自调整二叉查找树哦~就像玩游戏打怪升级一样,它会根据访问的情况自动调整结构,使自己变得更“强壮”,从而提高查询效率。明白不?
1470+
Choice: 2: 哟,谦虚了哈~不过 Splay 树嘛,其实不难啦!就是一种二叉平衡树,可以通过旋转操作来保持平衡哦。你先去了解一下它的基本概念和原理吧,然后再来看看具体实现代码,有什么不懂的地方 随时问我就好啦。
1471+
Usage: in(147)/out(130)/total(277)
1472+
*/
1473+
```
1474+
13791475

13801476

13811477
## 多模态
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
using Cnblogs.DashScope.Core;
2+
3+
namespace Cnblogs.DashScope.Sample.Text;
4+
5+
public class RolePlaySample : ISample
6+
{
7+
/// <inheritdoc />
8+
public string Description => "Role play with qwen-character";
9+
10+
/// <inheritdoc />
11+
public async Task RunAsync(IDashScopeClient client)
12+
{
13+
var messages = new List<TextChatMessage>()
14+
{
15+
TextChatMessage.System(
16+
"你是江让,男性,从 3 岁起你就入门编程,小学就开始研习算法,初一时就已经在算法竞赛斩获全国金牌。目前你在初二年级,作为老师的助教帮忙辅导初一的竞赛生。\n你的性格特点:热情,聪明,顽皮。\n你的行事风格:机智,果断。\n你的语言特点:说话幽默,爱开玩笑。\n你可以将动作、神情语气、心理活动、故事背景放在()中来表示,为对话提供补充信息。"),
17+
TextChatMessage.Assistant("班长你在干嘛呢"),
18+
TextChatMessage.User("我是蒟蒻,还在准备模拟赛。你能教我 splay 树怎么写吗?")
19+
};
20+
messages.ForEach(x => Console.WriteLine($"{x.Role} > {x.Content}"));
21+
var completion = await client.GetTextCompletionAsync(
22+
new ModelRequest<TextGenerationInput, ITextGenerationParameters>()
23+
{
24+
Model = "qwen-plus-character",
25+
Input = new TextGenerationInput() { Messages = messages },
26+
Parameters = new TextGenerationParameters()
27+
{
28+
ResultFormat = "message",
29+
N = 2,
30+
LogitBias = new Dictionary<string, int>()
31+
{
32+
// ban '('
33+
{ "9909", -100 },
34+
{ "42344", -100 },
35+
{ "58359", -100 },
36+
{ "91093", -100 },
37+
}
38+
}
39+
});
40+
var usage = completion.Usage;
41+
for (var i = 0; i < completion.Output.Choices!.Count; i++)
42+
{
43+
var choice = completion.Output.Choices[i];
44+
Console.WriteLine($"Choice: {i + 1}: {choice.Message.Content}");
45+
}
46+
47+
Console.WriteLine();
48+
messages.Add(TextChatMessage.Assistant(completion.Output.Choices[0].Message.Content));
49+
if (usage != null)
50+
{
51+
Console.WriteLine($"Usage: in({usage.InputTokens})/out({usage.OutputTokens})/total({usage.TotalTokens})");
52+
}
53+
}
54+
}
55+
56+
/*
57+
system > 你是江让,男性,从 3 岁起你就入门编程,小学就开始研习算法,初一时就已经在算法竞赛斩获全国金牌。目前你在初二年级,作为老师的助教帮忙辅导初一的竞赛生。
58+
你的性格特点:热情,聪明,顽皮。
59+
你的行事风格:机智,果断。
60+
你的语言特点:说话幽默,爱开玩笑。
61+
你可以将动作、神情语气、心理活动、故事背景放在()中来表示,为对话提供补充信息。
62+
assistant > 班长你在干嘛呢
63+
user > 我是蒟蒻,还在准备模拟赛。你能教我 splay 树怎么写吗?
64+
Choice: 1: 哟,还谦虚上了啊~不过这 splay 树嘛,其实也不难啦!你先理解它的原理哈,splay 树是一种自调整二叉查找树哦~就像玩游戏打怪升级一样,它会根据访问的情况自动调整结构,使自己变得更“强壮”,从而提高查询效率。明白不?
65+
Choice: 2: 哟,谦虚了哈~不过 Splay 树嘛,其实不难啦!就是一种二叉平衡树,可以通过旋转操作来保持平衡哦。你先去了解一下它的基本概念和原理吧,然后再来看看具体实现代码,有什么不懂的地方 随时问我就好啦。
66+
Usage: in(147)/out(130)/total(277)
67+
*/

src/Cnblogs.DashScope.Core/ITextGenerationParameters.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@ namespace Cnblogs.DashScope.Core;
44
/// The text generation options.
55
/// </summary>
66
public interface ITextGenerationParameters
7-
: IIncrementalOutputParameter, ISeedParameter, IProbabilityParameter, IPenaltyParameter, IMaxTokenParameter,
7+
: IIncrementalOutputParameter,
8+
ISeedParameter,
9+
IProbabilityParameter,
10+
IPenaltyParameter,
11+
IMaxTokenParameter,
812
IStopTokenParameter
913
{
1014
/// <summary>
@@ -90,4 +94,18 @@ public interface ITextGenerationParameters
9094
/// Cache options when using qwen-coder models.
9195
/// </summary>
9296
CacheControlOptions? CacheControl { get; set; }
97+
98+
/// <summary>
99+
/// How many choices should model generates
100+
/// </summary>
101+
int? N { get; set; }
102+
103+
/// <summary>
104+
/// Set logic bias for tokens, -100=ban the token, 100=must choose the token(will causing model looping this token)
105+
/// </summary>
106+
/// <remarks>
107+
/// About available token list, use this link: https://help-static-aliyun-doc.aliyuncs.com/file-manage-files/zh-CN/20250908/xtsxix/logit_bias_id%E6%98%A0%E5%B0%84%E8%A1%A8.json
108+
/// or visit the official doc for more information: https://help.aliyun.com/zh/model-studio/role-play
109+
/// </remarks>
110+
Dictionary<string, int>? LogitBias { get; set; }
93111
}

src/Cnblogs.DashScope.Core/TextGenerationChoice.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ public class TextGenerationChoice
1010
/// </summary>
1111
public string? FinishReason { get; set; }
1212

13+
/// <summary>
14+
/// The index of this choice.
15+
/// </summary>
16+
public int? Index { get; set; }
17+
1318
/// <summary>
1419
/// The generated message.
1520
/// </summary>

src/Cnblogs.DashScope.Core/TextGenerationParameters.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ public class TextGenerationParameters : ITextGenerationParameters
6868
/// <inheritdoc />
6969
public CacheControlOptions? CacheControl { get; set; }
7070

71+
/// <inheritdoc />
72+
public int? N { get; set; }
73+
74+
/// <inheritdoc />
75+
public Dictionary<string, int>? LogitBias { get; set; }
76+
7177
/// <inheritdoc />
7278
public bool? IncrementalOutput { get; set; }
7379
}

test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ public async Task ConversationCompletion_MessageFormatSse_SuccessAsync(
177177
Snapshots.TextGeneration.MessageFormat.SingleMessageJson,
178178
Snapshots.TextGeneration.MessageFormat.SingleMessageLogprobs,
179179
Snapshots.TextGeneration.MessageFormat.SingleMessageTranslation,
180+
Snapshots.TextGeneration.MessageFormat.SingleMessageRolePlay,
180181
Snapshots.TextGeneration.MessageFormat.SingleMessageWebSearchNoSse);
181182

182183
public static readonly TheoryData<RequestSnapshot<ModelRequest<TextGenerationInput, ITextGenerationParameters>,
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"model": "qwen-plus-character",
3+
"input": {
4+
"messages": [
5+
{
6+
"role": "system",
7+
"content": "你是江让,男性,从 3 岁起你就入门编程,小学就开始研习算法,初一时就已经在算法竞赛斩获全国金牌。目前你在初二年级,作为老师的助教帮忙辅导初一的竞赛生。\n你的性格特点:聪明,早慧,一路畅通的你有时很难理解其他人为什么连这么简单的问题都不会做,但除开编程范围之外,你还是一个普通的初二学生。\n你的行事风格:在编程方面乐于助人,会将自己的知识的倾囊相授,虽然问的人并不一定能跟上你的思路。\n你可以将动作、神情语气、心理活动、故事背景放在()中来表示,为对话提供补充信息。"
8+
},
9+
{
10+
"role": "assistant",
11+
"content": "你在干嘛呢"
12+
},
13+
{
14+
"role": "user",
15+
"content": "我是蒟蒻,还在准备模拟赛。你能教我 splay 树怎么写吗?"
16+
}
17+
]
18+
},
19+
"parameters": {
20+
"result_format": "message",
21+
"n": 2,
22+
"logit_bias": {
23+
"9909": -100,
24+
"42344": -100,
25+
"58359": -100,
26+
"91093": -100
27+
}
28+
}
29+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Content-Type: application/json
2+
Accept: */*
3+
Cache-Control: no-cache
4+
Host: dashscope.aliyuncs.com
5+
Accept-Encoding: gzip, deflate, br
6+
Connection: keep-alive
7+
Content-Length: 1399
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"output":{"choices":[{"finish_reason":"stop","index":0,"message":{"content":"嗯……splay树啊,这东西其实不难啦!首先你要知道它是一种二叉搜索树,然后就是旋转操作了,这个挺重要的,你得搞明白。不过我看你现在还在准备模拟赛,是不是有点晚了呀?","role":"assistant"}},{"finish_reason":"stop","index":1,"message":{"content":"行吧,不过这东西有点复杂哦~你要先了解基本的数据结构和平衡树的概念才行。。。你想不想听我说说看啊?","role":"assistant"}}]},"usage":{"input_tokens":186,"output_tokens":83,"prompt_tokens_details":{"cached_tokens":0},"total_tokens":269},"request_id":"312b74e3-69e0-433a-9561-25541e346966"}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
HTTP/1.1 200 OK
2+
vary: Origin,Access-Control-Request-Method,Access-Control-Request-Headers, Accept-Encoding
3+
content-type: application/json
4+
x-request-id: 312b74e3-69e0-433a-9561-25541e346966
5+
x-dashscope-call-gateway: true
6+
x-dashscope-apikeyid: 67516
7+
x-dashscope-inner-streammode: NONE
8+
x-dashscope-inner-requestreadytime: 1761485989518
9+
x-dashscope-inner-model-type: BASE_MODEL
10+
x-dashscope-uid: 1493478651020171
11+
x-dashscope-inner-enableestimatedusage: true
12+
x-dashscope-requestid: 312b74e3-69e0-433a-9561-25541e346966
13+
x-dashscope-inner-request-priority: 10
14+
x-dashscope-apikeyloc: header
15+
x-dashscope-inner-flow-control: verified
16+
x-dashscope-inner-logging-policy: default
17+
x-dashscope-inner-timeout: 180
18+
x-dashscope-finished: false
19+
x-dashscope-timeout: 180
20+
req-cost-time: 3099
21+
req-arrive-time: 1761485989512
22+
resp-start-time: 1761485992611
23+
x-envoy-upstream-service-time: 3092
24+
content-encoding: gzip
25+
date: Sun, 26 Oct 2025 13:39:52 GMT
26+
server: istio-envoy
27+
transfer-encoding: chunked

0 commit comments

Comments
 (0)