Files
VectorDBDemo/VoiceToFunctionDemo/Program.cs
2025-10-17 02:46:25 +08:00

211 lines
9.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace VoiceToFunction
{
class Program
{
// 初始化函数库(明确参数类型要求)
private static List<FunctionInfo> functionLibrary = new List<FunctionInfo>
{
// 1. 乘积函数参数两个double数组
new FunctionInfo
{
Name = "PRODUCT",
Description = "计算多列对应行的乘积",
Synonyms = new List<string> { "计算乘积", "相乘", "乘积" },
MinParams = 2,
ParamTypes = new List<Type> { typeof(double[]), typeof(double[]) },
Execute = (args) =>
{
double[] col1 = (double[])args[0];
double[] col2 = (double[])args[1];
return col1.Zip(col2, (a, b) => a * b).ToArray();
}
},
// 2. 筛选函数(参数:用户列表 + 筛选条件)
new FunctionInfo
{
Name = "FILTER",
Description = "筛选满足条件的数据",
Synonyms = new List<string> { "筛选", "过滤", "选出" },
MinParams = 2,
ParamTypes = new List<Type> { typeof(List<User>), typeof(Func<User, bool>) },
Execute = (args) =>
{
List<User> users = (List<User>)args[0];
Func<User, bool> condition = (Func<User, bool>)args[1];
return users.Where(condition).ToList();
}
},
// 3. 统计函数(参数:销售额数组 + 统计条件)
new FunctionInfo
{
Name = "COUNTIF",
Description = "统计满足条件的记录数",
Synonyms = new List<string> { "统计数量", "计数", "数一下" },
MinParams = 2,
ParamTypes = new List<Type> { typeof(double[]), typeof(Func<double, bool>) },
Execute = (args) =>
{
double[] sales = (double[])args[0];
Func<double, bool> condition = (Func<double, bool>)args[1];
return sales.Count(condition);
}
}
};
static void Main(string[] args)
{
// 测试带复杂参数的语音指令
TestVoiceCommand("计算C列和D列的乘积C列是[1,3,5]D列是[2,4,6]");
TestVoiceCommand("计算A列和B列的乘积A列是[1,3,5]B列是[2,4,6]");
TestVoiceCommand("筛选出年龄大于28且姓名包含'李'的用户");
TestVoiceCommand("统计销售额在5000到20000之间的订单数数据是[3000, 8000, 15000, 25000]");
Console.ReadKey();
}
static void TestVoiceCommand(string voiceText)
{
Console.WriteLine($"=== 语音指令:{voiceText} ===");
ParsedResult result = ParseVoiceCommand(voiceText);
if (!string.IsNullOrEmpty(result.Error))
{
Console.WriteLine($"错误:{result.Error}");
return;
}
// 校验参数类型是否匹配函数要求
var function = functionLibrary.First(f => f.Name == result.FunctionName);
bool paramTypeMatch = function.ParamTypes.Zip(result.ParamTypes,
(required, actual) => required.Name == actual).All(match => match);
if (!paramTypeMatch)
{
Console.WriteLine("错误:参数类型与函数要求不匹配");
return;
}
// 执行函数并输出结果
var executionResult = function.Execute(result.Parameters);
Console.WriteLine($"匹配函数:{result.FunctionName}");
Console.WriteLine($"执行结果:{GetResultString(executionResult)}");
Console.WriteLine();
}
// 核心:解析语音文本,提取函数+参数(强化入参处理)
static ParsedResult ParseVoiceCommand(string text)
{
var result = new ParsedResult();
// 1. 匹配函数(同之前逻辑)
FunctionInfo matchedFunction = functionLibrary.FirstOrDefault(
func => func.Synonyms.Any(syn => text.Contains(syn)));
if (matchedFunction == null)
{
result.Error = "未找到匹配的函数";
return result;
}
result.FunctionName = matchedFunction.Name;
// 2. 提取并解析参数(根据函数类型动态处理)
try
{
switch (matchedFunction.Name)
{
case "PRODUCT":
// 提取列数据(支持显式输入如"[1,3,5]"
var colDataMatches = Regex.Matches(text, @"\[([\d, ]+)\]")
.Cast<Match>()
.Select(m => m.Groups[1].Value.Split(',').Select(double.Parse).ToArray())
.ToList();
if (colDataMatches.Count < 2)
{
result.Error = "PRODUCT需要至少两列数据格式如'[1,2,3]'";
return result;
}
result.Parameters = new object[] { colDataMatches[0], colDataMatches[1] };
result.ParamTypes = new[] { "Double[]", "Double[]" };
break;
case "FILTER":
// 提取年龄条件(如"大于28")和姓名条件(如"包含'李'"
int ageThreshold = 0;
string nameKeyword = null;
var ageMatch = Regex.Match(text, @"年龄(大于|小于|等于)(\d+)");
if (ageMatch.Success)
{
string op = ageMatch.Groups[1].Value;
ageThreshold = int.Parse(ageMatch.Groups[2].Value);
}
var nameMatch = Regex.Match(text, @"姓名包含'([^']+)'");
if (nameMatch.Success)
{
nameKeyword = nameMatch.Groups[1].Value;
}
// 组合多条件筛选器
Func<User, bool> condition = u =>
(ageMatch.Success ? (ageMatch.Groups[1].Value == "大于" ? u.Age > ageThreshold : u.Age < ageThreshold) : true) &&
(nameMatch.Success ? u.Name.Contains(nameKeyword) : true);
// 模拟用户数据(实际应从数据源获取)
var users = new List<User>
{
new User { Name = "张三", Age = 25 },
new User { Name = "李四", Age = 30 },
new User { Name = "李白", Age = 29 },
new User { Name = "王五", Age = 35 }
};
result.Parameters = new object[] { users, condition };
result.ParamTypes = new[] { "List<User>", "Func<User, Boolean>" };
break;
case "COUNTIF":
// 提取数值范围(如"5000到20000")和数据
var rangeMatch = Regex.Match(text, @"(\d+)到(\d+)");
if (!rangeMatch.Success)
{
result.Error = "COUNTIF需要范围条件如'5000到20000'";
return result;
}
double min = double.Parse(rangeMatch.Groups[1].Value);
double max = double.Parse(rangeMatch.Groups[2].Value);
// 提取销售额数据
var salesData = Regex.Match(text, @"\[([\d, ]+)\]")
.Groups[1].Value.Split(',').Select(double.Parse).ToArray();
result.Parameters = new object[] { salesData, (Func<double, bool>)(s => s >= min && s <= max) };
result.ParamTypes = new[] { "Double[]", "Func<Double, Boolean>" };
break;
}
}
catch (Exception ex)
{
result.Error = $"参数解析失败:{ex.Message}";
return result;
}
return result;
}
static string GetResultString(object result)
{
if (result is double[] nums) return string.Join(", ", nums);
if (result is List<User> users) return string.Join(", ", users.Select(u => $"{u.Name}({u.Age})"));
if (result is int count) return count.ToString();
return "未知结果";
}
}
}