Merge branch 'master' of https://github.com/White-Tailed-Eagle/BotSharp
This commit is contained in:
commit
bf01fbd25f
11
BotSharp.sln
11
BotSharp.sln
|
|
@ -85,6 +85,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.Dashboard",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.SparkDesk", "src\Plugins\BotSharp.Plugin.SparkDesk\BotSharp.Plugin.SparkDesk.csproj", "{289E25C8-63F1-4D52-9909-207724DB40CB}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.SparkDesk", "src\Plugins\BotSharp.Plugin.SparkDesk\BotSharp.Plugin.SparkDesk.csproj", "{289E25C8-63F1-4D52-9909-207724DB40CB}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BotSharp.Plugin.MetaGLM", "src\Plugins\BotSharp.Plugin.MetaGLM\BotSharp.Plugin.MetaGLM.csproj", "{CCF745F2-0C95-4ED0-983B-507C528B39EA}"
|
||||||
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.AnthropicAI", "src\Plugins\BotSharp.Plugin.AnthropicAI\BotSharp.Plugin.AnthropicAI.csproj", "{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BotSharp.Plugin.AnthropicAI", "src\Plugins\BotSharp.Plugin.AnthropicAI\BotSharp.Plugin.AnthropicAI.csproj", "{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
|
|
@ -335,6 +337,14 @@ Global
|
||||||
{289E25C8-63F1-4D52-9909-207724DB40CB}.Release|Any CPU.Build.0 = Release|Any CPU
|
{289E25C8-63F1-4D52-9909-207724DB40CB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{289E25C8-63F1-4D52-9909-207724DB40CB}.Release|x64.ActiveCfg = Release|Any CPU
|
{289E25C8-63F1-4D52-9909-207724DB40CB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
{289E25C8-63F1-4D52-9909-207724DB40CB}.Release|x64.Build.0 = Release|Any CPU
|
{289E25C8-63F1-4D52-9909-207724DB40CB}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
|
@ -385,6 +395,7 @@ Global
|
||||||
{D775DB67-A4B4-44E5-9144-522689590057} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
|
{D775DB67-A4B4-44E5-9144-522689590057} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
|
||||||
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
|
{267998C1-55C2-4ADC-8361-2CDFA5EA6D6C} = {51AFE054-AE99-497D-A593-69BAEFB5106F}
|
||||||
{289E25C8-63F1-4D52-9909-207724DB40CB} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
|
{289E25C8-63F1-4D52-9909-207724DB40CB} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
|
||||||
|
{CCF745F2-0C95-4ED0-983B-507C528B39EA} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
|
||||||
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
|
{806A0B0E-FEFF-420E-B5B2-C9FCBF890A8C} = {D5293208-2BEF-42FC-A64C-5954F61720BA}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
|
|
||||||
|
|
@ -22,11 +22,13 @@ public partial class ConversationService
|
||||||
if (dialogs.IsNullOrEmpty()) continue;
|
if (dialogs.IsNullOrEmpty()) continue;
|
||||||
|
|
||||||
var content = GetConversationContent(dialogs);
|
var content = GetConversationContent(dialogs);
|
||||||
if (string.IsNullOrEmpty(content)) continue;
|
if (string.IsNullOrWhiteSpace(content)) continue;
|
||||||
|
|
||||||
contents.Add(content);
|
contents.Add(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (contents.IsNullOrEmpty()) return string.Empty;
|
||||||
|
|
||||||
var router = await agentService.LoadAgent(AIAssistant);
|
var router = await agentService.LoadAgent(AIAssistant);
|
||||||
var prompt = GetPrompt(router, contents);
|
var prompt = GetPrompt(router, contents);
|
||||||
var summary = await Summarize(router, prompt);
|
var summary = await Summarize(router, prompt);
|
||||||
|
|
@ -39,10 +41,10 @@ public partial class ConversationService
|
||||||
var template = agent.Templates.First(x => x.Name == "conversation.summary").Content;
|
var template = agent.Templates.First(x => x.Name == "conversation.summary").Content;
|
||||||
var render = _services.GetRequiredService<ITemplateRender>();
|
var render = _services.GetRequiredService<ITemplateRender>();
|
||||||
|
|
||||||
var texts = string.Empty;
|
var texts = new List<string>();
|
||||||
for (int i = 0; i < contents.Count; i++)
|
for (int i = 0; i < contents.Count; i++)
|
||||||
{
|
{
|
||||||
texts += $"[Conversation {i+1}]\r\n{contents[i]}";
|
texts.Add($"{contents[i]}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return render.Render(template, new Dictionary<string, object>
|
return render.Render(template, new Dictionary<string, object>
|
||||||
|
|
@ -97,7 +99,12 @@ public partial class ConversationService
|
||||||
foreach (var dialog in dialogs.TakeLast(maxDialogCount))
|
foreach (var dialog in dialogs.TakeLast(maxDialogCount))
|
||||||
{
|
{
|
||||||
var role = dialog.Role;
|
var role = dialog.Role;
|
||||||
if (role != AgentRole.User && role != AgentRole.Assistant) continue;
|
if (role == AgentRole.Function) continue;
|
||||||
|
|
||||||
|
if (role != AgentRole.User)
|
||||||
|
{
|
||||||
|
role = AgentRole.Assistant;
|
||||||
|
}
|
||||||
|
|
||||||
conversation += $"{role}: {dialog.Payload ?? dialog.Content}\r\n";
|
conversation += $"{role}: {dialog.Payload ?? dialog.Content}\r\n";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -138,7 +138,7 @@ public partial class BotSharpFileService
|
||||||
foreach (var messageId in messageIds)
|
foreach (var messageId in messageIds)
|
||||||
{
|
{
|
||||||
var dir = GetConversationFileDirectory(conversationId, messageId);
|
var dir = GetConversationFileDirectory(conversationId, messageId);
|
||||||
if (string.IsNullOrEmpty(dir)) continue;
|
if (!ExistDirectory(dir)) continue;
|
||||||
|
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
Directory.Delete(dir, true);
|
Directory.Delete(dir, true);
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,12 @@ public class UserService : IUserService
|
||||||
{
|
{
|
||||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||||
User user = default;
|
User user = default;
|
||||||
if (_user.UserName != null)
|
|
||||||
|
if (_user.Id != null)
|
||||||
|
{
|
||||||
|
user = db.GetUserById(_user.Id);
|
||||||
|
}
|
||||||
|
else if (_user.UserName != null)
|
||||||
{
|
{
|
||||||
user = db.GetUserByUserName(_user.UserName);
|
user = db.GetUserByUserName(_user.UserName);
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +227,7 @@ public class UserService : IUserService
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
[MemoryCache(10 * 60)]
|
[MemoryCache(10 * 60, perInstanceCache: true)]
|
||||||
public async Task<User> GetUser(string id)
|
public async Task<User> GetUser(string id)
|
||||||
{
|
{
|
||||||
var db = _services.GetRequiredService<IBotSharpRepository>();
|
var db = _services.GetRequiredService<IBotSharpRepository>();
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
Please read each conversation in the [CONVERSATIONS] section and provide a summary.
|
Please read each conversation in the [CONVERSATIONS] section by the same user and provide a summary.
|
||||||
|
|
||||||
*** Super Important! Please consider every conversation. Do not only consider the recent sentences. ***
|
*** Super Important! Please consider every conversation. Do not only consider the recent sentences. ***
|
||||||
** Please do not respond to the latest conversation.
|
** Please do not respond to the latest conversation.
|
||||||
** If there are different topics in the conversations, please summarize each topic in different sentences and list them in bullets.
|
** Please summarize all conversations in one sentence.
|
||||||
* Please use concise sentences to summarize each topic.
|
** Please do not exceed 900 characters when summarizing the conversations.
|
||||||
* Please do not include excessive details in the summaries.
|
* Please do not contain general information in the summary.
|
||||||
* Please use 'user' instead of 'you', 'he' or 'she'.
|
* Please include some but not excessive details in the summary.
|
||||||
|
|
||||||
|
|
||||||
[CONVERSATIONS]
|
[CONVERSATIONS]
|
||||||
|
|
||||||
{% for text in texts -%}
|
{% for text in texts -%}
|
||||||
|
[CONVERSATION]
|
||||||
{{ text }}{{ "\r\n" }}
|
{{ text }}{{ "\r\n" }}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
40
src/Plugins/BotSharp.Plugin.MetaGLM/AuthenicationUtils.cs
Normal file
40
src/Plugins/BotSharp.Plugin.MetaGLM/AuthenicationUtils.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM;
|
||||||
|
|
||||||
|
public class AuthenticationUtils
|
||||||
|
{
|
||||||
|
public static string GenerateToken(string apiKey, int expSeconds)
|
||||||
|
{
|
||||||
|
|
||||||
|
var parts = apiKey.Split('.');
|
||||||
|
if (parts.Length != 2)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Invalid API key format.");
|
||||||
|
}
|
||||||
|
|
||||||
|
string id = parts[0];
|
||||||
|
string secret = parts[1];
|
||||||
|
byte[] keyBytes = Encoding.UTF8.GetBytes(secret);
|
||||||
|
if (keyBytes.Length < 32)
|
||||||
|
{
|
||||||
|
// Extend the key to meet the minimum length requirement
|
||||||
|
Array.Resize(ref keyBytes, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
var securityKey = new SymmetricSecurityKey(keyBytes);
|
||||||
|
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var payload = new JwtPayload
|
||||||
|
{
|
||||||
|
{ "api_key", id },
|
||||||
|
{ "exp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() + expSeconds },
|
||||||
|
{ "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
|
||||||
|
};
|
||||||
|
|
||||||
|
var header = new JwtHeader(credentials);
|
||||||
|
header.Add("sign_type", "SIGN");
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(header, payload);
|
||||||
|
|
||||||
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<LangVersion>12.0</LangVersion>
|
||||||
|
<VersionPrefix>$(BotSharpVersion)</VersionPrefix>
|
||||||
|
<GeneratePackageOnBuild>$(GeneratePackageOnBuild)</GeneratePackageOnBuild>
|
||||||
|
<GenerateDocumentationFile>$(GenerateDocumentationFile)</GenerateDocumentationFile>
|
||||||
|
<OutputPath>$(SolutionDir)packages</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.4.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Infrastructure\BotSharp.Abstraction\BotSharp.Abstraction.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
31
src/Plugins/BotSharp.Plugin.MetaGLM/MessageItemConverter.cs
Normal file
31
src/Plugins/BotSharp.Plugin.MetaGLM/MessageItemConverter.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM;
|
||||||
|
|
||||||
|
public class MessageItemConverter : JsonConverter<MessageItem>
|
||||||
|
{
|
||||||
|
public override MessageItem Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
// Implement deserialization logic if needed
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, MessageItem value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteStartObject();
|
||||||
|
|
||||||
|
// Serialize all properties except 'content' for ImageToTextMessageItem
|
||||||
|
foreach (var prop in value.GetType().GetProperties())
|
||||||
|
{
|
||||||
|
if (value is ImageToTextMessageItem && prop.Name.Equals("content", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// Skip serializing 'content' for ImageToTextMessageItem
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var propValue = prop.GetValue(value);
|
||||||
|
writer.WritePropertyName(prop.Name);
|
||||||
|
JsonSerializer.Serialize(writer, propValue, prop.PropertyType, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WriteEndObject();
|
||||||
|
}
|
||||||
|
}
|
||||||
23
src/Plugins/BotSharp.Plugin.MetaGLM/MetaGLMClient.cs
Normal file
23
src/Plugins/BotSharp.Plugin.MetaGLM/MetaGLMClient.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
using BotSharp.Plugin.MetaGLM.Modules;
|
||||||
|
|
||||||
|
namespace BotSharp.Plugin.MetaGLM
|
||||||
|
{
|
||||||
|
public class MetaGLMClient
|
||||||
|
{
|
||||||
|
private MetaGLMSettings _settings;
|
||||||
|
|
||||||
|
public Chat Chat { get; private set; }
|
||||||
|
|
||||||
|
public Images Images { get; private set; }
|
||||||
|
|
||||||
|
public Embeddings Embeddings { get; private set; }
|
||||||
|
|
||||||
|
public MetaGLMClient(MetaGLMSettings settings)
|
||||||
|
{
|
||||||
|
this._settings = settings;
|
||||||
|
this.Chat = new Chat(this._settings.ApiKey, _settings.BaseAddress);
|
||||||
|
this.Images = new Images(this._settings.ApiKey, _settings.BaseAddress);
|
||||||
|
this.Embeddings = new Embeddings(this._settings.ApiKey, _settings.BaseAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
src/Plugins/BotSharp.Plugin.MetaGLM/MetaGLMPlugin.cs
Normal file
29
src/Plugins/BotSharp.Plugin.MetaGLM/MetaGLMPlugin.cs
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM;
|
||||||
|
|
||||||
|
public class MetaGLMPlugin : IBotSharpPlugin
|
||||||
|
{
|
||||||
|
public string Id => "35d464d9-dd94-4cac-9e5a-1eaff6b943f5";
|
||||||
|
|
||||||
|
public string Name => "MetaGLM AI";
|
||||||
|
|
||||||
|
public string Description => "MetaGLM Service including text generation and embedding services.";
|
||||||
|
|
||||||
|
public SettingsMeta Settings => new SettingsMeta("MetaGLM");
|
||||||
|
|
||||||
|
public object GetNewSettingsInstance()
|
||||||
|
{
|
||||||
|
return new MetaGLMSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RegisterDI(IServiceCollection services, IConfiguration config)
|
||||||
|
{
|
||||||
|
services.AddScoped(provider =>
|
||||||
|
{
|
||||||
|
var settingService = provider.GetRequiredService<ISettingService>();
|
||||||
|
return settingService.Bind<MetaGLMSettings>("MetaGLM");
|
||||||
|
});
|
||||||
|
services.AddScoped<MetaGLMClient>();
|
||||||
|
services.AddScoped<IChatCompletion, ChatCompletionProvider>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels;
|
||||||
|
|
||||||
|
public class EmbeddingRequestBase
|
||||||
|
{
|
||||||
|
// "input": input,
|
||||||
|
// "model": model,
|
||||||
|
// "encoding_format": encoding_format,
|
||||||
|
// "user": user,
|
||||||
|
public string model { get; private set; }
|
||||||
|
public string input { get; private set; }
|
||||||
|
|
||||||
|
public EmbeddingRequestBase SetModel(string model)
|
||||||
|
{
|
||||||
|
this.model = model;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public EmbeddingRequestBase SetInput(string input)
|
||||||
|
{
|
||||||
|
this.input = input;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels.FunctionModels;
|
||||||
|
|
||||||
|
public enum ParameterType
|
||||||
|
{
|
||||||
|
String,
|
||||||
|
Integer,
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FunctionParameterDescriptor
|
||||||
|
{
|
||||||
|
public string type { get; set; }
|
||||||
|
public string description { get; set; }
|
||||||
|
|
||||||
|
private static string ToTypeString(ParameterType type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
ParameterType.String => "string",
|
||||||
|
ParameterType.Integer => "int",
|
||||||
|
_ => null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionParameterDescriptor(ParameterType type, string description)
|
||||||
|
{
|
||||||
|
this.type = ToTypeString(type);
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels.FunctionModels;
|
||||||
|
|
||||||
|
public class FunctionParameters
|
||||||
|
{
|
||||||
|
public string type { get; set; }
|
||||||
|
public Dictionary<string, FunctionParameterDescriptor> properties { get; }
|
||||||
|
public string[] required { get; set; }
|
||||||
|
|
||||||
|
public FunctionParameters()
|
||||||
|
{
|
||||||
|
this.type = "object";
|
||||||
|
this.properties = new Dictionary<string, FunctionParameterDescriptor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionParameters AddParameter(string name, ParameterType type, string description)
|
||||||
|
{
|
||||||
|
properties[name] = new FunctionParameterDescriptor(type, description);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionParameters SetRequiredParameter(string[] required)
|
||||||
|
{
|
||||||
|
this.required = required;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels.FunctionModels;
|
||||||
|
|
||||||
|
public class FunctionTool
|
||||||
|
{
|
||||||
|
public string type { get; set; } = "function";
|
||||||
|
public Dictionary<string, object> function { get; set; } = new();
|
||||||
|
|
||||||
|
public FunctionTool SetName(string name)
|
||||||
|
{
|
||||||
|
this.function["name"] = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionTool SetDescription(string desc)
|
||||||
|
{
|
||||||
|
this.function["description"] = desc;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FunctionTool SetParameters(FunctionParameters param)
|
||||||
|
{
|
||||||
|
this.function["parameters"] = param;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels;
|
||||||
|
|
||||||
|
public class ImageRequestBase
|
||||||
|
{
|
||||||
|
// "quality": quality,
|
||||||
|
// "response_format": response_format,
|
||||||
|
// "size": size,
|
||||||
|
// "style": style,
|
||||||
|
// "user": user,
|
||||||
|
// public string request_id { get; private set; }
|
||||||
|
public string model { get; private set; }
|
||||||
|
public string prompt { get; private set; }
|
||||||
|
// public int n { get; private set; }
|
||||||
|
|
||||||
|
// public ImageRequestBase SetRequestId(string requestId)
|
||||||
|
// {
|
||||||
|
// this.request_id = requestId;
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public ImageRequestBase SetModel(string model)
|
||||||
|
{
|
||||||
|
this.model = model;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public ImageRequestBase SetPrompt(string prompt)
|
||||||
|
{
|
||||||
|
this.prompt = prompt;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
// public ImageRequestBase SetN(int n)
|
||||||
|
// {
|
||||||
|
// this.n = n;
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels.ImageToTextModels;
|
||||||
|
|
||||||
|
|
||||||
|
public class ContentType
|
||||||
|
{
|
||||||
|
public string type { get; set; }
|
||||||
|
public string text { set; get; }
|
||||||
|
public ImageUrlType image_url { set; get; }
|
||||||
|
|
||||||
|
public ContentType setType(string type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentType setText(string text)
|
||||||
|
{
|
||||||
|
this.text = text;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContentType setImageUrl(string image_url)
|
||||||
|
{
|
||||||
|
this.image_url = new ImageUrlType(image_url);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels.ImageToTextModels;
|
||||||
|
|
||||||
|
|
||||||
|
public class ImageToTextMessageItem(string role) : MessageItem(role, null)
|
||||||
|
{
|
||||||
|
public ContentType[] content { get; set; } = new ContentType[2];
|
||||||
|
|
||||||
|
public ImageToTextMessageItem setText(string text)
|
||||||
|
{
|
||||||
|
this.content[0] = new ContentType().setType("text").setText(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageToTextMessageItem setImageUrl(string image_url)
|
||||||
|
{
|
||||||
|
this.content[1] = new ContentType().setType("Image_url").setImageUrl(image_url);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels.ImageToTextModels
|
||||||
|
{
|
||||||
|
public class ImageUrlType
|
||||||
|
{
|
||||||
|
public string url { get; set; }
|
||||||
|
|
||||||
|
public ImageUrlType(string url)
|
||||||
|
{
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels;
|
||||||
|
|
||||||
|
public class MessageItem
|
||||||
|
{
|
||||||
|
public string role { get; set; }
|
||||||
|
public string content { get; set; }
|
||||||
|
|
||||||
|
public MessageItem(string role, string content)
|
||||||
|
{
|
||||||
|
this.role = role;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MessageItem()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
using BotSharp.Plugin.MetaGLM.Models.RequestModels.FunctionModels;
|
||||||
|
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.RequestModels
|
||||||
|
{
|
||||||
|
public class TextRequestBase
|
||||||
|
{
|
||||||
|
public string request_id { get; private set; }
|
||||||
|
public string model { get; private set; }
|
||||||
|
public MessageItem[] messages { get; private set; }
|
||||||
|
public FunctionTool[] tools { get; private set; }
|
||||||
|
public string tool_choice { get; private set; }
|
||||||
|
public double top_p { get; private set; }
|
||||||
|
public double temperature { get; private set; }
|
||||||
|
|
||||||
|
public bool stream { get; set; }
|
||||||
|
|
||||||
|
public TextRequestBase()
|
||||||
|
{
|
||||||
|
this.stream = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextRequestBase SetRequestId(string requestId)
|
||||||
|
{
|
||||||
|
this.request_id = requestId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextRequestBase SetModel(string model)
|
||||||
|
{
|
||||||
|
this.model = model;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextRequestBase SetMessages(MessageItem[] messages)
|
||||||
|
{
|
||||||
|
this.messages = messages;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextRequestBase SetTools(FunctionTool[] tools)
|
||||||
|
{
|
||||||
|
this.tools = tools;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextRequestBase SetToolChoice(string toolChoice)
|
||||||
|
{
|
||||||
|
this.tool_choice = toolChoice;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextRequestBase SetTopP(double topP)
|
||||||
|
{
|
||||||
|
if (topP is <= 0.0 or >= 1.0)
|
||||||
|
{
|
||||||
|
topP = 0.1;
|
||||||
|
}
|
||||||
|
this.top_p = topP;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextRequestBase SetTemperature(double temperature)
|
||||||
|
{
|
||||||
|
if (temperature is <= 0.0 or >= 1.0)
|
||||||
|
{
|
||||||
|
temperature = 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.temperature = temperature;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels.EmbeddingModels;
|
||||||
|
|
||||||
|
public class EmbeddingDataItem
|
||||||
|
{
|
||||||
|
public int index { get; set; }
|
||||||
|
public string _object { get; set; }
|
||||||
|
public double[] embedding { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels.EmbeddingModels;
|
||||||
|
|
||||||
|
public class EmbeddingResponseBase
|
||||||
|
{
|
||||||
|
public string model { set; get; }
|
||||||
|
public string _object { set; get; }
|
||||||
|
public Dictionary<string, int> usage { set; get; }
|
||||||
|
public EmbeddingDataItem[] data { get; set; }
|
||||||
|
public Dictionary<string, string> error { get; set; }
|
||||||
|
|
||||||
|
public static EmbeddingResponseBase FromJson(string json)
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<EmbeddingResponseBase>(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels.ImageGenerationModels;
|
||||||
|
|
||||||
|
public class ImageResponseBase
|
||||||
|
{
|
||||||
|
public long created { get; set; }
|
||||||
|
public List<ImageResponseDataItem> data { get; set; }
|
||||||
|
public Dictionary<string, string> error { get; set; }
|
||||||
|
|
||||||
|
public static ImageResponseBase FromJson(string json)
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<ImageResponseBase>(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels.ImageGenerationModels;
|
||||||
|
|
||||||
|
public class ImageResponseDataItem
|
||||||
|
{
|
||||||
|
public string url { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels;
|
||||||
|
|
||||||
|
public class ResponseBase
|
||||||
|
{
|
||||||
|
public string id { get; set; }
|
||||||
|
public string request_id { get; set; }
|
||||||
|
public long created { get; set; }
|
||||||
|
public string model { get; set; }
|
||||||
|
public Dictionary<string, int> usage { get; set; }
|
||||||
|
public ResponseChoiceItem[] choices { get; set; }
|
||||||
|
public Dictionary<string, string> error { get; set; }
|
||||||
|
|
||||||
|
public static ResponseBase FromJson(string json)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonSerializer.Deserialize<ResponseBase>(json);
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels;
|
||||||
|
|
||||||
|
public class ResponseChoiceDelta
|
||||||
|
{
|
||||||
|
public string role { get; set; }
|
||||||
|
public string content { get; set; }
|
||||||
|
public ToolCallItem[] tool_calls { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels;
|
||||||
|
|
||||||
|
public class ResponseChoiceItem
|
||||||
|
{
|
||||||
|
public string finish_reason { get; set; }
|
||||||
|
public int index { get; set; }
|
||||||
|
public ResponseChoiceDelta message { get; set; }
|
||||||
|
public ResponseChoiceDelta delta { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels.ToolModels;
|
||||||
|
|
||||||
|
public class FunctionDescriptor
|
||||||
|
{
|
||||||
|
public string name { get; set; }
|
||||||
|
public string arguments { get; set; }
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Models.ResponseModels.ToolModels;
|
||||||
|
|
||||||
|
public class ToolCallItem
|
||||||
|
{
|
||||||
|
public string id { get; set; }
|
||||||
|
public FunctionDescriptor function { get; set; }
|
||||||
|
public int index { get; set; }
|
||||||
|
public string type { get; set; }
|
||||||
|
}
|
||||||
129
src/Plugins/BotSharp.Plugin.MetaGLM/Modules/Chat.cs
Normal file
129
src/Plugins/BotSharp.Plugin.MetaGLM/Modules/Chat.cs
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Modules;
|
||||||
|
|
||||||
|
//public enum ModelPortal
|
||||||
|
//{
|
||||||
|
// Regular,
|
||||||
|
// Character,
|
||||||
|
//}
|
||||||
|
|
||||||
|
public class Chat
|
||||||
|
{
|
||||||
|
private string _apiKey;
|
||||||
|
private string _baseAddress;
|
||||||
|
|
||||||
|
private static readonly int API_TOKEN_TTL_SECONDS = 60 * 5;
|
||||||
|
|
||||||
|
private static readonly HttpClient client = new();
|
||||||
|
|
||||||
|
//private static readonly Dictionary<ModelPortal, string> PORTAL_URLS = new()
|
||||||
|
//{
|
||||||
|
// { ModelPortal.Regular , "https://open.bigmodel.cn/api/paas/v4/chat/completions"},
|
||||||
|
//};
|
||||||
|
|
||||||
|
private static readonly JsonSerializerOptions JsonOptions = new ()
|
||||||
|
{
|
||||||
|
Converters =
|
||||||
|
{
|
||||||
|
new MessageItemConverter()
|
||||||
|
},
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
|
WriteIndented = true,
|
||||||
|
};
|
||||||
|
|
||||||
|
public Chat(string apiKey, string basicAddress = "https://open.bigmodel.cn/api/paas/v4/")
|
||||||
|
{
|
||||||
|
this._apiKey = apiKey;
|
||||||
|
this._baseAddress = basicAddress.TrimEnd('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
private async IAsyncEnumerable<string> CompletionBase(TextRequestBase textRequestBody,string apiKey)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(textRequestBody, JsonOptions);
|
||||||
|
var data = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
|
var api_key = AuthenticationUtils.GenerateToken(apiKey, API_TOKEN_TTL_SECONDS);
|
||||||
|
|
||||||
|
var request = new HttpRequestMessage
|
||||||
|
{
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
RequestUri = new Uri($"{_baseAddress}/chat/completions"),
|
||||||
|
Content = data,
|
||||||
|
Headers =
|
||||||
|
{
|
||||||
|
{ "Authorization", api_key }
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
|
||||||
|
var stream = await response.Content.ReadAsStreamAsync();
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
while ((bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
||||||
|
{
|
||||||
|
yield return Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<ResponseBase> Completion(TextRequestBase textRequestBody)
|
||||||
|
{
|
||||||
|
textRequestBody.stream = false;
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
await foreach (var str in CompletionBase(textRequestBody, _apiKey))
|
||||||
|
{
|
||||||
|
sb.Append(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseBase.FromJson(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public async IAsyncEnumerable<ResponseBase> Stream(TextRequestBase textRequestBody )
|
||||||
|
{
|
||||||
|
textRequestBody.stream = true;
|
||||||
|
var buffer = string.Empty;
|
||||||
|
await foreach (var chunk in CompletionBase(textRequestBody, _apiKey))
|
||||||
|
{
|
||||||
|
|
||||||
|
buffer += chunk;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
int startPos = buffer.IndexOf("data: ", StringComparison.Ordinal);
|
||||||
|
if (startPos == -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int endPos = buffer.IndexOf("\n\n", startPos, StringComparison.Ordinal);
|
||||||
|
|
||||||
|
if (endPos == -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
startPos += "data: ".Length;
|
||||||
|
|
||||||
|
string jsonString = buffer.Substring(startPos, endPos - startPos);
|
||||||
|
if (jsonString.Equals("[DONE]"))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = ResponseBase.FromJson(jsonString);
|
||||||
|
if (response != null)
|
||||||
|
{
|
||||||
|
yield return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = buffer.Substring(endPos + "\n\n".Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var finalResponse = ResponseBase.FromJson(buffer.Trim());
|
||||||
|
if (finalResponse != null)
|
||||||
|
{
|
||||||
|
yield return finalResponse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/Plugins/BotSharp.Plugin.MetaGLM/Modules/Embeddings.cs
Normal file
60
src/Plugins/BotSharp.Plugin.MetaGLM/Modules/Embeddings.cs
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Modules;
|
||||||
|
|
||||||
|
public class Embeddings
|
||||||
|
{
|
||||||
|
private string _apiKey;
|
||||||
|
private string _baseAddress;
|
||||||
|
private static readonly int API_TOKEN_TTL_SECONDS = 60 * 5;
|
||||||
|
static readonly HttpClient client = new();
|
||||||
|
|
||||||
|
public Embeddings(string apiKey, string basicAddress = "https://open.bigmodel.cn/api/paas/v4/")
|
||||||
|
{
|
||||||
|
this._apiKey = apiKey;
|
||||||
|
this._baseAddress = basicAddress.TrimEnd('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private IEnumerable<string> ProcessBase(EmbeddingRequestBase requestBody)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(requestBody);
|
||||||
|
// Console.WriteLine(JsonSerializer.Serialize(requestBody));
|
||||||
|
// Console.WriteLine("----1----");
|
||||||
|
// Console.WriteLine(json);
|
||||||
|
var data = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
|
var api_key = AuthenticationUtils.GenerateToken(_apiKey, API_TOKEN_TTL_SECONDS);
|
||||||
|
|
||||||
|
var request = new HttpRequestMessage
|
||||||
|
{
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
RequestUri = new Uri($"{_baseAddress}/embeddings"),
|
||||||
|
Content = data,
|
||||||
|
Headers =
|
||||||
|
{
|
||||||
|
{ "Authorization", api_key }
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
|
||||||
|
var stream = response.Content.ReadAsStreamAsync().Result;
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
|
||||||
|
{
|
||||||
|
yield return Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmbeddingResponseBase Process(EmbeddingRequestBase requestBody)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var str in ProcessBase(requestBody))
|
||||||
|
{
|
||||||
|
sb.Append(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return EmbeddingResponseBase.FromJson(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
55
src/Plugins/BotSharp.Plugin.MetaGLM/Modules/Images.cs
Normal file
55
src/Plugins/BotSharp.Plugin.MetaGLM/Modules/Images.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Modules;
|
||||||
|
|
||||||
|
public class Images
|
||||||
|
{
|
||||||
|
private string _apiKey;
|
||||||
|
private string _baseAddress;
|
||||||
|
private static readonly int API_TOKEN_TTL_SECONDS = 60 * 5;
|
||||||
|
static readonly HttpClient client = new HttpClient();
|
||||||
|
|
||||||
|
public Images(string apiKey, string basicAddress = "https://open.bigmodel.cn/api/paas/v4/")
|
||||||
|
{
|
||||||
|
this._apiKey = apiKey;
|
||||||
|
this._baseAddress = basicAddress.TrimEnd('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<string> GenerateBase(ImageRequestBase requestBody)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(requestBody);
|
||||||
|
var data = new StringContent(json, Encoding.UTF8, "application/json");
|
||||||
|
var api_key = AuthenticationUtils.GenerateToken(_apiKey, API_TOKEN_TTL_SECONDS);
|
||||||
|
|
||||||
|
var request = new HttpRequestMessage
|
||||||
|
{
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
RequestUri = new Uri($"{_baseAddress}images/generations"),
|
||||||
|
Content = data,
|
||||||
|
Headers =
|
||||||
|
{
|
||||||
|
{ "Authorization", api_key }
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var response = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
|
||||||
|
var stream = response.Content.ReadAsStreamAsync().Result;
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int bytesRead;
|
||||||
|
|
||||||
|
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0)
|
||||||
|
{
|
||||||
|
yield return Encoding.UTF8.GetString(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageResponseBase Generation(ImageRequestBase requestBody, string apiKey)
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (var str in GenerateBase(requestBody))
|
||||||
|
{
|
||||||
|
sb.Append(str);
|
||||||
|
}
|
||||||
|
return ImageResponseBase.FromJson(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Providers;
|
||||||
|
|
||||||
|
public class ChatCompletionProvider : IChatCompletion
|
||||||
|
{
|
||||||
|
public string Provider => "metaglm";
|
||||||
|
|
||||||
|
private readonly MetaGLMSettings _settings;
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly ILogger _logger;
|
||||||
|
private readonly MetaGLMClient metaGLMClient;
|
||||||
|
private string _model;
|
||||||
|
|
||||||
|
public ChatCompletionProvider(IServiceProvider services,
|
||||||
|
MetaGLMSettings settings,
|
||||||
|
MetaGLMClient client,
|
||||||
|
ILogger<ChatCompletionProvider> logger)
|
||||||
|
{
|
||||||
|
_services = services;
|
||||||
|
_settings = settings;
|
||||||
|
_logger = logger;
|
||||||
|
metaGLMClient = client;
|
||||||
|
_model = "glm-4";
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RoleDialogModel> GetChatCompletions(Agent agent, List<RoleDialogModel> conversations)
|
||||||
|
{
|
||||||
|
var contentHooks = _services.GetServices<IContentGeneratingHook>().ToList();
|
||||||
|
|
||||||
|
// Before chat completion hook
|
||||||
|
foreach (var hook in contentHooks)
|
||||||
|
{
|
||||||
|
await hook.BeforeGenerating(agent, conversations);
|
||||||
|
}
|
||||||
|
|
||||||
|
var dto = new TextRequestBase();
|
||||||
|
dto.SetRequestId(Guid.NewGuid().ToString());
|
||||||
|
dto.SetModel(_settings.ModelId);
|
||||||
|
dto.SetTemperature(_settings.Temperature);
|
||||||
|
dto.SetTopP(_settings.TopP);
|
||||||
|
|
||||||
|
var prompt = PrepareOptions(agent, conversations, dto);
|
||||||
|
|
||||||
|
var response = await metaGLMClient.Chat.Completion(dto);
|
||||||
|
RoleDialogModel? responseMessage = null;
|
||||||
|
if (response?.choices.FirstOrDefault()?.finish_reason == "stop")
|
||||||
|
{
|
||||||
|
responseMessage = new RoleDialogModel(AgentRole.Assistant, response?.choices.FirstOrDefault()?.message.content)
|
||||||
|
{
|
||||||
|
CurrentAgentId = agent.Id,
|
||||||
|
MessageId = conversations.Last().MessageId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response?.choices.FirstOrDefault()?.finish_reason == "tool_calls")
|
||||||
|
{
|
||||||
|
var toolcall = response.choices.FirstOrDefault()?.message.tool_calls.FirstOrDefault();
|
||||||
|
responseMessage = new RoleDialogModel(AgentRole.Function, JsonSerializer.Serialize(toolcall.function))
|
||||||
|
{
|
||||||
|
CurrentAgentId = agent.Id,
|
||||||
|
MessageId = conversations.Last().MessageId,
|
||||||
|
FunctionName = toolcall.function.name,
|
||||||
|
FunctionArgs = toolcall.function.arguments
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// After chat completion hook
|
||||||
|
foreach (var hook in contentHooks)
|
||||||
|
{
|
||||||
|
await hook.AfterGenerated(message: responseMessage, new TokenStatsModel
|
||||||
|
{
|
||||||
|
Prompt = prompt,
|
||||||
|
Provider = Provider,
|
||||||
|
Model = _model,
|
||||||
|
PromptCount = response.usage.GetValueOrDefault("prompt_tokens"),
|
||||||
|
CompletionCount = response.usage.GetValueOrDefault("completion_tokens")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string PrepareOptions(Agent agent, List<RoleDialogModel> conversations, TextRequestBase dto)
|
||||||
|
{
|
||||||
|
var agentService = _services.GetRequiredService<IAgentService>();
|
||||||
|
List<MessageItem> messages = new List<MessageItem>();
|
||||||
|
List<FunctionTool> toolcalls = new List<FunctionTool>();
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(agent.Instruction))
|
||||||
|
{
|
||||||
|
var instruction = agentService.RenderedInstruction(agent);
|
||||||
|
messages.Add(new MessageItem("system", instruction));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(agent.Knowledges))
|
||||||
|
{
|
||||||
|
messages.Add(new MessageItem("system", agent.Knowledges));
|
||||||
|
}
|
||||||
|
|
||||||
|
var samples = ProviderHelper.GetChatSamples(agent.Samples);
|
||||||
|
foreach (var message in samples)
|
||||||
|
{
|
||||||
|
messages.Add(message.Role == AgentRole.User ?
|
||||||
|
new MessageItem("user", message.Content) :
|
||||||
|
new MessageItem("assistant", message.Content));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var function in agent.Functions)
|
||||||
|
{
|
||||||
|
var functionTool = ConvertToFunctionTool(function);
|
||||||
|
toolcalls.Add(functionTool);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var message in conversations)
|
||||||
|
{
|
||||||
|
if (message.Role == "function")
|
||||||
|
{
|
||||||
|
//messages.Add(ChatMessage.FromUser($"function call result: {message.content}"));
|
||||||
|
}
|
||||||
|
else if (message.Role == "user")
|
||||||
|
{
|
||||||
|
var userMessage = new MessageItem("user",message.Content);
|
||||||
|
|
||||||
|
messages.Add(userMessage);
|
||||||
|
}
|
||||||
|
else if (message.Role == "assistant")
|
||||||
|
{
|
||||||
|
messages.Add(new MessageItem("assistant", message.Content));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toolcalls.Count > 0)
|
||||||
|
{
|
||||||
|
dto.SetTools(toolcalls.ToArray());
|
||||||
|
dto.SetToolChoice("auto");
|
||||||
|
}
|
||||||
|
dto.SetMessages(messages.ToArray());
|
||||||
|
|
||||||
|
var prompt = GetPrompt(messages, toolcalls);
|
||||||
|
|
||||||
|
//var state = _services.GetRequiredService<IConversationStateService>();
|
||||||
|
//var temperature = float.Parse(state.GetState("temperature", "0.0"));
|
||||||
|
//var samplingFactor = float.Parse(state.GetState("sampling_factor", "0.0"));
|
||||||
|
//dto.SetTemperature(temperature);
|
||||||
|
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FunctionTool ConvertToFunctionTool(FunctionDef def)
|
||||||
|
{
|
||||||
|
var functionTool = new FunctionTool()
|
||||||
|
{
|
||||||
|
type = "function"
|
||||||
|
|
||||||
|
}
|
||||||
|
.SetName(def.Name)
|
||||||
|
.SetDescription(def.Description);
|
||||||
|
|
||||||
|
var funcParameter = new FunctionParameters() { type = def.Parameters.Type };
|
||||||
|
funcParameter.SetRequiredParameter(def.Parameters.Required.ToArray());
|
||||||
|
|
||||||
|
var parameters = def.Parameters;
|
||||||
|
var funcParamsProperties = parameters.Properties;
|
||||||
|
|
||||||
|
if (funcParamsProperties != null)
|
||||||
|
{
|
||||||
|
var props = funcParamsProperties.RootElement.EnumerateObject();
|
||||||
|
while (props.MoveNext())
|
||||||
|
{
|
||||||
|
var prop = props.Current;
|
||||||
|
var name = prop.Name;
|
||||||
|
string typestr = prop.Value.GetProperty("type").GetRawText();
|
||||||
|
if (!string.IsNullOrEmpty(typestr))
|
||||||
|
{
|
||||||
|
ParameterType parameterType;
|
||||||
|
if (Enum.TryParse(typestr, out parameterType))
|
||||||
|
{
|
||||||
|
funcParameter.AddParameter(name, parameterType, prop.Value.GetProperty("description").GetRawText());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
functionTool.SetParameters(funcParameter);
|
||||||
|
return functionTool;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetPrompt(List<MessageItem> messages, List<FunctionTool> functions)
|
||||||
|
{
|
||||||
|
var prompt = string.Empty;
|
||||||
|
|
||||||
|
if (messages.Count > 0)
|
||||||
|
{
|
||||||
|
// System instruction
|
||||||
|
var verbose = string.Join("\r\n", messages
|
||||||
|
.Where(x => x.role == AgentRole.System)
|
||||||
|
.Select(x =>
|
||||||
|
{
|
||||||
|
return $"{x.role}: {x.content}";
|
||||||
|
}));
|
||||||
|
prompt += $"{verbose}\r\n";
|
||||||
|
|
||||||
|
verbose = string.Join("\r\n", messages
|
||||||
|
.Where(x => x.role != AgentRole.System).Select(x =>
|
||||||
|
{
|
||||||
|
return
|
||||||
|
$"{x.role}: {x.content}";
|
||||||
|
|
||||||
|
}));
|
||||||
|
prompt += $"\r\n{verbose}\r\n";
|
||||||
|
}
|
||||||
|
if(functions.Count > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Task<bool> GetChatCompletionsAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived, Func<RoleDialogModel, Task> onFunctionExecuting)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<bool> GetChatCompletionsStreamingAsync(Agent agent, List<RoleDialogModel> conversations, Func<RoleDialogModel, Task> onMessageReceived)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetModelName(string model)
|
||||||
|
{
|
||||||
|
_model = model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Providers;
|
||||||
|
|
||||||
|
internal class ProviderHelper
|
||||||
|
{
|
||||||
|
public static string GetClient(string model, IServiceProvider services)
|
||||||
|
{
|
||||||
|
var settingsService = services.GetRequiredService<ILlmProviderService>();
|
||||||
|
var settings = settingsService.GetSetting("metaglm", model);
|
||||||
|
return settings.ApiKey;
|
||||||
|
}
|
||||||
|
public static List<RoleDialogModel> GetChatSamples(List<string> lines)
|
||||||
|
{
|
||||||
|
var samples = new List<RoleDialogModel>();
|
||||||
|
|
||||||
|
for (int i = 0; i < lines.Count; i++)
|
||||||
|
{
|
||||||
|
var line = lines[i];
|
||||||
|
if (string.IsNullOrEmpty(line.Trim()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var role = line.Substring(0, line.IndexOf(' ') - 1).Trim();
|
||||||
|
var content = line.Substring(line.IndexOf(' ') + 1).Trim();
|
||||||
|
|
||||||
|
// comments
|
||||||
|
if (role == "##")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
samples.Add(new RoleDialogModel(role, content));
|
||||||
|
}
|
||||||
|
|
||||||
|
return samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
namespace BotSharp.Plugin.MetaGLM.Settings;
|
||||||
|
|
||||||
|
public class MetaGLMSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// In the new mechanism, the API Key issued by the platform contains both “user identifier id” and “signature key secret” in the format of {id}.{secret}.
|
||||||
|
/// </summary>
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
|
||||||
|
public string BaseAddress { get; set; } = "https://open.bigmodel.cn/api/paas/v4/";
|
||||||
|
|
||||||
|
public string ModelId { get; set; }
|
||||||
|
|
||||||
|
public double Temperature { get; set; }
|
||||||
|
|
||||||
|
public double TopP { get; set; }
|
||||||
|
}
|
||||||
31
src/Plugins/BotSharp.Plugin.MetaGLM/Using.cs
Normal file
31
src/Plugins/BotSharp.Plugin.MetaGLM/Using.cs
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
global using BotSharp.Abstraction.Agents;
|
||||||
|
global using BotSharp.Abstraction.Agents.Enums;
|
||||||
|
global using BotSharp.Abstraction.Agents.Models;
|
||||||
|
global using BotSharp.Abstraction.Conversations.Models;
|
||||||
|
global using BotSharp.Abstraction.Functions.Models;
|
||||||
|
global using BotSharp.Abstraction.Loggers;
|
||||||
|
global using BotSharp.Abstraction.MLTasks;
|
||||||
|
global using BotSharp.Abstraction.Plugins;
|
||||||
|
global using BotSharp.Abstraction.Settings;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Models.RequestModels;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Models.RequestModels.FunctionModels;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Models.RequestModels.ImageToTextModels;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Models.ResponseModels;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Models.ResponseModels.EmbeddingModels;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Models.ResponseModels.ImageGenerationModels;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Models.ResponseModels.ToolModels;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Providers;
|
||||||
|
global using BotSharp.Plugin.MetaGLM.Settings;
|
||||||
|
global using Microsoft.Extensions.Configuration;
|
||||||
|
global using Microsoft.Extensions.DependencyInjection;
|
||||||
|
global using Microsoft.Extensions.Logging;
|
||||||
|
global using Microsoft.IdentityModel.Tokens;
|
||||||
|
global using System;
|
||||||
|
global using System.Collections.Generic;
|
||||||
|
global using System.IdentityModel.Tokens.Jwt;
|
||||||
|
global using System.Linq;
|
||||||
|
global using System.Net.Http;
|
||||||
|
global using System.Text;
|
||||||
|
global using System.Text.Json;
|
||||||
|
global using System.Text.Json.Serialization;
|
||||||
|
global using System.Threading.Tasks;
|
||||||
|
|
@ -27,6 +27,9 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
|
<ProjectReference Include="..\..\tests\BotSharp.Plugin.PizzaBot\BotSharp.Plugin.PizzaBot.csproj" />
|
||||||
|
<ProjectReference Include="..\Plugins\BotSharp.Plugin.Dashboard\BotSharp.Plugin.Dashboard.csproj" />
|
||||||
|
<ProjectReference Include="..\Plugins\BotSharp.Plugin.MetaGLM\BotSharp.Plugin.MetaGLM.csproj" />
|
||||||
|
<ProjectReference Include="..\Plugins\BotSharp.Plugin.SparkDesk\BotSharp.Plugin.SparkDesk.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="$(SolutionName)==BotSharp">
|
<ItemGroup Condition="$(SolutionName)==BotSharp">
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,17 @@
|
||||||
"CompletionCost": 0.002
|
"CompletionCost": 0.002
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Provider": "metaglm",
|
||||||
|
"Models": [
|
||||||
|
{
|
||||||
|
"Name": "chatglm3_6b",
|
||||||
|
"Type": "chat",
|
||||||
|
"PromptCost": 0.0015,
|
||||||
|
"CompletionCost": 0.002
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
@ -239,6 +250,13 @@
|
||||||
"ApiSecret": "",
|
"ApiSecret": "",
|
||||||
"ModelVersion": "V3_5"
|
"ModelVersion": "V3_5"
|
||||||
},
|
},
|
||||||
|
"MetaGLM": {
|
||||||
|
"ApiKey": "6b6c8b3fca3e5da21d633e350980744d.938gruOqrK4BDqW8",
|
||||||
|
"BaseAddress": "http://localhost:8100/v1/",
|
||||||
|
"ModelId": "chatglm3_6b",
|
||||||
|
"Temperature": 0.7,
|
||||||
|
"TopP": 0.7
|
||||||
|
},
|
||||||
|
|
||||||
"GoogleApi": {
|
"GoogleApi": {
|
||||||
"ApiKey": "",
|
"ApiKey": "",
|
||||||
|
|
@ -273,7 +291,8 @@
|
||||||
"BotSharp.Plugin.PizzaBot",
|
"BotSharp.Plugin.PizzaBot",
|
||||||
"BotSharp.Plugin.WebDriver",
|
"BotSharp.Plugin.WebDriver",
|
||||||
"BotSharp.Plugin.LLamaSharp",
|
"BotSharp.Plugin.LLamaSharp",
|
||||||
"BotSharp.Plugin.SparkDesk"
|
"BotSharp.Plugin.SparkDesk",
|
||||||
|
"BotSharp.Plugin.MetaGLM"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue