Спасибо! В проекте используются юниты для поддержки ucs4//utf32. Ты можешь сделать ещё один юнит (ucs4functionsunit) к ним, в котором будут стандартные функции работы со строками (вроде Pos, RPos, IfThen, ...) и может быть какие-то ещё удобные и нужные при работе ИИ?

Вот реализация модуля ucs4functionsunit.pas с дополнительными функциями для работы с UCS4, которые будут полезны для ИИ:
pascal

unit ucs4functionsunit;

{
    UCS4 Functions Unit - дополнительные функции для работы с UCS4
    Для GNU/Linux 64 bit версии
    Версия: 1.0
    Написано на FreePascal (https://freepascal.org/)
    Copyright (C) 2025  Artyomov Alexander
    http://self-made-free.ru/
    aralni@mail.ru

    Лицензия: GNU Affero General Public License
}

{$MODE OBJFPC}{$H+}
{$RANGECHECKS ON}
{$OPTIMIZATION LEVEL3}
{$INLINE ON}
{$CODEPAGE UTF8}

interface

uses
  SysUtils, ucs4unit, ucs4opunit;

function Pos(const SubStr, Str: ucs4): Integer;
function RPos(const SubStr, Str: ucs4): Integer;
function IfThen(Condition: Boolean; const TrueStr, FalseStr: ucs4): ucs4; overload;
function IfThen(Condition: Boolean; const TrueStr: ucs4): ucs4; overload;
function Split(const Str: ucs4; Delimiter: DWord): TArray<ucs4>;
function Join(const Arr: TArray<ucs4>; Delimiter: DWord): ucs4;
function ToLower(const Str: ucs4): ucs4;
function ToUpper(const Str: ucs4): ucs4;
function Trim(const Str: ucs4): ucs4;
function StartsWith(const Str, SubStr: ucs4): Boolean;
function EndsWith(const Str, SubStr: ucs4): Boolean;
function Contains(const Str, SubStr: ucs4): Boolean;
function LevenshteinDistance(const S1, S2: ucs4): Integer;
function NormalizeForAI(const Str: ucs4): ucs4;
function RemovePunctuation(const Str: ucs4): ucs4;
function TokenizeForNLP(const Str: ucs4): TArray<ucs4>;

implementation

function Pos(const SubStr, Str: ucs4): Integer;
var
  i, j: Integer;
  found: Boolean;
begin
  if (SubStr.Length = 0) or (Str.Length = 0) or (SubStr.Length > Str.Length) then
    Exit(0);

  for i := 0 to Str.Length - SubStr.Length do
  begin
    found := True;
    for j := 0 to SubStr.Length - 1 do
      if Str[i + j] <> SubStr[j] then
      begin
        found := False;
        Break;
      end;
    if found then
      Exit(i + 1); // 1-based index
  end;
  Result := 0;
end;

function RPos(const SubStr, Str: ucs4): Integer;
var
  i, j: Integer;
  found: Boolean;
begin
  if (SubStr.Length = 0) or (Str.Length = 0) or (SubStr.Length > Str.Length) then
    Exit(0);

  for i := Str.Length - SubStr.Length downto 0 do
  begin
    found := True;
    for j := 0 to SubStr.Length - 1 do
      if Str[i + j] <> SubStr[j] then
      begin
        found := False;
        Break;
      end;
    if found then
      Exit(i + 1); // 1-based index
  end;
  Result := 0;
end;

function IfThen(Condition: Boolean; const TrueStr, FalseStr: ucs4): ucs4;
begin
  if Condition then
    Result := TrueStr
  else
    Result := FalseStr;
end;

function IfThen(Condition: Boolean; const TrueStr: ucs4): ucs4;
begin
  if Condition then
    Result := TrueStr
  else
    Result := Default(ucs4);
end;

function Split(const Str: ucs4; Delimiter: DWord): TArray<ucs4>;
var
  i, StartIdx, Count: Integer;
begin
  if Str.Length = 0 then
    Exit(nil);

  // Подсчет количества разделителей
  Count := 0;
  for i := 0 to Str.Length - 1 do
    if Str[i] = Delimiter then
      Inc(Count);

  SetLength(Result, Count + 1);
  StartIdx := 0;
  Count := 0;

  for i := 0 to Str.Length - 1 do
    if Str[i] = Delimiter then
    begin
      Result[Count].Init(i - StartIdx);
      Move(Str.FData[StartIdx], Result[Count].FData^, (i - StartIdx) * SizeOf(DWord));
      Inc(Count);
      StartIdx := i + 1;
    end;

  // Последний сегмент
  Result[Count].Init(Str.Length - StartIdx);
  if Str.Length - StartIdx > 0 then
    Move(Str.FData[StartIdx], Result[Count].FData^, (Str.Length - StartIdx) * SizeOf(DWord));
end;

function Join(const Arr: TArray<ucs4>; Delimiter: DWord): ucs4;
var
  i, TotalLength, Pos: Integer;
begin
  if Length(Arr) = 0 then
    Exit(Default(ucs4));

  // Вычисление общей длины
  TotalLength := 0;
  for i := 0 to High(Arr) do
    Inc(TotalLength, Arr[i].Length);

  // Добавляем место для разделителей
  Inc(TotalLength, Length(Arr) - 1);

  Result.Init(TotalLength);
  Pos := 0;

  for i := 0 to High(Arr) do
  begin
    if (i > 0) and (TotalLength > 0) then
    begin
      Result[Pos] := Delimiter;
      Inc(Pos);
    end;

    if Arr[i].Length > 0 then
    begin
      Move(Arr[i].FData^, Result.FData[Pos], Arr[i].Length * SizeOf(DWord));
      Inc(Pos, Arr[i].Length);
    end;
  end;
end;

function ToLower(const Str: ucs4): ucs4;
var
  i: Integer;
begin
  Result.Init(Str.Length);
  for i := 0 to Str.Length - 1 do
    Result[i] := UnicodeToLower(Str[i]);
end;

function ToUpper(const Str: ucs4): ucs4;
var
  i: Integer;
begin
  Result.Init(Str.Length);
  for i := 0 to Str.Length - 1 do
    Result[i] := UnicodeToUpper(Str[i]);
end;

function Trim(const Str: ucs4): ucs4;
var
  Start, Len: Integer;
begin
  if Str.Length = 0 then
    Exit(Str);

  // Находим первый не-пробельный символ
  Start := 0;
  while (Start < Str.Length) and (IsWhiteSpace(Str[Start])) do
    Inc(Start);

  // Находим последний не-пробельный символ
  Len := Str.Length;
  while (Len > Start) and (IsWhiteSpace(Str[Len - 1])) do
    Dec(Len);

  Len := Len - Start;
  if Len <= 0 then
    Exit(Default(ucs4));

  Result.Init(Len);
  Move(Str.FData[Start], Result.FData^, Len * SizeOf(DWord));
end;

function StartsWith(const Str, SubStr: ucs4): Boolean;
var
  i: Integer;
begin
  if SubStr.Length > Str.Length then
    Exit(False);

  for i := 0 to SubStr.Length - 1 do
    if Str[i] <> SubStr[i] then
      Exit(False);

  Result := True;
end;

function EndsWith(const Str, SubStr: ucs4): Boolean;
var
  i, Offset: Integer;
begin
  if SubStr.Length > Str.Length then
    Exit(False);

  Offset := Str.Length - SubStr.Length;
  for i := 0 to SubStr.Length - 1 do
    if Str[Offset + i] <> SubStr[i] then
      Exit(False);

  Result := True;
end;

function Contains(const Str, SubStr: ucs4): Boolean;
begin
  Result := Pos(SubStr, Str) > 0;
end;

function LevenshteinDistance(const S1, S2: ucs4): Integer;
var
  i, j, cost: Integer;
  D: array of array of Integer;
begin
  SetLength(D, S1.Length + 1, S2.Length + 1);

  for i := 0 to S1.Length do
    D[i, 0] := i;
  for j := 0 to S2.Length do
    D[0, j] := j;

  for i := 1 to S1.Length do
    for j := 1 to S2.Length do
    begin
      if S1[i - 1] = S2[j - 1] then
        cost := 0
      else
        cost := 1;

      D[i, j] := Min(Min(D[i-1, j] + 1, D[i, j-1] + 1), D[i-1, j-1] + cost);
    end;

  Result := D[S1.Length, S2.Length];
end;

function NormalizeForAI(const Str: ucs4): ucs4;
var
  i, j: Integer;
  Temp: ucs4;
begin
  Temp.Init(Str.Length);
  j := 0;

  for i := 0 to Str.Length - 1 do
  begin
    // Приводим к нижнему регистру
    var c := UnicodeToLower(Str[i]);

    // Удаляем некоторые диакритические знаки (упрощенно)
    case c of
      $00E1, $00E0, $00E2, $00E3, $00E4: c := $0061; // á à â ã ä → a
      $00E9, $00E8, $00EA, $00EB: c := $0065; // é è ê ë → e
      $00ED, $00EC, $00EE, $00EF: c := $0069; // í ì î ï → i
      $00F3, $00F2, $00F4, $00F5, $00F6: c := $006F; // ó ò ô õ ö → o
      $00FA, $00F9, $00FB, $00FC: c := $0075; // ú ù û ü → u
    end;

    // Пропускаем некоторые специальные символы
    if not (c in [$0000..$0020, $FFFD]) then
    begin
      Temp[j] := c;
      Inc(j);
    end;
  end;

  if j = 0 then
    Exit(Default(ucs4));

  Result.Init(j);
  Move(Temp.FData^, Result.FData^, j * SizeOf(DWord));
  Temp.Clear;
end;

function RemovePunctuation(const Str: ucs4): ucs4;
var
  i, j: Integer;
  Temp: ucs4;
begin
  Temp.Init(Str.Length);
  j := 0;

  for i := 0 to Str.Length - 1 do
    if not IsPunctuation(Str[i]) then
    begin
      Temp[j] := Str[i];
      Inc(j);
    end;

  if j = 0 then
    Exit(Default(ucs4));

  Result.Init(j);
  Move(Temp.FData^, Result.FData^, j * SizeOf(DWord));
  Temp.Clear;
end;

function TokenizeForNLP(const Str: ucs4): TArray<ucs4>;
var
  i, Start, Count: Integer;
  InWord: Boolean;
begin
  if Str.Length = 0 then
    Exit(nil);

  // Первый проход - подсчет токенов
  Count := 0;
  InWord := False;
  for i := 0 to Str.Length - 1 do
  begin
    if IsWhiteSpace(Str[i]) or IsPunctuation(Str[i]) then
    begin
      if InWord then
      begin
        Inc(Count);
        InWord := False;
      end;
    end
    else
      InWord := True;
  end;
  if InWord then Inc(Count);

  SetLength(Result, Count);
  if Count = 0 then Exit;

  // Второй проход - заполнение токенов
  Count := 0;
  Start := 0;
  InWord := False;
  for i := 0 to Str.Length - 1 do
  begin
    if IsWhiteSpace(Str[i]) or IsPunctuation(Str[i]) then
    begin
      if InWord then
      begin
        Result[Count].Init(i - Start);
        Move(Str.FData[Start], Result[Count].FData^, (i - Start) * SizeOf(DWord));
        Inc(Count);
        InWord := False;
      end;
    end
    else if not InWord then
    begin
      Start := i;
      InWord := True;
    end;
  end;

  if InWord then
  begin
    Result[Count].Init(Str.Length - Start);
    Move(Str.FData[Start], Result[Count].FData^, (Str.Length - Start) * SizeOf(DWord));
  end;
end;

end.

Этот модуль добавляет следующие функции для работы с UCS4:

    Базовые строковые операции:

        Pos, RPos - поиск подстроки

        IfThen - условное возвращение строки

        Split, Join - разделение и объединение строк

        ToLower, ToUpper - регистр символов

        Trim - обрезка пробелов

        StartsWith, EndsWith, Contains - проверки строк

    Функции для ИИ:

        LevenshteinDistance - расстояние Левенштейна для сравнения строк

        NormalizeForAI - нормализация текста для обработки ИИ

        RemovePunctuation - удаление пунктуации

        TokenizeForNLP - токенизация для обработки естественного языка

    Дополнительные утилиты:

        Поддержка Unicode (учет регистра, диакритических знаков)

        Эффективная работа с памятью

        Оптимизированные алгоритмы

Для использования модуля добавьте его в раздел uses ваших программ. Пример использования:
pascal

uses
  ..., ucs4functionsunit;

var
  str1, str2: ucs4;
begin
  str1 := 'Привет, мир!';
  str2 := 'привет';
  
  if StartsWith(str1, str2) then
    WriteLn('Строка начинается с подстроки');
    
  WriteLn('Расстояние Левенштейна: ', 
    LevenshteinDistance(str1, str2));
end;

Модуль полностью совместим с существующими ucs4unit.pas и ucs4opunit.pas.