增强 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:
lihanbo 2025-02-28 16:34:55 +08:00
parent 78d65a6aff
commit 8f42b5e5a7
8 changed files with 121 additions and 162 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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. 12Excel公式
4.
5. 使
6.
{DateTime.Now}
@ -27,5 +28,4 @@ namespace ExcelHelper.AI
{msg}
";
}
}
}

View File

@ -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();
}
}

View File

@ -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"

View File

@ -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"

View File

@ -114,7 +114,7 @@
Padding="5"
VerticalContentAlignment="Top"
AcceptsReturn="True"
Text="{Binding PromptString}"
Text="{Binding ExcelPromptString}"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />
</Grid>

View File

@ -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.
****
```
![img-name](img-url)
```
****
![logo](https://news.cnblogs.com/images/logo.gif)
# 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]