增强 Markdown 渲染和 AI 交互功能
- 修改 `MarkdownWpfRenderer.RenderHtmlBlock` 方法,支持 `<think>` 标签并使用 `Expander` 控件展示内容。 - 更新 `AiHelper` 类,添加新的 API_KEY 注释。 - 调整 `PromptUtil.UsePrompt` 方法的注释,增加思考过程的要求。 - 新增 `StringEmptyToBoolConverter` 类,用于处理字符串空状态。 - 在 `MainWindow.xaml` 中注释掉部分 `SideMenu` 内容。 - 在 `AiMessageControll.xaml` 中集成 `StringEmptyToBoolConverter`,优化内容显示逻辑。 - 修改 `ImportExcelPage.xaml` 的文本绑定属性。 - 更新 `ImportViewModel.cs` 中 `AiHelper` 的实例化方式和变量声明,提升代码清晰度。 - 更新 `TEST_AI_CONTENT`,添加 `<think>` 标签示例。
This commit is contained in:
parent
78d65a6aff
commit
8f42b5e5a7
|
|
@ -362,9 +362,19 @@ public class MarkdownWpfRenderer
|
|||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return new FrameworkElement();
|
||||
var text = htmlBlock.Lines.ToString();
|
||||
if (text.StartsWith("<think>"))
|
||||
{
|
||||
text = text.Replace("<think>", "").Replace("</think>", "");
|
||||
}
|
||||
var htmlText = new SelectableTextBlock();
|
||||
htmlText.Text = htmlBlock.Lines.ToString();
|
||||
return htmlText;
|
||||
htmlText.Text = text;
|
||||
var expander = new Expander();
|
||||
var header = new StackPanel();
|
||||
header.Children.Add(new ProgressBar() { IsIndeterminate = true,Width = 30 });
|
||||
expander.Header = header;
|
||||
expander.Content = htmlText;
|
||||
return expander;
|
||||
|
||||
}
|
||||
public FrameworkElement RenderMathBlock(MathBlock mathBlock, CancellationToken cancellationToken)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@ class AiHelper
|
|||
/// 火山引擎
|
||||
/// </summary>
|
||||
private const string API_KEY = "58e5c6fd-a5da-400e-b889-715febce478f";
|
||||
|
||||
/// <summary>
|
||||
/// 硅基流动
|
||||
/// </summary>
|
||||
//private const string API_KEY = "sk-anocoxlcvabejwwzzfsozibmrhzygyedjxdbjpmzfwauwtnx";
|
||||
//private const string API_ENDPOINT = "https://api.siliconflow.cn/";
|
||||
private const string API_ENDPOINT = "https://ark.cn-beijing.volces.com/api/v3/";
|
||||
|
||||
private readonly IChatClient _client;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ using System.Linq;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ExcelHelper.AI
|
||||
namespace ExcelHelper.AI;
|
||||
|
||||
class PromptUtil
|
||||
{
|
||||
class PromptUtil
|
||||
{
|
||||
public static string UsePrompt(string msg,string excelPrompt)
|
||||
{
|
||||
return $@"
|
||||
|
|
@ -16,9 +16,10 @@ namespace ExcelHelper.AI
|
|||
你在回复用户的问题时,需要遵守以下规则:
|
||||
1. 优先保证答案的准确性,其次是简洁明了。
|
||||
2. 需要保证你的回答是有逻辑性的,不要让用户感到困惑。
|
||||
3. 可以例举2~3个例子来帮助用户更好地理解你的回答。
|
||||
3. 可以例举1到2个例子来帮助用户更好地理解你的回答中的Excel公式。
|
||||
4. 一定要保证文档格式的正确性,避免出现无法显示的内容。
|
||||
5. 尽量使用比较简短与易懂的公式来回答用户的问题,避免用户无法理解。
|
||||
6. 你不能跳过你的思考过程。
|
||||
|
||||
现在的时间是{DateTime.Now}。
|
||||
|
||||
|
|
@ -27,5 +28,4 @@ namespace ExcelHelper.AI
|
|||
用户的问题是:{msg}
|
||||
";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using System.Windows;
|
||||
|
||||
namespace ExcelHelper.Converter;
|
||||
|
||||
public class StringEmptyToBoolConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
var str = value as string;
|
||||
var isEmpty = string.IsNullOrEmpty(str);
|
||||
|
||||
// 如果参数是"invert",则反转结果
|
||||
if (parameter != null && parameter.ToString() == "invert")
|
||||
{
|
||||
isEmpty = !isEmpty;
|
||||
}
|
||||
|
||||
return isEmpty ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
|
@ -15,16 +15,16 @@
|
|||
mc:Ignorable="d">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" MinWidth="100" />
|
||||
<!--<ColumnDefinition Width="Auto" MinWidth="100" />-->
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<hc:SideMenu Grid.Column="0" AutoSelect="True">
|
||||
<!--<hc:SideMenu Grid.Column="0" AutoSelect="True">
|
||||
<hc:SideMenuItem
|
||||
Command="{Binding SideMenuSelectCommand}"
|
||||
CommandParameter="ImportExcelPage"
|
||||
Header="导入"
|
||||
IsSelected="True" />
|
||||
</hc:SideMenu>
|
||||
</hc:SideMenu>-->
|
||||
<Frame
|
||||
x:Name="MainFrame"
|
||||
Grid.Column="1"
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@
|
|||
|
||||
<!-- 布尔值到可见性转换器 -->
|
||||
<BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
|
||||
<!-- 字符串空判断转换器 -->
|
||||
<local1:StringEmptyToBoolConverter x:Key="StringEmptyToBoolConverter" />
|
||||
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
|
|
@ -52,17 +55,51 @@
|
|||
Padding="5"
|
||||
HorizontalAlignment="{Binding IsUser, Converter={StaticResource BoolToAlignmentConverter}}"
|
||||
Background="{Binding IsUser, Converter={StaticResource BoolToColorConverter}}"
|
||||
CornerRadius="10">
|
||||
CornerRadius="3">
|
||||
<StackPanel>
|
||||
<md:MarkdownViewer x:Name="MdViewer" Content="{Binding Content}" />
|
||||
<!-- 当Content为空时显示进度条 -->
|
||||
<ProgressBar
|
||||
Height="5"
|
||||
Margin="5"
|
||||
IsIndeterminate="True"
|
||||
Visibility="{Binding Content, Converter={StaticResource StringEmptyToBoolConverter}}" />
|
||||
|
||||
<!-- 当Content不为空时显示内容 -->
|
||||
<TabControl
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Visibility="{Binding Content, Converter={StaticResource StringEmptyToBoolConverter}, ConverterParameter=invert}">
|
||||
<TabItem Background="Transparent" Header="文档">
|
||||
<md:MarkdownViewer
|
||||
x:Name="MdViewer"
|
||||
Margin="10"
|
||||
Padding="10"
|
||||
Content="{Binding Content}" />
|
||||
</TabItem>
|
||||
<TabItem Background="Transparent" Header="文本">
|
||||
<TextBox
|
||||
Margin="5"
|
||||
Padding="5"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0"
|
||||
Text="{Binding Content}" />
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,5,5,0"
|
||||
FontSize="10"
|
||||
Foreground="#99000000"
|
||||
Text="{Binding Content.Length, StringFormat='字数: {0}'}" />
|
||||
<TextBlock
|
||||
Margin="0,5,0,0"
|
||||
HorizontalAlignment="Right"
|
||||
FontSize="10"
|
||||
Foreground="#99000000"
|
||||
Text="{Binding Timestamp, StringFormat='{}{0:HH:mm}'}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
|
|
@ -101,8 +138,12 @@
|
|||
Height="40"
|
||||
Margin="5,0,0,0"
|
||||
Padding="15,0"
|
||||
Background="#000"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="0"
|
||||
Click="SendButton_Click"
|
||||
Content="发送"
|
||||
Foreground="White"
|
||||
IsEnabled="{Binding IsWaiting, Converter={StaticResource InverseBoolConverter}, UpdateSourceTrigger=PropertyChanged, ElementName=userControl}" />
|
||||
</Grid>
|
||||
|
||||
|
|
@ -117,7 +158,7 @@
|
|||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock VerticalAlignment="Center" Text="AI正在思考中..." />
|
||||
<TextBlock VerticalAlignment="Center" Text="正在思考中..." />
|
||||
<ProgressBar
|
||||
Width="100"
|
||||
Height="15"
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@
|
|||
Padding="5"
|
||||
VerticalContentAlignment="Top"
|
||||
AcceptsReturn="True"
|
||||
Text="{Binding PromptString}"
|
||||
Text="{Binding ExcelPromptString}"
|
||||
TextWrapping="Wrap"
|
||||
VerticalScrollBarVisibility="Auto" />
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace ExcelHelper.Views.ViewModels;
|
|||
public partial class ImportViewModel : ObservableRecipient, IViewModel
|
||||
{
|
||||
|
||||
private AiHelper AiHelper = new AiHelper("deepseek-v3-241226", false);
|
||||
private readonly AiHelper AiHelper = new("deepseek-r1-250120", false);
|
||||
|
||||
public Task FileDrop(string[] files)
|
||||
{
|
||||
|
|
@ -46,7 +46,11 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
|
|||
IsLoading = false;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 读取excel
|
||||
/// </summary>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="isReload"></param>
|
||||
public async void ReadForExcel(string path, bool isReload = false)
|
||||
{
|
||||
IsLoading = true;
|
||||
|
|
@ -135,7 +139,7 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
|
|||
ExcelColumns.Add(column);
|
||||
}
|
||||
}
|
||||
int columnsSeq = 0;
|
||||
var columnsSeq = 0;
|
||||
foreach (var item in ExcelColumns)
|
||||
{
|
||||
TableColumns.Add(new TableColumnModel
|
||||
|
|
@ -308,143 +312,9 @@ public partial class ImportViewModel : ObservableRecipient, IViewModel
|
|||
|
||||
|
||||
private const string TEST_AI_CONTENT = @"
|
||||
这篇文章包含markdown语法基本的内容, 目的是放在自己的博客园上, 通过开发者控制台快速选中,
|
||||
从而自定义自己博客园markdown样式.当然本文也可以当markdown语法学习之用.
|
||||
|
||||
在markdown里强制换行是在末尾添加2个空格+1个回车.
|
||||
在markdown里可以使用 \ 对特殊符号进行转义.
|
||||
|
||||
# 1. 标题
|
||||
|
||||
**语法**
|
||||
```
|
||||
# This is an <h1> tag
|
||||
## This is an <h2> tag
|
||||
### This is an <h3> tag
|
||||
#### This is an <h4> tag
|
||||
```
|
||||
|
||||
**实例**
|
||||
|
||||
# This is an h1 tag
|
||||
## This is an h2 tag
|
||||
### This is an h3 tag
|
||||
#### This is an h4 tag
|
||||
|
||||
# 2. 强调和斜体
|
||||
|
||||
**语法**
|
||||
```
|
||||
*This text will be italic*
|
||||
_This will also be italic_
|
||||
|
||||
**This text will be bold**
|
||||
__This will also be bold__
|
||||
```
|
||||
(个人不喜欢2个下划线中间包含的内容被斜体, 会和网址冲突, 我会在自定义博客园样式中去除这个样式.)
|
||||
|
||||
**实例**
|
||||
|
||||
*This text will be italic*
|
||||
_This will also be italic_
|
||||
|
||||
**This text will be bold**
|
||||
__This will also be bold__
|
||||
|
||||
# 3. 有序列表和无序列表
|
||||
|
||||
**语法**
|
||||
```
|
||||
* Item 1
|
||||
* Item 2
|
||||
* Item 3
|
||||
|
||||
1. Item 1
|
||||
2. Item 2
|
||||
3. Item 3
|
||||
```
|
||||
|
||||
**实例**
|
||||
* Item 1
|
||||
* Item 2
|
||||
* Item 3
|
||||
|
||||
1. Item 1
|
||||
2. Item 2
|
||||
3. Item 3
|
||||
|
||||
# 4. 图片
|
||||
|
||||
**语法**
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
**实例**
|
||||

|
||||
|
||||
# 5. 超链接
|
||||
|
||||
**语法**
|
||||
```
|
||||
[link-name](link-url)
|
||||
```
|
||||
|
||||
**实例**
|
||||
|
||||
[阿胜4K](http://www.cnblogs.com/asheng2016/)
|
||||
|
||||
# 6. 引用
|
||||
|
||||
**语法**
|
||||
```
|
||||
> 引用本意是引用别人的话之类
|
||||
> 但我个人喜欢把引用当成""注意""使用
|
||||
```
|
||||
|
||||
**实例**
|
||||
|
||||
> If you please draw me a sheep!
|
||||
> 不想当将军的士兵, 不是好士兵.
|
||||
|
||||
# 7. 单行代码
|
||||
|
||||
**语法**
|
||||
```
|
||||
`This is an inline code.`
|
||||
```
|
||||
|
||||
**实例**
|
||||
|
||||
`同样的单行代码, 我经常用来显示特殊名词`
|
||||
|
||||
# 8. 多行代码
|
||||
|
||||
**语法**
|
||||
````
|
||||
```javascript
|
||||
for (var i=0; i<100; i++) {
|
||||
console.log(""hello world"" + i);
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
**实例**
|
||||
|
||||
```js
|
||||
for (var i=0; i<100; i++) {
|
||||
console.log(""hello world"" + i);
|
||||
}
|
||||
```
|
||||
|
||||
也可以通过缩进来显示代码, 下面是示例:
|
||||
|
||||
console.loe(""Hello_World"");
|
||||
|
||||
# 参考链接
|
||||
|
||||
https://guides.github.com/features/mastering-markdown/
|
||||
https://help.github.com/articles/basic-writing-and-formatting-syntax/
|
||||
<think>
|
||||
1231231
|
||||
</think>
|
||||
";
|
||||
#region Props
|
||||
[ObservableProperty]
|
||||
|
|
|
|||
Loading…
Reference in New Issue