Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- public class Conversation
- {
- private const string CmdSplitToken = "_";
- //------------------------
- public Conversation(OpenAIAPIClient client)
- {
- Client = client;
- IsRunning = false;
- }
- public OpenAIAPIClient Client;
- [SerializeField]public string ModelOverride = "";
- [Header("Status")]
- [SerializeField]public bool IsRunning = false;
- [SerializeField]public string Log = "";
- [Header("Addenda")]
- public string TextInjection = "";
- [Header("Setting")]
- public Setting Loc;
- [Header("People")]
- [SerializeField] public List<Actor> Conversants = new();
- [Header("Events")]
- [SerializeField] public List<string> PreviousEvents = new(); //Mix of JSON and raw strings
- [SerializeField] public List<Proposal> ProposedActions = new();
- //Events
- public CoreEvent<string> OnRawReceive = new();
- public CoreEvent<string> OnSuccessfullyProcessed = new();
- [Header("Debug")]
- [SerializeField] private string rawSend;
- [SerializeField] private string rawResult;
- [TextArea(3,10)]
- [SerializeField] private string processedResult;
- [TextArea(3,10)][SerializeField] private string Result;
- //State
- [NonSerialized]public Actor lastSpeaker;
- // ---------------------------
- public string GetEventsAsString()
- {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < PreviousEvents.Count; i++)
- {
- //try to convert to json
- try
- {
- var json = JsonUtility.FromJson<LLMCommandJSON>(PreviousEvents[i]);
- sb.AppendLine($"{i}: {json.Speaker} to {json.Listener}: {json.Dialogue}");
- }
- catch
- {
- sb.AppendLine($"{i}: {PreviousEvents[i]}");
- }
- }
- return sb.ToString().Trim();
- }
- public string GetProposalsAsString()
- {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < ProposedActions.Count; i++)
- sb.AppendLine($"{i}: {ProposedActions[i].Source.Name} to {ProposedActions[i].Target.Name}: [{ProposedActions[i].Key}] {ProposedActions[i].Description}");
- return sb.ToString().Trim();
- }
- public bool HasProposal(Actor target, string key) => ProposedActions.Exists(p => p.Target == target && string.Equals(p.Key, key, StringComparison.OrdinalIgnoreCase));
- public bool HasProposal(string target, string key) => ProposedActions.Exists(p => String.Equals(p.Target.Name, target, StringComparison.OrdinalIgnoreCase) && string.Equals(p.Key, key, StringComparison.OrdinalIgnoreCase));
- // INFERENCING -------------------
- private string GeneratePrompt(Actor currentSpeaker, string pastEvents) => PromptGenerator.GenerateConversationPrompt(currentSpeaker, LLMCmdRegistry.SortedDefs, GetEventsAsString, Conversants);
- public void InferenceWithSpeaker(Actor speaker)
- {
- IsRunning = true;
- lastSpeaker = speaker;
- rawSend = TextInjection + " " + GeneratePrompt(speaker, GetEventsAsString());
- Client.SimpleRequest(rawSend, OnResponse, ModelOverride);
- }
- public void InferenceNextSpeaker() => GetNameOfNextSpeaker(TryInference);
- private void TryInference(string? speakerName)
- {
- if (TryGetActorByName(speakerName, out var speaker))
- InferenceWithSpeaker(speaker);
- else
- {
- IsRunning = false;
- Log = "Failed to find speaker: " + speakerName;
- }
- }
- // ------------------------------
- private void OnResponse(string str)
- {
- rawResult = str;
- OnRawReceive?.Invoke(str);
- int start = str.IndexOf('{');
- str = str.Substring(start, str.LastIndexOf('}') - start + 1);
- OnProcessed(str.Trim());
- }
- private void OnProcessed(string str)
- {
- processedResult = str;
- OnSuccessfullyProcessed?.Invoke(str);
- try
- {
- LLMCommandJSON raw = JsonUtility.FromJson<LLMCommandJSON>(str.Trim());
- raw.Speaker = lastSpeaker.Name;
- LLMCommandJSON json = raw;
- string jsonStr = JsonUtility.ToJson(json);
- PreviousEvents.Add(jsonStr);
- processedResult = str;
- Result = $"{raw.Speaker} [{raw.Action} - {raw.ActionTarget}] to {raw.Listener}: {raw.Dialogue}";
- OnSuccessfullyProcessed?.Invoke(str);
- TryExecute(lastSpeaker, json);
- }
- catch
- {
- Debug.LogError($"Failed to process JSON: {str}");
- Log = "Failed to process JSON: " + str;
- IsRunning = false;
- }
- }
- // NEXT ----------------------------
- class LLMNextSpeakerJSON //Container json for next speaker prompt results.
- {
- public string NextSpeaker;
- }
- public void GetNameOfNextSpeaker(Action<string> callback)
- {
- string prompt = PromptGenerator.GetNextSpeakerPrompt(this);
- void MergedCallback(string s)
- {
- string name = ProcessNameOfNextSpeaker(s, callback);
- callback(name);
- }
- Client.SimpleRequest(prompt, MergedCallback, ModelOverride);
- }
- private string ProcessNameOfNextSpeaker(string raw, Action<string> callback)
- {
- try
- {
- var json = JsonUtility.FromJson<LLMNextSpeakerJSON>(raw);
- return json.NextSpeaker;
- }
- catch
- {
- Debug.LogError($"Failed to process JSON: {raw}");
- Log = "Failed to process JSON: " + raw;
- IsRunning = false;
- return "";
- }
- }
- // ACTIONS ----------------------------
- private void TryExecute(Actor speaker, LLMCommandJSON json)
- {
- if (String.IsNullOrEmpty(json.Action))
- return;
- string[] actions = json.Action.Split(',');
- foreach (var action in actions)
- {
- if (LLMCmdRegistry.TryGetCmdDef(action, out var cmdDef))
- ExecuteStandard(action, cmdDef);
- else //Procedural
- ExecuteProcedural(action);
- }
- IsRunning = false;
- return;
- void ExecuteStandard(string action, CmdDef cmdDef)
- {
- Actor? target;
- TryGetActorByName(json.ActionTarget, out target);
- cmdDef.Execute(this, speaker, target, out var resultEvent);
- if (String.IsNullOrEmpty(resultEvent) == false)
- PreviousEvents.Add(resultEvent);
- }
- void ExecuteProcedural(string action)
- {
- string[] split = action.Replace("#", "").Split(CmdSplitToken);
- if (split.Length < 2)
- return;
- Actor? target;
- TryGetActorByName(json.ActionTarget, out target);
- if (!LLMCmdRegistry.TryGetCmdDef(split[0], out var procCmdDef)) return;
- if (procCmdDef is ProcCmdDef procCmd == false)
- return;
- procCmd.ExecuteProcedural(this, speaker, target, split, out var resultEvent);
- if (String.IsNullOrEmpty(resultEvent) == false)
- PreviousEvents.Add(resultEvent);
- }
- }
- bool TryGetActorByName(string str, out Actor? actor)
- {
- actor = null;
- if (String.IsNullOrEmpty(str))
- return false;
- foreach (var c in Conversants)
- if (String.Equals(str, c.Name, StringComparison.OrdinalIgnoreCase))
- actor = c;
- return actor != null;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement