简体   繁体   English

如何在 Unity 的聊天框/文本字段中隔离文本字符串?

[英]How do you isolate a text string from in a chatbox/text field in Unity?

I am making a chatbot (well I'm attempting.) and I have set up wit.ai to handle the text-to-speech of the bot, My issue is that I am pulling all of the chat into the speaker on each update which is overloading the TTS.我正在制作一个聊天机器人(嗯,我正在尝试。)并且我已经设置了 wit.ai 来处理机器人的文本到语音,我的问题是我在每次更新时将所有聊天内容都拉到扬声器中这使 TTS 超载。 when I really only want the line of the Bot (Dave) to go through the speaker and update with each new line?当我真的只希望 Bot (Dave) 的线路通过扬声器连接到 go 并更新每条新线路时? How can I isolate only the bots lines?我怎样才能只隔离机器人线路? Would love some help with this!希望对此有所帮助!

public class SimpleCharacter : MonoBehaviour
{
    public GameObject item;
    public Scrollbar verticalScrollbar;
    public ScrollRect scrollRect;
    public TMP_Text chatText;
    private Animator anim;
    public TTSSpeaker _speaker;


    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("Simple Character start 0 ");
        anim = GetComponentInChildren<Animator>();
        if (anim == null)
        {
            Debug.Log("Simple Character anim is null");
        }
        Debug.Log("Simple Character start 1");
    }

    public void Think (string text)
    {
        string chat = chatText.text;
        chat = chat + "/n" + text;
        chatText.text = text;
        anim.SetTrigger("Think");
    }

    public void Talk(List<Choice> choices)
    {
        
        string chat = chatText.text;
        chatText.text = "";
        Debug.Log("////////////////////// :  " + chat);
        chat = chat + "/n" + choices[0].ToString();
        Debug.Log("////////////////////// :  " + chat);
        chatText.text = chat;

        chatText.text = choices[0].ToString();
        anim.SetTrigger("Talk");    
    }    

    public void Talk (string text)
    {
        string chat = chatText.text;
        chat = chat + "/n" + text;
        chatText.text = chat;
        chatText.text = text;

        _speaker.Speak(chatText.text);
                
        }
    
}

Daves's lines are being received from this character's script正在从该角色的脚本中接收戴夫斯的台词

namespace OpenAI_Unity
{
    
    public class OAICharacter : OAICompletion
    {
        protected override StringBuilder GetDefaultInformation()
        {
            Debug.Log("GetDefaultInformation -  OAICharacter");
            var sb = base.GetDefaultInformation();
            sb.Replace("[Subject]", this.characterName);
            sb.Append($"\n\nHuman: Hi\n{characterName}: Hello\nHuman: ");

            return sb;
        }
        public override string Description { get => $"The following is a conversation between a Human and {characterName}.\n"; set => throw new System.NotImplementedException(); }

        public override string InjectStartText { get => "\n" + characterName + ":"; set => throw new System.NotImplementedException(); }
        [SerializeField]
        private string characterName = "Dave";

        public override string InjectRestartText { get => "\nHuman: "; set => throw new System.NotImplementedException(); }

        public override string[] StopSequences { get => new string[] { "\n", "Human:" }; set => throw new System.NotImplementedException(); }

        public override int NumOutputs { get => 1; set => throw new NotImplementedException(); }


        private void ThrowError (string value)
        {
            Debug.LogError($"Can not set OAICharacter variable to {value}! If you want to modify these please use an OAISimpleObject instead");
        }

    }
}

This is the controller script这是 controller 脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using OpenAI_Unity;
using TMPro;

public class ChatController : MonoBehaviour
{
    public OAICharacter _oaiCharacter;
    public TMP_InputField questionInput;
    // Start is called before the first frame update
    void Start()
    {
        questionInput.onEndEdit.AddListener((string data) =>
        {
            if (!string.IsNullOrEmpty(data))
            {

                _oaiCharacter.AddToStory(data);
            }
            questionInput.text = "";
        });
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Tab))
        {
            questionInput.Select();
            questionInput.ActivateInputField();
        }
    }
}

And the completion和完成

namespace OpenAI_Unity
{
    /// <summary>
    /// Used for objects that communicate with OpenAI Completion
    /// Abstract itself, for a Generic and fully customizable Completion object use OAIGenericCompletion
    /// </summary>
    public abstract class OAICompletion : MonoBehaviour
    {
        public abstract string Description
        {
            get; set;
        }

        public abstract string InjectStartText
        {
            get; set;
        }

        public abstract string InjectRestartText
        {
            get; set;
        }

        public abstract string[] StopSequences
        {
            get; set;
        }

        public EngineEnum engine;

        public enum EngineEnum
        {
            Ada,
            Babbage,
            Curie,
            Davinci
        }

        public enum LogLevel
        {
            None,
            Responses,
            ResponsesAndMemory
        }

        public LogLevel logLevel;

        public int Max_tokens = 16;
        [Range(0, 1)]
        public double Temperature = 0.1;
        [Range(0, 1)]
        public double Top_p = 1;
        public abstract int NumOutputs {get;set;}
        [Range(0, 1)]
        public double PresencePenalty = 1;
        [Range(0, 1)]
        public double FrequencyPenalty = 1;
        public int LogProbs = 1;

        public StringEvent QuestionReceivedEvent;
        public ChoicesEvent ResponseReceivedEvent;
        public ChoiceEvent ResponseReceivedEvent1;

        /// <summary>
        /// This can be disabled when using multiple responses, since they should not be manually added to the entire memory
        /// </summary>
        [HideInInspector]
        public bool autoAddResponseToMemory = true;


        public StringBuilder memory ;

        private void Start()
        {
            Debug.Log("OAI Completion start 0 ");
            memory = GetDefaultInformation();
            Debug.Log("Start - memory: " + memory);
            
            
            Debug.Log("OAI Completion start 1 ");
        }

        


        public void Brainwash(bool resetToDefault = true)
        {
            memory = resetToDefault ? GetDefaultInformation() : new StringBuilder();
        }

        /// <summary>
        /// D
        /// </summary>
        /// <returns></returns>
        protected virtual StringBuilder GetDefaultInformation()
        {
            Debug.Log("GetDefaultInformation -  OAICompletion");
            StringBuilder sb = new StringBuilder();
            sb.Append(Description);

            foreach (OAIBehavior behavior in GetComponents<OAIBehavior>())
            {
                string behaviorText = behavior.GetAsText();
                sb.Append(behaviorText);
                sb.Append(" ");
            }            

            return sb;
        }

        public async void AddToStory(string value)
        {
            
            //QuestionReceivedEvent?.Invoke(value);

            
            //Character should remember what they said before, since every time we send a request it requires the full 'story' to OpenAI
            memory.Append(value).Append(InjectStartText);
            QuestionReceivedEvent?.Invoke(memory.ToString());
            if (logLevel == LogLevel.ResponsesAndMemory)
            {
                Debug.Log(memory);
            }

            if (!OAIEngine.Instance)
            {
                Debug.LogError("No OAIEngine object found in scene. Make sure there's a GameObject with an OAIEngine Component in your scene");
                return;
            }    

            //We allow the engine to change per request (= per character and per statement)
            OAIEngine.Instance.Api.UsingEngine = GetEngine(engine);

            if (NumOutputs < 1)
            {
                Debug.LogWarning($"NumOutputs was set to {NumOutputs}. You should have at least 1 output!");
                NumOutputs = 1;
            } else if (autoAddResponseToMemory && NumOutputs > 1)
            {
                Debug.Log("Multiple or no outputs are requested while autoAddResponseToMemory is still true. You should set this to false and manually call 'AddResponseToMemory' after selecting your prefered response.");
            }
            Debug.Log("Stop Seq: " + StopSequences[0] + " _ " + StopSequences[1]);
            var c = new CompletionRequest(memory.ToString(), Max_tokens, Temperature, Top_p, NumOutputs, PresencePenalty, FrequencyPenalty, LogProbs, StopSequences);
            var results = await OAIEngine.Instance.Api.Completions.CreateCompletionsAsync(c);

            //ResponseReceivedEvent?.Invoke(results.Completions);

            //We make it easy by auto-adding responses to the memory
            if (autoAddResponseToMemory)
            {
                var r = results.Completions[0].Text;
                AddResponseToMemory(r);
                if (logLevel == LogLevel.Responses || logLevel == LogLevel.ResponsesAndMemory)
                {
                    Debug.Log(r);
                }                
            }
        }

        public void AddResponseToMemory (string value)
        {
            memory.Append(value).Append(InjectRestartText);
            ResponseReceivedEvent1?.Invoke(memory.ToString());
            Debug.Log("Memory: " + memory);
        }

        private Engine GetEngine(EngineEnum e)
        {
            switch (e)
            {
                case EngineEnum.Ada:
                    return Engine.Ada;
                case EngineEnum.Babbage:
                    return Engine.Babbage;
                case EngineEnum.Curie:
                    return Engine.Curie;
                case EngineEnum.Davinci:
                    return Engine.Davinci;
            }
            return Engine.Default;
        }

    }

}

You should work with the text string that is passed to the function instead of the entire chat text.您应该使用传递给 function 的文本字符串,而不是整个聊天文本。 Assuming that all spoken dialog starts with "Dave: " you can easily detect this substring in the text, remove it and pass it to your text to speech.假设所有口头对话都以“戴夫:”开头,您可以轻松地在文本中检测到这个 substring,将其删除并将其传递给您的文本转语音。

using System;

string botName = "Dave: ";

public void Talk(string text){
  chatText.text += "\n" + text;

  if(text.StartsWith(botName)){
    string spokenText = text.Remove(0, botName.Length)
    _speaker.Speak(spokenText);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM