mirror of
https://github.com/AIDotNet/AntSK.git
synced 2026-02-21 00:54:21 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b25e429687 | ||
|
|
a3f87bf123 | ||
|
|
2cab253c4a | ||
|
|
ed119f02e2 | ||
|
|
f178fc16e9 | ||
|
|
e4b2071689 | ||
|
|
146df7ed1d | ||
|
|
7e8db0a3f8 | ||
|
|
e098922219 | ||
|
|
16ca024c22 | ||
|
|
a886e9dfb3 | ||
|
|
5d6114c9ec | ||
|
|
e3b2e1f434 | ||
|
|
6145347d9b | ||
|
|
49e694cbdc | ||
|
|
f860229993 |
@@ -13,14 +13,14 @@
|
||||
<PackageReference Include="LLamaSharp.semantic-kernel" Version="0.10.0" />
|
||||
<PackageReference Include="MarkdownSharp" Version="2.0.5" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.137" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.143" />
|
||||
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.118" />
|
||||
|
||||
<PackageReference Include="Microsoft.SemanticKernel" Version="1.4.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Core" Version="1.4.0" />
|
||||
<PackageReference Include="Microsoft.SemanticKernel.Plugins.Core" Version="1.4.0-alpha" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.29.240219.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.29.240219.2" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.Core" Version="0.30.240227.1" />
|
||||
<PackageReference Include="Microsoft.KernelMemory.MemoryDb.Postgres" Version="0.30.240227.1" />
|
||||
|
||||
<PackageReference Include="LLamaSharp" Version="0.10.0" />
|
||||
<PackageReference Include="LLamaSharp.Backend.Cpu" Version="0.10.0" />
|
||||
|
||||
@@ -57,6 +57,11 @@
|
||||
<param name="result"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.MessageInfo.IsSend">
|
||||
<summary>
|
||||
发送是true 接收是false
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Model.PageList`1.PageIndex">
|
||||
<summary>
|
||||
当前页,从1开始
|
||||
@@ -424,6 +429,11 @@
|
||||
备注
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:AntSK.Domain.Repositories.Users.MenuRole">
|
||||
<summary>
|
||||
菜单权限
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:AntSK.Domain.Utils.ConvertUtils.IsNull(System.Object)">
|
||||
<summary>
|
||||
判断是否为空,为空返回true
|
||||
|
||||
@@ -9,9 +9,13 @@ namespace AntSK.Domain.Model
|
||||
public class MessageInfo
|
||||
{
|
||||
public string ID { get; set; } = "";
|
||||
public string Questions { get; set; } = "";
|
||||
public string Answers { get; set; } = "";
|
||||
public string Context { get; set; } = "";
|
||||
public string HtmlAnswers { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 发送是true 接收是false
|
||||
/// </summary>
|
||||
public bool IsSend { get; set; } = false;
|
||||
public DateTime CreateTime { get; set; }
|
||||
|
||||
}
|
||||
|
||||
@@ -37,6 +37,11 @@ namespace AntSK.Domain.Repositories
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string Describe { get; set; }
|
||||
/// <summary>
|
||||
/// 菜单权限
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string MenuRole { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Buffers.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace AntSK.Utils
|
||||
namespace AntSK.Domain.Utils
|
||||
{
|
||||
public class LongToDateTimeConverter : JsonConverter<DateTime>
|
||||
{
|
||||
@@ -35,10 +35,14 @@ namespace AntSK.Domain.Utils
|
||||
{
|
||||
// 这里是你要修改的 URL
|
||||
Scheme = $"{xieyi}://{hostnew}/",
|
||||
Host = host,
|
||||
Port=port.ConvertToInt32(),
|
||||
Host = host,
|
||||
Path = route + "v1/chat/completions",
|
||||
};
|
||||
if (port.ConvertToInt32() != 0)
|
||||
{
|
||||
uriBuilder.Port = port.ConvertToInt32();
|
||||
}
|
||||
|
||||
request.RequestUri = uriBuilder.Uri;
|
||||
|
||||
break;
|
||||
@@ -48,9 +52,12 @@ namespace AntSK.Domain.Utils
|
||||
// 这里是你要修改的 URL
|
||||
Scheme = $"{xieyi}://{host}/",
|
||||
Host = host,
|
||||
Port = port.ConvertToInt32(),
|
||||
Path = route + "v1/embeddings",
|
||||
};
|
||||
if (port.ConvertToInt32() != 0)
|
||||
{
|
||||
uriBuilder.Port = port.ConvertToInt32();
|
||||
}
|
||||
request.RequestUri = uriBuilder.Uri;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
@namespace AntSK
|
||||
@using System.Security.Claims
|
||||
@using AntSK.Services.Auth
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using AntSK.Domain.Options
|
||||
@using AntSK.Domain.Repositories
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<AntDesign.ProLayout.BasicLayout
|
||||
@@ -21,11 +26,28 @@
|
||||
private MenuDataItem[] _menuData = { };
|
||||
|
||||
[Inject] public HttpClient HttpClient { get; set; }
|
||||
[Inject] public AuthenticationStateProvider AuthenticationStateProvider { get; set; }
|
||||
[Inject] protected IUsers_Repositories _users_Repositories { get; set; }
|
||||
private ClaimsPrincipal context => ((AntSKAuthProvider)AuthenticationStateProvider).GetCurrentUser();
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
_menuData = await HttpClient.GetFromJsonAsync<MenuDataItem[]>("data/menu.json");
|
||||
//菜单权限控制
|
||||
var menuList = await HttpClient.GetFromJsonAsync<MenuDataItem[]>("data/menu.json");
|
||||
if ((bool)context?.Identity.IsAuthenticated)
|
||||
{
|
||||
if (context.Identity.Name == LoginOption.User)
|
||||
{
|
||||
_menuData = menuList;
|
||||
}
|
||||
else
|
||||
{
|
||||
var userMenuList = _users_Repositories.GetFirst(p => p.No == context.Identity.Name).MenuRole.Split(",").ToList();
|
||||
//非管理员用户不允许操作系统设置
|
||||
_menuData = menuList.Where(p => p.Key != "setting" && userMenuList.Contains(p.Key)).ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace AntSK.Models.OpenAPI
|
||||
public long created { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class ChoicesModel
|
||||
{
|
||||
public string finish_reason { get; set; } = "stop";
|
||||
@@ -46,4 +47,21 @@ namespace AntSK.Models.OpenAPI
|
||||
|
||||
public List<float> embedding { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class OpenAIStreamResult
|
||||
{
|
||||
public string id { get; set; } = Guid.NewGuid().ToString();
|
||||
[JsonProperty("object")]
|
||||
public string obj { get; set; } = "chat.completion";
|
||||
public List<StreamChoicesModel> choices { get; set; }
|
||||
public long created { get; set; }
|
||||
}
|
||||
public class StreamChoicesModel
|
||||
{
|
||||
public int index { get; set; } = 0;
|
||||
|
||||
public OpenAIMessage delta { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using AntSK.Utils;
|
||||
using AntSK.Domain.Utils;
|
||||
|
||||
namespace AntSK.Models
|
||||
{
|
||||
|
||||
@@ -23,28 +23,36 @@
|
||||
</TitleTemplate>
|
||||
<Body>
|
||||
<div id="scrollDiv" style="height: 530px; overflow-y: auto; overflow-x: hidden;">
|
||||
<GridRow Gutter="(8, 8)">
|
||||
<Virtualize Items="@(MessageList.OrderByDescending(o => o.CreateTime).ToList())" Context="item">
|
||||
<GridCol Span="24">
|
||||
<Card Size="small">
|
||||
<TitleTemplate>
|
||||
<Text Strong><Icon Type="bulb" /> @(item.Questions)</Text>
|
||||
</TitleTemplate>
|
||||
<Extra>
|
||||
<Space>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnCopyAsync(item))"><Icon Type="copy" /></a>
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnClearAsync(item.ID))"><Icon Type="rest" /></a>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</Extra>
|
||||
<Body>
|
||||
@((MarkupString)(item.HtmlAnswers))
|
||||
</Body>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<GridRow Gutter="(8, 8)" Style="margin:0">
|
||||
<Virtualize Items="@(MessageList.OrderBy(o => o.CreateTime).ToList())" Context="item">
|
||||
@if (item.IsSend)
|
||||
{
|
||||
<GridRow Style="width:100%">
|
||||
<GridCol Span="23">
|
||||
<div class="chat-bubble sent">
|
||||
@(item.Context)
|
||||
@* <span class="timestamp">@item.CreateTime</span> *@
|
||||
</div>
|
||||
</GridCol>
|
||||
<GridCol Span="1">
|
||||
<Image Width="100%" Style="margin-top:10px;" Src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" />
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
}
|
||||
else
|
||||
{
|
||||
<GridRow Style="width:100%">
|
||||
<GridCol Span="1">
|
||||
<Image Width="100%" Style="margin-top:10px;" Src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg" />
|
||||
</GridCol>
|
||||
<GridCol Span="23">
|
||||
<div class="chat-bubble received">
|
||||
@((MarkupString)(item.HtmlAnswers))
|
||||
@* <span class="timestamp">@item.CreateTime</span> *@
|
||||
</div>
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
}
|
||||
</Virtualize>
|
||||
</GridRow>
|
||||
</div>
|
||||
@@ -67,8 +75,8 @@
|
||||
|
||||
</Extra>
|
||||
<Body>
|
||||
<AntList Bordered DataSource="@RelevantSources">
|
||||
<ChildContent Context="item">
|
||||
<AntList Bordered DataSource="@RelevantSources" Style="padding:10px;">
|
||||
<ChildContent Context="item" >
|
||||
<span> <b>@item.SourceName </b> 相似度:<Text Mark> @item.Relevance</Text></span>
|
||||
<Body>
|
||||
@((MarkupString)(@item.Text))
|
||||
@@ -80,7 +88,65 @@
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
|
||||
<style>
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.chat-container {
|
||||
width: 350px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.chat-bubble {
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
margin-bottom: 0;
|
||||
border-radius: 5px;
|
||||
max-width: 70%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.received {
|
||||
background-color: #f0f0f0;
|
||||
align-self: flex-start;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.sent {
|
||||
background-color: #daf8cb;
|
||||
align-self: flex-end;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
display: block;
|
||||
font-size: 0.75em;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.received .timestamp {
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.sent .timestamp {
|
||||
text-align: left;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
@code {
|
||||
|
||||
}
|
||||
|
||||
@@ -64,6 +64,15 @@ namespace AntSK.Pages.ChatPage
|
||||
return;
|
||||
}
|
||||
|
||||
MessageList.Add(new MessageInfo()
|
||||
{
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Context = _messageInput,
|
||||
CreateTime = DateTime.Now,
|
||||
IsSend = true
|
||||
});
|
||||
|
||||
|
||||
Sendding = true;
|
||||
await SendAsync(_messageInput);
|
||||
_messageInput = "";
|
||||
@@ -74,7 +83,7 @@ namespace AntSK.Pages.ChatPage
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
_messageInput = item.Questions;
|
||||
_messageInput = item.Context;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -140,8 +149,7 @@ namespace AntSK.Pages.ChatPage
|
||||
var info1 = new MessageInfo()
|
||||
{
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Questions = questions,
|
||||
Answers = answers,
|
||||
Context = answers,
|
||||
HtmlAnswers = htmlAnswers,
|
||||
CreateTime = DateTime.Now,
|
||||
};
|
||||
@@ -193,9 +201,8 @@ namespace AntSK.Pages.ChatPage
|
||||
{
|
||||
info = new MessageInfo();
|
||||
info.ID = Guid.NewGuid().ToString();
|
||||
info.Questions = questions;
|
||||
info.Answers = content.Content!;
|
||||
info.HtmlAnswers = content.Content!;
|
||||
info.Context = content?.Content?.ConvertToString();
|
||||
info.HtmlAnswers = content?.Content?.ConvertToString();
|
||||
info.CreateTime = DateTime.Now;
|
||||
|
||||
MessageList.Add(info);
|
||||
@@ -208,7 +215,11 @@ namespace AntSK.Pages.ChatPage
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
//全部处理完后再处理一次Markdown
|
||||
info!.HtmlAnswers = markdown.Transform(info.HtmlAnswers);
|
||||
if (info.IsNotNull())
|
||||
{
|
||||
info!.HtmlAnswers = markdown.Transform(info.HtmlAnswers);
|
||||
}
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
@@ -219,18 +230,31 @@ namespace AntSK.Pages.ChatPage
|
||||
/// <returns></returns>
|
||||
private async Task<string> HistorySummarize(string questions)
|
||||
{
|
||||
StringBuilder history = new StringBuilder();
|
||||
foreach (var item in MessageList)
|
||||
if (MessageList.Count > 1)
|
||||
{
|
||||
history.Append($"user:{item.Questions}{Environment.NewLine}");
|
||||
history.Append($"assistant:{item.Answers}{Environment.NewLine}");
|
||||
}
|
||||
StringBuilder history = new StringBuilder();
|
||||
foreach (var item in MessageList)
|
||||
{
|
||||
if (item.IsSend)
|
||||
{
|
||||
history.Append($"user:{item.Context}{Environment.NewLine}");
|
||||
}
|
||||
else
|
||||
{
|
||||
history.Append($"assistant:{item.Context}{Environment.NewLine}");
|
||||
}
|
||||
}
|
||||
|
||||
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
|
||||
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
|
||||
string his = summary.GetValue<string>();
|
||||
var msg = $"历史对话:{his}{Environment.NewLine} 用户问题:{Environment.NewLine}{questions}"; ;
|
||||
return msg;
|
||||
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
|
||||
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
|
||||
string his = summary.GetValue<string>();
|
||||
var msg = $"历史对话:{his}{Environment.NewLine} 用户问题:{Environment.NewLine}{questions}"; ;
|
||||
return msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
return questions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,27 +8,36 @@
|
||||
<div id="chat" style="display:flex; flex-direction:column; height:100%; overflow-x:hidden;">
|
||||
<PageHeader Class="site-page-header" Title="@app.Name" Subtitle="@app.Describe" />
|
||||
<div id="scrollDiv" style="flex:1; width:100%; overflow-y:auto; overflow-x:hidden;padding:10px;">
|
||||
<Virtualize Items="@(MessageList.OrderByDescending(o => o.CreateTime).ToList())" Context="item">
|
||||
<GridCol Span="24">
|
||||
<Card>
|
||||
<TitleTemplate>
|
||||
<Text Strong><Icon Type="bulb" />@(item.Questions)</Text>
|
||||
</TitleTemplate>
|
||||
<Extra>
|
||||
<Space>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnCopyAsync(item))"><Icon Type="copy" /></a>
|
||||
</SpaceItem>
|
||||
<SpaceItem>
|
||||
<a style="color: gray;" @onclick="@(() => OnClearAsync(item.ID))"><Icon Type="rest" /></a>
|
||||
</SpaceItem>
|
||||
</Space>
|
||||
</Extra>
|
||||
<Body>
|
||||
@((MarkupString)(item.HtmlAnswers))
|
||||
</Body>
|
||||
</Card>
|
||||
</GridCol>
|
||||
<Virtualize Items="@(MessageList.OrderBy(o => o.CreateTime).ToList())" Context="item">
|
||||
@if (item.IsSend)
|
||||
{
|
||||
<GridRow>
|
||||
<GridCol Span="23">
|
||||
<div class="chat-bubble sent">
|
||||
@(item.Context)
|
||||
@* <span class="timestamp">@item.CreateTime</span> *@
|
||||
</div>
|
||||
</GridCol>
|
||||
<GridCol Span="1">
|
||||
<Image Width="100%" Style="margin-top:10px;" Src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg" />
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
}
|
||||
else
|
||||
{
|
||||
<GridRow>
|
||||
<GridCol Span="1">
|
||||
<Image Width="100%" Style="margin-top:10px;" Src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg" />
|
||||
</GridCol>
|
||||
<GridCol Span="23">
|
||||
<div class="chat-bubble received">
|
||||
@((MarkupString)(item.HtmlAnswers))
|
||||
@* <span class="timestamp">@item.CreateTime</span> *@
|
||||
</div>
|
||||
</GridCol>
|
||||
</GridRow>
|
||||
}
|
||||
|
||||
</Virtualize>
|
||||
</div>
|
||||
<div style="flex-shrink:0;margin:10px;">
|
||||
@@ -40,6 +49,66 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.chat-container {
|
||||
width: 350px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.chat-bubble {
|
||||
padding: 10px;
|
||||
margin: 10px;
|
||||
margin-bottom: 0;
|
||||
border-radius: 5px;
|
||||
max-width: 70%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.received {
|
||||
background-color: #f0f0f0;
|
||||
align-self: flex-start;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.sent {
|
||||
background-color: #daf8cb;
|
||||
align-self: flex-end;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
display: block;
|
||||
font-size: 0.75em;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.received .timestamp {
|
||||
text-align: right;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.sent .timestamp {
|
||||
text-align: left;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ using Newtonsoft.Json;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Text;
|
||||
using AntSK.Domain.Utils;
|
||||
|
||||
namespace AntSK.Pages.ChatPage
|
||||
{
|
||||
@@ -56,6 +57,14 @@ namespace AntSK.Pages.ChatPage
|
||||
return;
|
||||
}
|
||||
|
||||
MessageList.Add(new MessageInfo() {
|
||||
ID=Guid.NewGuid().ToString(),
|
||||
Context=_messageInput,
|
||||
CreateTime=DateTime.Now,
|
||||
IsSend=true
|
||||
});
|
||||
|
||||
|
||||
Sendding = true;
|
||||
await SendAsync(_messageInput);
|
||||
_messageInput = "";
|
||||
@@ -66,7 +75,7 @@ namespace AntSK.Pages.ChatPage
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
_messageInput = item.Questions;
|
||||
_messageInput = item.Context;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -132,8 +141,7 @@ namespace AntSK.Pages.ChatPage
|
||||
var info1 = new MessageInfo()
|
||||
{
|
||||
ID = Guid.NewGuid().ToString(),
|
||||
Questions = questions,
|
||||
Answers = answers,
|
||||
Context = answers,
|
||||
HtmlAnswers = htmlAnswers,
|
||||
CreateTime = DateTime.Now,
|
||||
};
|
||||
@@ -170,9 +178,8 @@ namespace AntSK.Pages.ChatPage
|
||||
{
|
||||
info = new MessageInfo();
|
||||
info.ID = Guid.NewGuid().ToString();
|
||||
info.Questions = questions;
|
||||
info.Answers = content.Content!;
|
||||
info.HtmlAnswers = content.Content!;
|
||||
info.Context = content?.Content?.ConvertToString();
|
||||
info.HtmlAnswers = content?.Content?.ConvertToString();
|
||||
info.CreateTime = DateTime.Now;
|
||||
|
||||
MessageList.Add(info);
|
||||
@@ -196,18 +203,31 @@ namespace AntSK.Pages.ChatPage
|
||||
/// <returns></returns>
|
||||
private async Task<string> HistorySummarize(string questions)
|
||||
{
|
||||
StringBuilder history = new StringBuilder();
|
||||
foreach (var item in MessageList)
|
||||
if (MessageList.Count > 1)
|
||||
{
|
||||
history.Append($"user:{item.Questions}{Environment.NewLine}");
|
||||
history.Append($"assistant:{item.Answers}{Environment.NewLine}");
|
||||
}
|
||||
StringBuilder history = new StringBuilder();
|
||||
foreach (var item in MessageList)
|
||||
{
|
||||
if (item.IsSend)
|
||||
{
|
||||
history.Append($"user:{item.Context}{Environment.NewLine}");
|
||||
}
|
||||
else
|
||||
{
|
||||
history.Append($"assistant:{item.Context}{Environment.NewLine}");
|
||||
}
|
||||
}
|
||||
|
||||
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
|
||||
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
|
||||
string his = summary.GetValue<string>();
|
||||
var msg = $"历史对话:{his}{Environment.NewLine} 用户问题:{Environment.NewLine}{questions}"; ;
|
||||
return msg;
|
||||
KernelFunction sunFun = _kernel.Plugins.GetFunction("ConversationSummaryPlugin", "SummarizeConversation");
|
||||
var summary = await _kernel.InvokeAsync(sunFun, new() { ["input"] = $"内容是:{history.ToString()} {Environment.NewLine} 请注意用中文总结" });
|
||||
string his = summary.GetValue<string>();
|
||||
var msg = $"历史对话:{his}{Environment.NewLine} 用户问题:{Environment.NewLine}{questions}"; ;
|
||||
return msg;
|
||||
}
|
||||
else
|
||||
{
|
||||
return questions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
@using AntSK.Models
|
||||
@page "/setting/user/add"
|
||||
@page "/setting/user/add/{UserId}"
|
||||
@inject IMessageService _message
|
||||
@using AntSK.Services.Auth
|
||||
@inherits AuthComponentBase
|
||||
|
||||
@@ -26,14 +25,31 @@
|
||||
<FormItem Label="用户备注" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Input Placeholder="请输入用户备注" @bind-Value="@context.Describe" />
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label="菜单权限" LabelCol="LayoutModel._formItemLayout.LabelCol" WrapperCol="LayoutModel._formItemLayout.WrapperCol">
|
||||
<Select Mode="multiple"
|
||||
@bind-Values="_menuKeys"
|
||||
Placeholder="选择菜单权限"
|
||||
TItemValue="string"
|
||||
TItem="string"
|
||||
Size="@AntSizeLDSType.Default">
|
||||
<SelectOptions>
|
||||
@foreach (var menu in menuList)
|
||||
{
|
||||
<SelectOption TItem="string" TItemValue="string" Value="@menu.Key" Label="@menu.Name" />
|
||||
}
|
||||
</SelectOptions>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem Label=" " Style="margin-top:32px" WrapperCol="LayoutModel._submitFormLayout.WrapperCol">
|
||||
<Button Type="primary" HtmlType="submit">
|
||||
<Button Type="primary" OnClick="HandleSubmit">
|
||||
保存
|
||||
</Button>
|
||||
<Button OnClick="Back">
|
||||
返回
|
||||
</Button>
|
||||
</FormItem>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Card>
|
||||
</ChildContent>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AntDesign;
|
||||
using AntDesign.ProLayout;
|
||||
using AntSK.Domain.Options;
|
||||
using AntSK.Domain.Repositories;
|
||||
using AntSK.Domain.Utils;
|
||||
@@ -12,14 +13,15 @@ namespace AntSK.Pages.Setting.User
|
||||
{
|
||||
[Parameter]
|
||||
public string UserId { get; set; }
|
||||
[Inject]
|
||||
protected IUsers_Repositories _users_Repositories { get; set; }
|
||||
[Inject]
|
||||
protected MessageService? Message { get; set; }
|
||||
[Inject] protected IUsers_Repositories _users_Repositories { get; set; }
|
||||
[Inject] protected MessageService? Message { get; set; }
|
||||
[Inject] public HttpClient HttpClient { get; set; }
|
||||
|
||||
private Users _userModel = new Users();
|
||||
private string _password = "";
|
||||
IEnumerable<string> _menuKeys;
|
||||
|
||||
private List<MenuDataItem> menuList = new List<MenuDataItem>();
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
@@ -28,10 +30,13 @@ namespace AntSK.Pages.Setting.User
|
||||
_userModel= _users_Repositories.GetFirst(p => p.Id == UserId);
|
||||
_password= _userModel.Password;
|
||||
}
|
||||
menuList = (await HttpClient.GetFromJsonAsync<MenuDataItem[]>("data/menu.json")).ToList().Where(p=>p.Key!= "setting").ToList();
|
||||
_menuKeys= _userModel.MenuRole?.Split(",");
|
||||
}
|
||||
|
||||
private void HandleSubmit()
|
||||
{
|
||||
_userModel.MenuRole = string.Join(",", _menuKeys);
|
||||
if (string.IsNullOrEmpty(UserId))
|
||||
{
|
||||
//新增
|
||||
@@ -47,7 +52,6 @@ namespace AntSK.Pages.Setting.User
|
||||
_ = Message.Error("工号已存在!", 2);
|
||||
return;
|
||||
}
|
||||
|
||||
_userModel.Password=PasswordUtil.HashPassword(_userModel.Password);
|
||||
_users_Repositories.Insert(_userModel);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ void InitSK(WebApplicationBuilder builder)
|
||||
//Kernel Memory
|
||||
var searchClientConfig = new SearchClientConfig
|
||||
{
|
||||
MaxAskPromptSize = 8000,
|
||||
MaxAskPromptSize = 2048,
|
||||
MaxMatchesCount = 3,
|
||||
AnswerTokens = 1000,
|
||||
EmptyAnswer = "知识库未搜索到相关内容"
|
||||
@@ -158,12 +158,12 @@ void InitSK(WebApplicationBuilder builder)
|
||||
.WithSimpleFileStorage(new SimpleFileStorageConfig { StorageType = FileSystemTypes.Volatile, Directory = "_files" })
|
||||
.WithSearchClientConfig(searchClientConfig)
|
||||
//如果用本地模型需要设置token小一点。
|
||||
//.WithCustomTextPartitioningOptions(new Microsoft.KernelMemory.Configuration.TextPartitioningOptions
|
||||
//{
|
||||
// MaxTokensPerLine=99,
|
||||
// MaxTokensPerParagraph=299,
|
||||
// OverlappingTokens=47
|
||||
//})
|
||||
.WithCustomTextPartitioningOptions(new Microsoft.KernelMemory.Configuration.TextPartitioningOptions
|
||||
{
|
||||
MaxTokensPerLine = 99,
|
||||
MaxTokensPerParagraph = 299,
|
||||
OverlappingTokens = 47
|
||||
})
|
||||
.WithOpenAITextGeneration(new OpenAIConfig()
|
||||
{
|
||||
APIKey = OpenAIOption.Key,
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace AntSK.Services.LLamaSharp
|
||||
{
|
||||
var @params = new ModelParams(LLamaSharpOption.Chat)
|
||||
{
|
||||
ContextSize = 512,
|
||||
ContextSize = 2048,
|
||||
};
|
||||
|
||||
// todo: share weights from a central service
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace AntSK.Services.LLamaSharp
|
||||
{
|
||||
float[] embeddings =await _embedder.GetEmbeddings(text);
|
||||
//PG只有1536维
|
||||
return embeddings.ToList().Take(1536).ToList();
|
||||
return embeddings.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,12 +35,17 @@ namespace AntSK.Services.LLamaSharp
|
||||
|
||||
public async Task ChatStream(OpenAIModel model, HttpContext HttpContext)
|
||||
{
|
||||
HttpContext.Response.ContentType = "text/event-stream";
|
||||
HttpContext.Response.Headers.Add("Content-Type", "text/event-stream");
|
||||
OpenAIStreamResult result = new OpenAIStreamResult();
|
||||
result.created = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result.choices = new List<StreamChoicesModel>() { new StreamChoicesModel() { delta = new OpenAIMessage() { role = "assistant" } } };
|
||||
string questions = model.messages.LastOrDefault().content;
|
||||
|
||||
await foreach (var r in _lLamaChatService.ChatStreamAsync(questions))
|
||||
{
|
||||
Console.Write(r);
|
||||
await HttpContext.Response.WriteAsync("data:" + r + "\n\n");
|
||||
result.choices[0].delta.content = r.ConvertToString();
|
||||
string message = $"data: {JsonConvert.SerializeObject(result)}\n\n";
|
||||
await HttpContext.Response.WriteAsync(message, Encoding.UTF8);
|
||||
await HttpContext.Response.Body.FlushAsync();
|
||||
}
|
||||
await HttpContext.Response.WriteAsync("data: [DONE]");
|
||||
|
||||
@@ -39,9 +39,8 @@ namespace AntSK.Services.OpenApi
|
||||
{
|
||||
public async Task Chat(OpenAIModel model,string sk, HttpContext HttpContext)
|
||||
{
|
||||
OpenAIResult result = new OpenAIResult();
|
||||
result.created= DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result.choices=new List<ChoicesModel>() { new ChoicesModel() { message=new OpenAIMessage() { role= "assistant" } } };
|
||||
|
||||
|
||||
Apps app = _apps_Repositories.GetFirst(p => p.SecretKey == sk);
|
||||
|
||||
if (app.IsNotNull())
|
||||
@@ -53,26 +52,42 @@ namespace AntSK.Services.OpenApi
|
||||
//普通会话
|
||||
if (model.stream)
|
||||
{
|
||||
await SendChatStream( HttpContext, result, app, msg);
|
||||
OpenAIStreamResult result1 = new OpenAIStreamResult();
|
||||
result1.created = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result1.choices = new List<StreamChoicesModel>() { new StreamChoicesModel() { delta = new OpenAIMessage() { role = "assistant" } } };
|
||||
await SendChatStream( HttpContext, result1, app, msg);
|
||||
HttpContext.Response.ContentType = "application/json";
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result1));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
result.choices[0].message.content = await SendChat(msg, app);
|
||||
OpenAIResult result2 = new OpenAIResult();
|
||||
result2.created = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result2.choices = new List<ChoicesModel>() { new ChoicesModel() { message = new OpenAIMessage() { role = "assistant" } } };
|
||||
result2.choices[0].message.content = await SendChat(msg, app);
|
||||
HttpContext.Response.ContentType = "application/json";
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result2));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
}
|
||||
break;
|
||||
case "kms":
|
||||
//知识库问答
|
||||
result.choices[0].message.content = await SendKms( msg, app);
|
||||
OpenAIResult result3 = new OpenAIResult();
|
||||
result3.created = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
result3.choices = new List<ChoicesModel>() { new ChoicesModel() { message = new OpenAIMessage() { role = "assistant" } } };
|
||||
result3.choices[0].message.content = await SendKms( msg, app);
|
||||
HttpContext.Response.ContentType = "application/json";
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result3));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
HttpContext.Response.ContentType = "application/json";
|
||||
await HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(result));
|
||||
await HttpContext.Response.CompleteAsync();
|
||||
|
||||
}
|
||||
|
||||
private async Task SendChatStream( HttpContext HttpContext, OpenAIResult result, Apps app, string msg)
|
||||
private async Task SendChatStream( HttpContext HttpContext, OpenAIStreamResult result, Apps app, string msg)
|
||||
{
|
||||
HttpContext.Response.Headers.Add("Content-Type", "text/event-stream");
|
||||
|
||||
@@ -91,7 +106,7 @@ namespace AntSK.Services.OpenApi
|
||||
|
||||
await foreach (var content in chatResult)
|
||||
{
|
||||
result.choices[0].message.content = content.Content.ConvertToString();
|
||||
result.choices[0].delta.content = content.Content.ConvertToString();
|
||||
string message = $"data: {JsonConvert.SerializeObject(result)}\n\n";
|
||||
await HttpContext.Response.WriteAsync(message, Encoding.UTF8);
|
||||
await HttpContext.Response.Body.FlushAsync();
|
||||
|
||||
Reference in New Issue
Block a user