|
|
using System.Collections.Generic;
|
|
|
using System;
|
|
|
using AI.Models.Form;
|
|
|
using YamlDotNet.Serialization;
|
|
|
using YamlDotNet.Serialization.NamingConventions;
|
|
|
|
|
|
namespace AI.Utils
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// 将表单定义序列化为 YAML,供 LLM 上下文、追踪、调试等使用。
|
|
|
/// </summary>
|
|
|
public static class FormSchemaYamlGenerator
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// System 消息中「表单 Schema YAML」块的开始标记(存在则整块替换,避免重复追加)。
|
|
|
/// </summary>
|
|
|
public const string FormsYamlBlockStart = "\n\n# --- 当前可用表单 Schema (YAML) ---\n";
|
|
|
|
|
|
/// <summary>
|
|
|
/// System 消息中「表单 Schema YAML」块的结束标记。
|
|
|
/// </summary>
|
|
|
public const string FormsYamlBlockEnd = "\n# --- 结束 ---";
|
|
|
|
|
|
/// <summary>
|
|
|
/// 将现有 System 内容与新的表单 YAML 合并:若已包含标记块则替换该块,否则在末尾追加。
|
|
|
/// </summary>
|
|
|
public static string MergeFormsYamlIntoSystemContent(string currentSystemContent, string formsYaml)
|
|
|
{
|
|
|
var block = FormsYamlBlockStart + formsYaml + FormsYamlBlockEnd;
|
|
|
if (string.IsNullOrEmpty(currentSystemContent))
|
|
|
return block.TrimStart('\n');
|
|
|
if (currentSystemContent.Contains(FormsYamlBlockStart))
|
|
|
{
|
|
|
int start = currentSystemContent.IndexOf(FormsYamlBlockStart, StringComparison.Ordinal);
|
|
|
int end = currentSystemContent.IndexOf(FormsYamlBlockEnd, start, StringComparison.Ordinal);
|
|
|
if (end >= 0)
|
|
|
{
|
|
|
end += FormsYamlBlockEnd.Length;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
end = currentSystemContent.Length;
|
|
|
}
|
|
|
return currentSystemContent.Remove(start, end - start).Insert(start, block);
|
|
|
}
|
|
|
return currentSystemContent + block;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 将当前可用表单定义生成为 YAML 字符串。
|
|
|
/// </summary>
|
|
|
public static string ToYaml(IEnumerable<FormDefinition> forms)
|
|
|
{
|
|
|
var schema = new FormsSchemaYaml
|
|
|
{
|
|
|
Forms = BuildForms(forms)
|
|
|
};
|
|
|
|
|
|
var serializer = new SerializerBuilder()
|
|
|
.WithNamingConvention(CamelCaseNamingConvention.Instance)
|
|
|
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitNull | DefaultValuesHandling.OmitDefaults)
|
|
|
.Build();
|
|
|
|
|
|
// 保留顶部说明注释(内容不参与结构序列化)。
|
|
|
return "# 当前可用表单 Schema(供助手了解可展示的表单与字段)\n" + serializer.Serialize(schema);
|
|
|
}
|
|
|
|
|
|
private static List<FormYaml> BuildForms(IEnumerable<FormDefinition>? forms)
|
|
|
{
|
|
|
var list = new List<FormYaml>();
|
|
|
foreach (var form in forms ?? [])
|
|
|
{
|
|
|
var formYaml = new FormYaml
|
|
|
{
|
|
|
Id = form.Id,
|
|
|
Title = form.Title,
|
|
|
SubmitTarget = form.SubmitTarget,
|
|
|
SubmitLabel = form.SubmitLabel,
|
|
|
Fields = BuildFields(form.Fields)
|
|
|
};
|
|
|
list.Add(formYaml);
|
|
|
}
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
private static List<FieldYaml> BuildFields(IReadOnlyList<FormField>? fields)
|
|
|
{
|
|
|
var list = new List<FieldYaml>();
|
|
|
foreach (var f in fields ?? [])
|
|
|
{
|
|
|
list.Add(new FieldYaml
|
|
|
{
|
|
|
Id = f.Id,
|
|
|
Label = f.Label,
|
|
|
Description = string.IsNullOrEmpty(f.Description) ? null : f.Description,
|
|
|
Type = f.Type.ToString(),
|
|
|
Required = f.Required ? true : null,
|
|
|
Default = f.DefaultValue == null ? null : f.DefaultValue.ToString(),
|
|
|
Min = f.Min,
|
|
|
Max = f.Max,
|
|
|
Step = f.Step,
|
|
|
MaxLength = f.MaxLength,
|
|
|
Placeholder = string.IsNullOrEmpty(f.Placeholder) ? null : f.Placeholder,
|
|
|
Options = (f.Options != null && f.Options.Count > 0) ? new List<string>(f.Options) : null,
|
|
|
DefaultValues = (f.DefaultValues != null && f.DefaultValues.Count > 0) ? new List<string>(f.DefaultValues) : null
|
|
|
});
|
|
|
}
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
private sealed class FormsSchemaYaml
|
|
|
{
|
|
|
public List<FormYaml> Forms { get; init; } = [];
|
|
|
}
|
|
|
|
|
|
private sealed class FormYaml
|
|
|
{
|
|
|
public string? Id { get; init; }
|
|
|
public string? Title { get; init; }
|
|
|
public string? SubmitTarget { get; init; }
|
|
|
public string? SubmitLabel { get; init; }
|
|
|
public List<FieldYaml> Fields { get; init; } = [];
|
|
|
}
|
|
|
|
|
|
private sealed class FieldYaml
|
|
|
{
|
|
|
public string? Id { get; init; }
|
|
|
public string? Label { get; init; }
|
|
|
public string? Description { get; init; }
|
|
|
public string? Type { get; init; }
|
|
|
|
|
|
// 仅在 true 时输出
|
|
|
public bool? Required { get; init; }
|
|
|
|
|
|
[YamlMember(Alias = "default")]
|
|
|
public string? Default { get; init; }
|
|
|
|
|
|
public double? Min { get; init; }
|
|
|
public double? Max { get; init; }
|
|
|
public double? Step { get; init; }
|
|
|
public int? MaxLength { get; init; }
|
|
|
public string? Placeholder { get; init; }
|
|
|
public List<string>? Options { get; init; }
|
|
|
public List<string>? DefaultValues { get; init; }
|
|
|
}
|
|
|
}
|
|
|
}
|