Skip to content

Commit 4612151

Browse files
committed
优化示例
1 parent 0858fdb commit 4612151

File tree

4 files changed

+107
-51
lines changed

4 files changed

+107
-51
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,4 @@ obj/
6868
/Samples/Senparc.AI.Samples.Consoles/appsettings.test.json
6969
/Samples/Senparc.Weixin.AI.MPSample/App_Data/WeChat_OfficialAccount/2023-05-07
7070
/Samples/Senparc.Weixin.AI.MPSample/App_Data/WeChat_OfficialAccount/2023-05-13
71+
/Samples/Senparc.Weixin.AI.MPSample/App_Data/OpenAiImageTemp

Samples/Senparc.Weixin.AI.MPSample/CustomMessageHandler.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public override async Task<IResponseMessageBase> OnTextRequestAsync(RequestMessa
6969
messages.CleanMessage();
7070
await _cache.SetAsync(cacheKey, messages, TimeSpan.FromHours(1));
7171
responseMessage.Content = "Chat 准备就绪,请开始对话!";
72+
73+
//TODO:清空 Senparc.AI 层面的对话
74+
ReponseMessageFactory.iWantToRunCollection.TryRemove(OpenId, out _);
7275
return responseMessage;
7376
});
7477
return result.Unwrap().GetAwaiter().GetResult() as IResponseMessageBase;
@@ -100,7 +103,7 @@ public override async Task<IResponseMessageBase> OnTextRequestAsync(RequestMessa
100103
{
101104
var handler = new SemanticAiHandler();
102105
var factory = new ReponseMessageFactory(ServiceProvider);
103-
var isChat = true;
106+
var isChat = true;
104107
var responseMessage = await factory.GetResponseMessageAsync(_appId, this, requestMessage, handler, isChat);
105108
await factory.SendCustomMessageAsync(responseMessage, ApiEnlightener, _appId, OpenId);
106109
}

src/Senparc.Weixin.AI/ReponseMessageFactory.cs

Lines changed: 83 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Microsoft.SemanticKernel.CoreSkills;
1+
using Microsoft.SemanticKernel.AI.ImageGeneration;
2+
using Microsoft.SemanticKernel.CoreSkills;
23
using Microsoft.SemanticKernel.Orchestration;
34
using Senparc.AI;
45
using Senparc.AI.Entities;
@@ -20,6 +21,7 @@
2021
using Senparc.Weixin.MP.Entities;
2122
using System;
2223
using System.Collections.Concurrent;
24+
using System.Collections.Generic;
2325
using System.IO;
2426
using System.Linq;
2527
using System.Runtime.InteropServices;
@@ -29,8 +31,13 @@ namespace Senparc.Weixin.AI
2931
{
3032
public class ReponseMessageFactory
3133
{
34+
35+
public static ConcurrentDictionary<string, IWantToRun> iWantToRunCollection = new ConcurrentDictionary<string, IWantToRun>();
36+
3237
IServiceProvider ServiceProvider { get; set; }
3338

39+
40+
3441
public ReponseMessageFactory(IServiceProvider serviceProvider)
3542
{
3643
ServiceProvider = serviceProvider;
@@ -112,7 +119,6 @@ public async Task<string> GetResponseMessageByPlanAsync(IAiHandler aiHandler, st
112119
return messageType;
113120
}
114121

115-
public static ConcurrentDictionary<string, IWantToRun> iWantToRunCollection = new ConcurrentDictionary<string, IWantToRun>();
116122

117123
public async Task<ResponseMessageResult> GetResponseMessagResultAsync(IAiHandler aiHandler, string openId, string text, bool isChat)
118124
{
@@ -134,6 +140,7 @@ public async Task<ResponseMessageResult> GetResponseMessagResultAsync(IAiHandler
134140
MaxTokens = 2000,
135141
Temperature = 0.7,
136142
TopP = 0.5,
143+
StopSequences = new List<string> { "[done]" }
137144
};
138145
var chatConfig = skAiHandler.ChatConfig(parameter, userId: "User-" + openId);
139146
iWantToRun = chatConfig.iWantToRun;
@@ -250,6 +257,8 @@ public async Task<IResponseMessageBase> GetResponseMessageAsync(string appId, IM
250257
break;
251258
case ResponseMsgType.Image:
252259
{
260+
var useDallE = true;
261+
253262
var response = (IResponseMessageImage)responseMessage;
254263
//调用 DallE 接口,并上传图片
255264

@@ -262,63 +271,96 @@ public async Task<IResponseMessageBase> GetResponseMessageAsync(string appId, IM
262271

263272
_ = CustomApi.SendTextAsync(appId, openId, "图片Prompt:" + messageTypeResult.Result);
264273

265-
//var iWantToRun = skAiHandler
266-
// .IWantTo()
267-
// .ConfigModel(ConfigModel.ImageGeneration, openId, "dalle")
268-
// .BuildKernel();
269-
270-
//var dallE = iWantToRun.Kernel.GetService<IImageGeneration>();
271-
//var imageUrl = await dallE.GenerateImageAsync(messageTypeResult.Result, 256, 256);
272274
_ = CustomApi.SendTextAsync(appId, openId, $"正在准备图片,请等待...");
273275

274-
try
276+
277+
if (useDallE)
275278
{
276-
#region DallE 需要直接使用 OpenAI 接口,需要在中国外使用
279+
var iWantToRun = skAiHandler
280+
.IWantTo()
281+
.ConfigModel(ConfigModel.ImageGeneration, openId, "dalle")
282+
.BuildKernel();
277283

278-
//var ms = new MemoryStream();
279-
//var downloadFile = Senparc.CO2NET.HttpUtility.Get.DownloadAsync(ServiceProvider, imageUrl, ms);
280-
//ms.Seek(0, SeekOrigin.Begin);
284+
var dallE = iWantToRun.Kernel.GetService<IImageGeneration>();
285+
var imageUrl = await dallE.GenerateImageAsync(messageTypeResult.Result, 256, 256);
286+
try
287+
{
288+
#region DallE 默认需要直接使用 OpenAI 接口,需要在中国外使用
281289

290+
await CustomApi.SendTextAsync(appId, openId, @$"图片已生成,URL:{imageUrl}
291+
正在保存至本地,并上传到微信服务器,然后才能展示在窗口中。");
282292

283-
////缓存在本地
284-
//var fileDir = Senparc.CO2NET.Utilities.ServerUtility.ContentRootMapPath($"~/App_Data/OpenAiImageTemp");
285-
////确认文件夹存在
286-
//Senparc.CO2NET.Helpers.FileHelper.TryCreateDirectory(fileDir);
293+
var ms = new MemoryStream();
294+
var downloadFile = Senparc.CO2NET.HttpUtility.Get.DownloadAsync(ServiceProvider, imageUrl, ms);
295+
ms.Seek(0, SeekOrigin.Begin);
296+
ms.Position = 0;
287297

288-
//var file = Path.Combine(fileDir, $"{SystemTime.Now.ToString("yyyyMMdd-HH-mm-ss")}_{openId}_{SystemTime.NowTicks}.jpg");
298+
//缓存在本地
299+
var fileDir = Senparc.CO2NET.Utilities.ServerUtility.ContentRootMapPath($"~/App_Data/OpenAiImageTemp")
300+
.Replace(@"\\Mac\Develop & Data\", @"Y:\");//Mac 本地测试才需要
289301

290-
//using (var fs = new FileStream(file, FileMode.OpenOrCreate))
291-
//{
292-
// await ms.CopyToAsync(fs);
293-
// await fs.FlushAsync();
294-
//}
302+
//确认文件夹存在
303+
Senparc.CO2NET.Helpers.FileHelper.TryCreateDirectory(fileDir);
295304

296-
////创建一个副本,防止被占用
297-
//var newFile = file + ".jpg";
298-
//File.Copy(file, newFile);
299-
#endregion
305+
var file = Path.Combine(fileDir, $"{SystemTime.Now.ToString("yyyyMMdd-HH-mm-ss")}_{openId}_{SystemTime.NowTicks}.jpg");
300306

301-
var newFile = CO2NET.Utilities.ServerUtility.DllMapPath("~/test.png")
302-
.Replace(@"\\Mac\Develop & Data\", @"Y:\");
307+
using (var fs = new FileStream(file, FileMode.OpenOrCreate))
308+
{
309+
await ms.CopyToAsync(fs);
310+
await ms.FlushAsync();
311+
await fs.FlushAsync();
312+
}
303313

304-
//await CustomApi.SendTextAsync(appId, openId, $"new file:" + newFile);
314+
//创建一个副本,防止被占用
315+
var newFile = file + ".jpg";
316+
File.Copy(file, newFile);
317+
#endregion
305318

306-
//await CustomApi.SendTextAsync(appId, openId, $"new file exist:" + File.Exists(newFile));
319+
//await CustomApi.SendTextAsync(appId, openId, $"new file:" + newFile);
307320

308-
//上传到微信素材库
309-
var uploadResult = await MediaApi.UploadTemporaryMediaAsync(appId, Weixin.MP.UploadMediaFileType.image, newFile);
321+
//await CustomApi.SendTextAsync(appId, openId, $"new file exist:" + File.Exists(newFile));
310322

311-
//await CustomApi.SendTextAsync(appId, openId, $"result:"+uploadResult.ToJson(true));
323+
//上传到微信素材库
324+
var uploadResult = await MediaApi.UploadTemporaryMediaAsync(appId, MP.UploadMediaFileType.image, newFile, 500000);
312325

313-
await CustomApi.SendImageAsync(appId, openId, uploadResult.media_id);
326+
//await CustomApi.SendTextAsync(appId, openId, $"result:" + uploadResult.ToJson(true));
327+
328+
await CustomApi.SendImageAsync(appId, openId, uploadResult.media_id);
329+
330+
//删除临时文件
331+
File.Delete(newFile);
332+
}
333+
catch (Exception ex)
334+
{
335+
new SenparcAiException(ex.Message, ex);
336+
await CustomApi.SendTextAsync(appId, openId, $"图片生成失败!");
337+
}
314338

315-
//删除临时文件
316-
File.Delete(newFile);
317339
}
318-
catch (Exception ex)
340+
else
319341
{
320-
new SenparcAiException(ex.Message, ex);
321-
await CustomApi.SendTextAsync(appId, openId, $"图片生成失败!");
342+
try
343+
{
344+
var newFile = CO2NET.Utilities.ServerUtility.DllMapPath("~/test.png")
345+
.Replace(@"\\Mac\Develop & Data\", @"Y:\");
346+
347+
//await CustomApi.SendTextAsync(appId, openId, $"new file:" + newFile);
348+
349+
//await CustomApi.SendTextAsync(appId, openId, $"new file exist:" + File.Exists(newFile));
350+
351+
//上传到微信素材库
352+
var uploadResult = await MediaApi.UploadTemporaryMediaAsync(appId, MP.UploadMediaFileType.image, newFile, 500000);
353+
354+
//await CustomApi.SendTextAsync(appId, openId, $"result:" + uploadResult.ToJson(true));
355+
356+
await CustomApi.SendImageAsync(appId, openId, uploadResult.media_id);
357+
358+
}
359+
catch (Exception ex)
360+
{
361+
new SenparcAiException(ex.Message, ex);
362+
await CustomApi.SendTextAsync(appId, openId, $"图片生成失败!");
363+
}
322364
}
323365

324366
//预计会超过时间,直接返回文本信息

src/Senparc.Weixin.AI/WeixinSkills/SenparcWeixinSkills.cs

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,34 @@ public class SenparcWeixinSkills
2121

2222
private const string BUILD_RESPONSE_MESSAGE_DEFINITION = @"Determine the type of message and result that should be returned based on the input information.
2323
24+
The context of the request may contains several history messages, only the last message can determine the type of the message, which always using the key of ""input"" in context.
25+
2426
There are two types of message:
25-
- ResponseMessageText: just need return text, without image required. The Result parameter will be returned as a ChatBot's reply.
26-
- ResponseMessageImage: need to generate image. The Result parameter will give a better prompt to generate a image by general image generate engine.
27+
- Text: just need return text, without image required. The Result parameter will be returned as a ChatBot's reply.
28+
- Image: need to generate image. The Result parameter will give a better prompt to generate a image by general image generate engine.
2729
28-
Example:
30+
Examples:
2931
3032
Input: What's the mean of animal?
31-
Output: {""MessageType"":""ResponseMessageText"", ""Result"":""The word \""animal\"" is a broad term that refers to living organisms that are not plants or fungi, and it encompasses a wide range of species with diverse characteristics. Therefore, it is not possible to calculate a mean for the term ""animal"" as it is not a numerical value or a quantitative measure.""}
33+
Output: [{""MessageType"":""Text"", ""Result"":""The word \""animal\"" is a broad term that refers to living organisms that are not plants or fungi, and it encompasses a wide range of species with diverse characteristics. Therefore, it is not possible to calculate a mean for the term ""animal"" as it is not a numerical value or a quantitative measure.""}]
34+
35+
Input: Can you tell me what's in the image?
36+
Output: [{""MessageType"":""Text"", ""Result"":""It's an image of a panda driving a car in the sky, with the car flying high and the panda looking happy and excited.""}]
37+
38+
Input: Give me a picture with sky and bird.
39+
Output: [{""MessageType"":""Image"", ""Result"":""The sky is filled with colorful birds.""}]
3240
3341
Input: Give me an image shows the spring of China.
34-
Output: {""MessageType"":""ResponseMessageImage"", ""Result"":""Generate a high-quality and visually stunning image that depicts the beauty of spring in China, with a focus on blooming flowers, lush green landscapes, and perhaps a cultural or historical element such as a traditional Chinese garden or temple.""}
42+
Output: [{""MessageType"":""Image"", ""Result"":""Generate a high-quality and visually stunning image that depicts the beauty of spring in China, with a focus on blooming flowers, lush green landscapes, and perhaps a cultural or historical element such as a traditional Chinese garden or temple.""}]
43+
44+
[done]
3545
36-
# done
3746
38-
Now tell me the follow message's output:
39-
{{$input}}
4047
The original Output is JSON format, I want to get an XML format result, do the parse first. Just left JSON information without any other 'appendToResult' information.
41-
";
48+
49+
Now tell me the follow message's output:
50+
Input: {{$input}}
51+
Output: ";
4252

4353
public SenparcWeixinSkills(IKernel kernel)
4454
{

0 commit comments

Comments
 (0)