EchoTrio
 
Loading...
Searching...
No Matches
ActorConfig.cs
Go to the documentation of this file.
1using System;
2using Microsoft.Extensions.Configuration;
3using UnityEngine;
4
5namespace EchoTrio {
6 /// Actor's configuration as a ScriptableObject.
7 /// Some configurations can be overridden via the ActorOverrides.ini file.
8 [CreateAssetMenu(fileName = "ActorConfig", menuName = "EchoTrio/ActorConfig")]
9 public class ActorConfig : ScriptableObject {
10 private const string OverrideFileName = "ActorOverrides.ini";
11
12 [System.Serializable] public class InstructionSnippet {
13 public bool enabled = true;
14 [TextArea(minLines: 4, maxLines: 8)] public string instruction = string.Empty;
15 }
16
17 /// Flags to enable or disable actor features.
18 [System.Flags] public enum Feature {
19 /// Allow the actor's OpenAI model to access the internet and search for information.
20 WebSearch = 1 << 0,
21 /// Allow the actor's OpenAI model to access files uploaded into the vector store. https://platform.openai.com/storage
22 FileSearch = 1 << 1,
23 /// Allow the actor's OpenAI model to provide its reasoning when generating a response.
24 Reasoning = 1 << 2,
25 /// Allow the actor's ElevenLabs model to use audio tags to generate more expressive dialouge. https://elevenlabs.io/blog/v3-audiotags
26 AudioTags = 1 << 3,
27 }
28
29 [Header("Settings")]
30 [SerializeField] private Persona persona = PersonaExtensions.DefaultValue;
31 [SerializeField] private Feature enabledFeatures = Feature.WebSearch | Feature.FileSearch | Feature.Reasoning | Feature.AudioTags;
32 [SerializeField] private string elevenLabsVoiceId = string.Empty;
33 [SerializeField] private string openAIVectorStoreId = string.Empty;
34
35 [Header("Instructions")]
36 [SerializeField, TextArea(minLines: 16, maxLines: 32)] private string generalInstructions = string.Empty;
37 [SerializeField] private InstructionSnippet[] contextInfos = new InstructionSnippet[0];
38 [SerializeField] private InstructionSnippet[] backgroundInfos = new InstructionSnippet[0];
39 [SerializeField] private InstructionSnippet[] personalityInfos = new InstructionSnippet[0];
40 [SerializeField] private InstructionSnippet[] exampleResponses = new InstructionSnippet[0];
41
42 // Public Interface
43 public Persona GetPersona() { return persona; }
44
45 public bool AreAllFeaturesEnabled(Feature features) { return (enabledFeatures & features) == features; }
46
47 public bool IsAnyFeatureEnabled(Feature features) { return (enabledFeatures & features) != 0; }
48
49 public string GetElevenLabsVoiceID() { return elevenLabsVoiceId; }
50
51 public string GetOpenAIVectorStoreID() { return openAIVectorStoreId; }
52
53 public string GetInstructions() {
54 string instructions = $"You will be playing a character named {this.persona}.\n\n";
55 instructions += generalInstructions + "\n\n";
56 instructions += GetSnippetsInstructions("Here are some context information about your character:", contextInfos);
57 instructions += GetSnippetsInstructions("Here are some background information about your character:", backgroundInfos);
58 instructions += GetSnippetsInstructions("Here are some personality information about your character:", personalityInfos);
59 instructions += GetSnippetsInstructions("Here are some example responses that you should style your own responses after:", exampleResponses);
60 return instructions;
61 }
62
63 /// <summary>
64 /// Overrides any actor config if value is set in ActorOverrides.ini.
65 /// </summary>
66 /// <returns>Returns a copy of this ActorConfig with values overridden.</returns>
68 ActorConfig overriddenConfig = Instantiate(this);
69
70 string filePath = $"{Application.streamingAssetsPath}/Configs/{OverrideFileName}";
71 IConfiguration config = new ConfigurationBuilder().AddIniFile(filePath).Build();
72 IConfigurationSection section = config.GetSection(persona.ToString());
73
74 // We cannot proceed if the section does not exist.
75 if (section == null) {
76 Debug.LogWarning($"Section {persona.ToString()} not found in {filePath}!");
77 return overriddenConfig;
78 }
79
80 // Define a helper function.
81 Func<string, string> GetValue = (string key) => { return section[key] == null ? string.Empty : section[key].Trim(); };
82 string value = string.Empty;
83
84 // Override OpenAI Vector Store ID
85 value = GetValue("openai_vector_store_id");
86 if (!string.IsNullOrEmpty(value)) {
87 Debug.Log($"Overrode {persona.ToString()}'s OpenAI Vector Store ID.");
88 overriddenConfig.openAIVectorStoreId = value;
89 }
90
91 // Override ElevenLabs Voice ID
92 value = GetValue("elevenlabs_voice_id");
93 if (!string.IsNullOrEmpty(value)) {
94 Debug.Log($"Overrode {persona.ToString()}'s ElevenLabs Voice ID.");
95 overriddenConfig.elevenLabsVoiceId = value.Trim();
96 }
97
98 // Override Features
99 value = GetValue("feature_web_search");
100 if (!string.IsNullOrEmpty(value)) {
101 if (value.ToUpper() == "TRUE") {
102 Debug.Log($"Overrode {persona.ToString()}'s Web Search Feature Setting To TRUE.");
103 overriddenConfig.enabledFeatures |= Feature.WebSearch;
104 } else if (value.ToUpper() == "FALSE") {
105 Debug.Log($"Overrode {persona.ToString()}'s Web Search Feature Setting To TRUE.");
106 overriddenConfig.enabledFeatures &= ~Feature.WebSearch;
107 }
108 }
109
110 value = GetValue("feature_file_search");
111 if (!string.IsNullOrEmpty(value)) {
112 if (value.ToUpper() == "TRUE") {
113 Debug.Log($"Overrode {persona.ToString()}'s File Search Feature Setting To TRUE.");
114 overriddenConfig.enabledFeatures |= Feature.FileSearch;
115 } else if (value.ToUpper() == "FALSE") {
116 Debug.Log($"Overrode {persona.ToString()}'s File Search Feature Setting To FALSE.");
117 overriddenConfig.enabledFeatures &= ~Feature.FileSearch;
118 }
119 }
120
121 value = GetValue("feature_reasoning");
122 if (!string.IsNullOrEmpty(value)) {
123 if (value.ToUpper() == "TRUE") {
124 Debug.Log($"Overrode {persona.ToString()}'s Reasoning Feature Setting To TRUE.");
125 overriddenConfig.enabledFeatures |= Feature.Reasoning;
126 } else if (value.ToUpper() == "FALSE") {
127 Debug.Log($"Overrode {persona.ToString()}'s Reasoning Feature Setting To FALSE.");
128 overriddenConfig.enabledFeatures &= ~Feature.Reasoning;
129 }
130 }
131
132 value = GetValue("feature_audio_tags");
133 if (!string.IsNullOrEmpty(value)) {
134 if (value.ToUpper() == "TRUE") {
135 Debug.Log($"Overrode {persona.ToString()}'s Audio Tags Feature Setting To TRUE.");
136 overriddenConfig.enabledFeatures |= Feature.AudioTags;
137 } else if (value.ToUpper() == "FALSE") {
138 Debug.Log($"Overrode {persona.ToString()}'s Audio Tags Feature Setting To FALSE.");
139 overriddenConfig.enabledFeatures &= ~Feature.AudioTags;
140 }
141 }
142
143 return overriddenConfig;
144 }
145
146 // Internal Variables
147 private string GetSnippetsInstructions(string prefix, InstructionSnippet[] snippets) {
148 // Check if there are any valid snippets.
149 bool hasValidSnippets = false;
150 foreach (InstructionSnippet snippet in snippets) {
151 if (snippet == null) { continue; }
152 hasValidSnippets = hasValidSnippets || snippet.enabled;
153 }
154 if (!hasValidSnippets) { return string.Empty; }
155
156 // Combine all the snippets into a single string.
157 string instructions = $"{prefix}\n";
158 foreach (InstructionSnippet snippet in snippets) {
159 if (snippet == null) { continue; }
160 if (!snippet.enabled) { continue; }
161 instructions += $"{snippet.instruction}\n";
162 }
163 return instructions + "\n";
164 }
165 }
166}
ActorConfig Override()
Overrides any actor config if value is set in ActorOverrides.ini.
Definition: ActorConfig.cs:67
string generalInstructions
Definition: ActorConfig.cs:36
InstructionSnippet[] exampleResponses
Definition: ActorConfig.cs:40
InstructionSnippet[] backgroundInfos
Definition: ActorConfig.cs:38
bool IsAnyFeatureEnabled(Feature features)
Definition: ActorConfig.cs:47
bool AreAllFeaturesEnabled(Feature features)
Definition: ActorConfig.cs:45
Persona GetPersona()
Definition: ActorConfig.cs:43
Feature
Flags to enable or disable actor features.
Definition: ActorConfig.cs:18
@ FileSearch
Allow the actor's OpenAI model to access files uploaded into the vector store. https://platform....
@ AudioTags
Allow the actor's ElevenLabs model to use audio tags to generate more expressive dialouge....
@ Reasoning
Allow the actor's OpenAI model to provide its reasoning when generating a response.
@ WebSearch
Allow the actor's OpenAI model to access the internet and search for information.
InstructionSnippet[] personalityInfos
Definition: ActorConfig.cs:39
string GetOpenAIVectorStoreID()
Definition: ActorConfig.cs:51
string GetInstructions()
Definition: ActorConfig.cs:53
const string OverrideFileName
Definition: ActorConfig.cs:10
string GetSnippetsInstructions(string prefix, InstructionSnippet[] snippets)
Definition: ActorConfig.cs:147
string openAIVectorStoreId
Definition: ActorConfig.cs:33
string GetElevenLabsVoiceID()
Definition: ActorConfig.cs:49
InstructionSnippet[] contextInfos
Definition: ActorConfig.cs:37
const Persona DefaultValue
Definition: Persona.cs:11
Persona
Personas the actors will role-play.
Definition: Persona.cs:5