5 changed files with 437 additions and 149 deletions
-
67src/Shentun.Peis.Application.Contracts/AIMessages/DeepModel.cs
-
109src/Shentun.Peis.Application/AIMessages/AIMessageAppService.cs
-
210src/Shentun.Peis.Domain/TextFormatter.cs
-
188src/Shentun.Peis.HttpApi.Host/Controllers/AiMessageWsController.cs
-
12src/Shentun.Peis.HttpApi.Host/PeisHttpApiHostModule.cs
@ -0,0 +1,67 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
|
|||
namespace Shentun.Peis.AIMessages |
|||
{ |
|||
//如果好用,请收藏地址,帮忙分享。
|
|||
public class Delta |
|||
{ |
|||
/// <summary>
|
|||
/// 保持
|
|||
/// </summary>
|
|||
public string content { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public string reasoning_content { get; set; } |
|||
} |
|||
|
|||
public class ChoicesItem |
|||
{ |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public int index { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public Delta delta { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public string logprobs { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public string finish_reason { get; set; } |
|||
} |
|||
|
|||
public class Root |
|||
{ |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public string id { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public string @object { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public int created { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public string model { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public string system_fingerprint { get; set; } |
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
public List<ChoicesItem> choices { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,210 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Shentun.Peis |
|||
{ |
|||
public class TextFormatter |
|||
{ |
|||
public static string FormatStreamingText(string text, int consoleWidth = 80) |
|||
{ |
|||
if (string.IsNullOrEmpty(text)) |
|||
return text; |
|||
|
|||
// 1. 处理Markdown风格的格式
|
|||
text = ProcessMarkdown(text); |
|||
|
|||
// 2. 自动换行
|
|||
text = WordWrap(text, consoleWidth); |
|||
|
|||
// 3. 处理代码块
|
|||
text = ProcessCodeBlocks(text); |
|||
|
|||
// 4. 处理列表
|
|||
text = ProcessLists(text); |
|||
|
|||
//text = text.Replace("\n\n","").Replace("\n","");
|
|||
|
|||
return text; |
|||
} |
|||
|
|||
private static string ProcessMarkdown(string text) |
|||
{ |
|||
// 处理粗体 - Markdown: **text** 或 __text__ → HTML: <strong>text</strong>
|
|||
text = System.Text.RegularExpressions.Regex.Replace( |
|||
text, @"\*\*(.*?)\*\*", "<strong>$1</strong>"); |
|||
|
|||
text = System.Text.RegularExpressions.Regex.Replace( |
|||
text, @"__(.*?)__", "<strong>$1</strong>"); |
|||
|
|||
// 处理斜体 - Markdown: *text* 或 _text_ → HTML: <em>text</em>
|
|||
text = System.Text.RegularExpressions.Regex.Replace( |
|||
text, @"\*(.*?)\*", "<em>$1</em>"); |
|||
|
|||
text = System.Text.RegularExpressions.Regex.Replace( |
|||
text, @"_(.*?)_", "<em>$1</em>"); |
|||
|
|||
// 处理标题
|
|||
text = System.Text.RegularExpressions.Regex.Replace( |
|||
text, @"^### (.*)$", "<h3>$1</h3>", |
|||
System.Text.RegularExpressions.RegexOptions.Multiline); |
|||
|
|||
text = System.Text.RegularExpressions.Regex.Replace( |
|||
text, @"^## (.*)$", "<h2>$1</h2>", |
|||
System.Text.RegularExpressions.RegexOptions.Multiline); |
|||
|
|||
text = System.Text.RegularExpressions.Regex.Replace( |
|||
text, @"^# (.*)$", "<h1>$1</h1>", |
|||
System.Text.RegularExpressions.RegexOptions.Multiline); |
|||
|
|||
return text; |
|||
} |
|||
|
|||
private static string WordWrap(string text, int maxWidth) |
|||
{ |
|||
var lines = text.Split("\n", StringSplitOptions.None); |
|||
var result = new List<string>(); |
|||
|
|||
foreach (var line in lines) |
|||
{ |
|||
if (line.Length <= maxWidth) |
|||
{ |
|||
result.Add(line); |
|||
continue; |
|||
} |
|||
|
|||
var words = line.Split(' '); |
|||
var currentLine = new StringBuilder(); |
|||
|
|||
foreach (var word in words) |
|||
{ |
|||
if (currentLine.Length + word.Length + 1 > maxWidth) |
|||
{ |
|||
result.Add(currentLine.ToString()); |
|||
currentLine.Clear(); |
|||
} |
|||
|
|||
if (currentLine.Length > 0) |
|||
currentLine.Append(' '); |
|||
|
|||
currentLine.Append(word); |
|||
} |
|||
|
|||
if (currentLine.Length > 0) |
|||
result.Add(currentLine.ToString()); |
|||
} |
|||
|
|||
return string.Join("<br>", result); |
|||
} |
|||
|
|||
private static string ProcessCodeBlocks(string text) |
|||
{ |
|||
// 简单的代码块处理
|
|||
var lines = text.Split('\n'); |
|||
var result = new List<string>(); |
|||
bool inCodeBlock = false; |
|||
|
|||
foreach (var line in lines) |
|||
{ |
|||
if (line.Trim().StartsWith("```")) |
|||
{ |
|||
inCodeBlock = !inCodeBlock; |
|||
result.Add(new string('=', 60)); |
|||
continue; |
|||
} |
|||
|
|||
if (inCodeBlock) |
|||
{ |
|||
result.Add($" {line}"); |
|||
} |
|||
else |
|||
{ |
|||
result.Add(line); |
|||
} |
|||
} |
|||
|
|||
return string.Join("\n", result); |
|||
} |
|||
|
|||
private static string ProcessLists(string text) |
|||
{ |
|||
var lines = text.Split('\n'); |
|||
var result = new List<string>(); |
|||
|
|||
bool inUnorderedList = false; |
|||
bool inOrderedList = false; |
|||
var orderedListStart = 0; |
|||
|
|||
foreach (var line in lines) |
|||
{ |
|||
// 处理无序列表项 (*, -, +)
|
|||
var unorderedMatch = System.Text.RegularExpressions.Regex.Match(line, @"^[\*\-+]\s+(.+)"); |
|||
if (unorderedMatch.Success) |
|||
{ |
|||
if (!inUnorderedList) |
|||
{ |
|||
// 开始无序列表
|
|||
if (inOrderedList) |
|||
{ |
|||
result.Add("</ol>"); |
|||
inOrderedList = false; |
|||
} |
|||
result.Add("<ul>"); |
|||
inUnorderedList = true; |
|||
} |
|||
result.Add($"<li>{unorderedMatch.Groups[1].Value}</li>"); |
|||
continue; |
|||
} |
|||
|
|||
// 处理有序列表项 (1., 2., 等)
|
|||
var orderedMatch = System.Text.RegularExpressions.Regex.Match(line, @"^(\d+)\.\s+(.+)"); |
|||
if (orderedMatch.Success) |
|||
{ |
|||
if (!inOrderedList) |
|||
{ |
|||
// 开始有序列表
|
|||
if (inUnorderedList) |
|||
{ |
|||
result.Add("</ul>"); |
|||
inUnorderedList = false; |
|||
} |
|||
result.Add("<ol>"); |
|||
inOrderedList = true; |
|||
orderedListStart = int.Parse(orderedMatch.Groups[1].Value); |
|||
} |
|||
result.Add($"<li>{orderedMatch.Groups[2].Value}</li>"); |
|||
continue; |
|||
} |
|||
|
|||
// 如果不是列表项,关闭之前的列表
|
|||
if (inUnorderedList) |
|||
{ |
|||
result.Add("</ul>"); |
|||
inUnorderedList = false; |
|||
} |
|||
if (inOrderedList) |
|||
{ |
|||
result.Add("</ol>"); |
|||
inOrderedList = false; |
|||
} |
|||
|
|||
// 添加普通行
|
|||
result.Add(line); |
|||
} |
|||
|
|||
// 处理末尾未关闭的列表
|
|||
if (inUnorderedList) |
|||
{ |
|||
result.Add("</ul>"); |
|||
} |
|||
if (inOrderedList) |
|||
{ |
|||
result.Add("</ol>"); |
|||
} |
|||
|
|||
return string.Join("\n", result); |
|||
} |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue