using System;
using System.Collections.Generic;
namespace LLama
{
///
/// AntipromptProcessor keeps track of past tokens looking for any set Anti-Prompts
///
public sealed class AntipromptProcessor
{
private int _longestAntiprompt;
private readonly List _antiprompts = new();
private string? _string;
///
/// Initializes a new instance of the class.
///
/// The antiprompts.
public AntipromptProcessor(IEnumerable? antiprompts = null)
{
if (antiprompts != null)
SetAntiprompts(antiprompts);
}
///
/// Add an antiprompt to the collection
///
///
public void AddAntiprompt(string antiprompt)
{
_antiprompts.Add(antiprompt);
_longestAntiprompt = Math.Max(_longestAntiprompt, antiprompt.Length);
}
///
/// Overwrite all current antiprompts with a new set
///
///
public void SetAntiprompts(IEnumerable antiprompts)
{
_antiprompts.Clear();
_antiprompts.AddRange(antiprompts);
_longestAntiprompt = 0;
foreach (var antiprompt in _antiprompts)
_longestAntiprompt = Math.Max(_longestAntiprompt, antiprompt.Length);
}
///
/// Add some text and check if the buffer now ends with any antiprompt
///
///
/// true if the text buffer ends with any antiprompt
public bool Add(string text)
{
_string += text;
// When the string gets very long (4x antiprompt length) trim it down (to 2x antiprompt length).
// This trimming leaves a lot of extra characters because two sequences can be considered "equal" in unicode
// even with different numbers of characters. Hopefully there are enough characters here to handle all those weird circumstances!
var maxLength = Math.Max(32, _longestAntiprompt * 4);
var trimLength = Math.Max(16, _longestAntiprompt * 2);
if (_string.Length > maxLength)
_string = _string.Substring(_string.Length - trimLength);
foreach (var antiprompt in _antiprompts)
if (_string.EndsWith(antiprompt, StringComparison.CurrentCulture))
return true;
return false;
}
}
}