using AIStudio.Settings.DataModel; namespace AIStudio.Assistants.BeyondFactsLab; /// /// Reads the prompts and the knowledge base of the BeyondFacts Lab, which come with AI Studio. /// /// /// The files are German Markdown below Assistants/BeyondFactsLab, embedded into the app. A development build reads /// them from the disk, so that a changed prompt shows in the next request without building again; see AppResources. /// public static class BflPromptLibrary { /// /// The folder of the lab, relative to the project folder. /// private const string FOLDER = "Assistants/BeyondFactsLab"; /// /// The prompt every chat of the lab starts with: role, principles, and the places of the other parts. /// public const string CORE_PATH = FOLDER + "/Prompts/core.md"; /// /// The guide by Lara Wüster (TUM), which every chat of the lab keeps in its context. /// public const string KNOWLEDGE_PATH = FOLDER + "/Knowledge/beyondfacts-paper.md"; /// /// The prompt of the conversation in which the lab tells whether it fits a task. It stands on its own, without /// the core and the guide. /// public const string ONBOARDING_PATH = FOLDER + "/Prompts/onboarding.md"; /// /// The instruction to address the person formally. /// private const string ADDRESS_FORMAL_PATH = FOLDER + "/Prompts/snippets/address-formal.md"; /// /// The instruction to address the person informally. /// private const string ADDRESS_INFORMAL_PATH = FOLDER + "/Prompts/snippets/address-informal.md"; /// /// Gets the prompt of a step, named like the folder of the step. /// /// The step. public static string StepPath(BflStep step) => $"{FOLDER}/Prompts/steps/{step.FolderName}.md"; /// /// Gets the instruction for a form of address. /// /// The form of address. public static string AddressPath(AddressForm addressForm) => addressForm is AddressForm.INFORMAL ? ADDRESS_INFORMAL_PATH : ADDRESS_FORMAL_PATH; /// /// Gets every file of the lab's prompts, e.g., to check that the app comes with all of them. /// public static IReadOnlyList AllPaths => [ CORE_PATH, KNOWLEDGE_PATH, ONBOARDING_PATH, ..Enum.GetValues().Select(AddressPath).Distinct(), ..BflStep.All.Select(StepPath) ]; /// /// Reads the texts of the system prompt of a step. /// /// The step. /// How the model addresses the person. /// The cancellation token. /// The texts, which BflPromptComposer puts together. /// The app comes without one of the files. public static async Task LoadPartsAsync(BflStep step, AddressForm addressForm, CancellationToken token = default) => new( await ReadAsync(CORE_PATH, token), await ReadAsync(KNOWLEDGE_PATH, token), await ReadAsync(StepPath(step), token), await ReadAsync(AddressPath(addressForm), token)); /// /// Reads the texts of the system prompt of the conversation about whether the lab fits a task. /// /// How the model addresses the person. /// The cancellation token. /// The texts, which BflPromptComposer puts together. /// The app comes without one of the files. public static async Task LoadOnboardingPartsAsync(AddressForm addressForm, CancellationToken token = default) => new( await ReadAsync(ONBOARDING_PATH, token), await ReadAsync(AddressPath(addressForm), token)); /// /// Reads a file of the lab's prompts. /// /// The file, one of the paths of this class. /// The cancellation token. /// The text of the file. /// The app comes without the file, or the file is empty. public static async Task ReadAsync(string path, CancellationToken token = default) { var text = await AppResources.ReadTextAsync(path, token); if (string.IsNullOrWhiteSpace(text)) throw new FileNotFoundException("The BeyondFacts Lab misses one of its prompts.", path); return text; } }