Skip to content

Sab0h AI Memory Core

AI-powered NPCs with memory, personality, accents & speech for FiveM

NPCs observe players, remember their appearance, respond to conversations with unique personalities, and speak with neural Text-to-Speech. Each NPC has its own memory, voice, mood, and accent.


Features

FeatureDescription
AI Witness MemoryNPCs observe suspects and generate natural descriptions
Memory DecayMemories fade over time (fresh → partial → weak → forgotten)
Neural TTS56+ Cartesia Sonic 3.5 voices with 3D Spatial Audio
AI ConversationsPlayers can chat with any NPC — AI responds context-aware
Multi-Personality22 personality types with 2–5 description variants each
Accent & Slang18 TTS accent languages, 27 slang languages mixed into speech
Mood System25 random moods influencing NPC tone and behavior
Ambient ChatterNPCs comment randomly when players walk by
Reputation SystemNPCs remember how they feel about each player (-100 to +100)
Persistent Names/VoicesEach NPC keeps its name and voice across sessions
Thinking & ReasoningNPCs build internal reasoning before responding
Vision AIOptional screenshot-based scene analysis (qwen2.5vl:7b)
Multi-FrameworkQBX, QBCore, ESX, or Standalone
Multi-LanguageEN, DE, FR, ES, PT, IT, NL, PL, TR, RU

Requirements

DependencyRequiredPurpose
ox_libUtility library
oxmysqlDatabase driver
screenshot-basicVision AI captures
MariaDB / MySQLData storage
sab0h_ai_serverNode.js AI middleware (Ollama + Cartesia TTS)
OllamaLocal LLM inference

Ollama Models:

  • llama3.1:8b — Text generation (conversations, descriptions)
  • qwen2.5vl:7b — Vision analysis (optional)

Installation

  1. Place ai_memory in your server's resources folder
  2. Import sql/install.sql into your database
  3. Configure config.lua (language, TTS, ambient, etc.)
  4. Add to your server.cfg:
    cfg
    ensure screenshot-basic
    ensure ai_memory
  5. Ensure sab0h_ai_server is running (default port 3847)
  6. Restart your server

Configuration

All user-configurable options are in config.lua. Core logic is server-side (escrowed).

General

lua
Config.Debug = false
Config.Framework = 'auto'  -- 'auto' | 'qbx' | 'qb' | 'esx' | 'standalone'
Config.Locale = 'en'       -- 'en' | 'de' | 'fr' | 'es' | 'pt' | 'nl' | 'it' | 'pl' | 'tr' | 'ru'

AI

lua
Config.AI = {
    enabled = true,  -- Master switch for AI system
}

Memory Decay

lua
Config.Memory = {
    freshDuration = 15,     -- Minutes: full detail recall
    partialDuration = 45,   -- Minutes: some details lost
    weakDuration = 90,      -- Minutes: only vague impressions
    forgetDuration = 180,   -- Minutes: memory deleted
    decayInterval = 60000,  -- ms: decay check interval
    maxPerNpc = 5,          -- Max memories per NPC
}

Witness Questioning

lua
Config.Questioning = {
    enabled = true,
    cooldown = 30,       -- Seconds between questioning attempts
    maxDistance = 5.0,   -- Max distance (meters) to NPC
    requireJob = false,  -- true = only allowedJobs can question
    allowedJobs = { 'police', 'sheriff', 'trooper', 'bcso', 'sasp', 'ranger', 'fib', 'doj' },
}

Text-to-Speech

lua
Config.TTS = {
    enabled = true,
    volume = 0.5,        -- Base volume (0.0 - 1.0)
    maxDistance = 15.0,  -- Audio falloff in meters
    animation = true,    -- NPC plays talking animation
    mode = 'both',       -- 'tts' = audio only | 'bubble' = text only | 'both'
}

Ambient Chatter

lua
Config.Ambient = {
    enabled = true,
    triggerDistance = 8.0,  -- Meters: NPC speaks when player in range
    cooldownPerNpc = 120,  -- Seconds: same NPC won't repeat
    globalCooldown = 15,   -- Seconds: minimum between ambient speech
    chance = 25,           -- Percent chance per check
    checkInterval = 3000,  -- ms: how often to check
    maxConcurrent = 1,     -- Max simultaneously speaking NPCs
}

Conversation

lua
Config.Conversation = {
    memoryTTL = 600,   -- Seconds: how long NPC remembers conversation
    maxHistory = 20,   -- Max messages per conversation
}

NPC Moods

25 possible moods randomly assigned on first contact, persisting for memoryTTL seconds. Moods influence NPC tone, word choice, and behavior.

You can add, remove, or rename moods freely:

lua
Config.NpcMoods = {
    'happy', 'grumpy', 'stressed', 'relaxed', 'bored',
    'nervous', 'cheerful', 'annoyed', 'thoughtful', 'tired',
    'suspicious', 'curious', 'angry', 'indifferent', 'excited',
    'paranoid', 'hungover', 'euphoric', 'sarcastic', 'melancholic',
    'reckless', 'absent-minded', 'desperate', 'narcissistic', 'nostalgic',
}

Customizable: Add any mood string you want. The AI will adapt its tone accordingly. No limit on how many moods you define.

Accents & Slang

The accent pool controls NPC accent distribution. Each entry is a language code — more entries = higher spawn chance.

lua
Config.Accents = {
    pool = {
        'de', 'de', 'de', 'de', 'de', 'de',  -- 30% native
        'en', 'en',                            -- 10% English
        'tr', 'tr',                            -- 10% Turkish
        'ru', 'es', 'fr', 'it', 'pl',         -- 5% each
        'nl', 'pt', 'ar',                      -- 5% each
        'ja', 'sv', 'hi', 'zh', 'ko',         -- 2.5% each
        'ro', 'el',                            -- 2.5% each
    },
}

18 TTS accent languages: DE, EN, TR, RU, ES, FR, IT, PL, NL, PT, AR, JA, SV, HI, ZH, KO, RO, EL

27 slang languages: All above + SR, UK, VI, CS, HU, AL, BG, PH, TH

When Config.Slang.enabled = true, NPCs mix native-language words into their speech (e.g., a Turkish NPC says "Wallah bro I swear on everything").

lua
Config.Slang = {
    enabled = true,  -- true = NPCs use accent-based slang | false = clean speech
}

What You Can Customize

A complete overview of everything you can change in config.lua:

SettingWhat It DoesHow to Change
Config.DebugDebug prints in consoleSet true or false
Config.FrameworkFramework detection'auto', 'qbx', 'qb', 'esx', 'standalone'
Config.LocaleLanguage of all NPC speech & prompts'en', 'de', 'fr', 'es', 'pt', 'nl', 'it', 'pl', 'tr', 'ru'
Config.AI.enabledMaster AI on/offtrue / false
Config.Memory.freshDurationMinutes with full detailAny number (default: 15)
Config.Memory.partialDurationMinutes until partial fadeAny number (default: 45)
Config.Memory.weakDurationMinutes until vagueAny number (default: 90)
Config.Memory.forgetDurationMinutes until deletedAny number (default: 180)
Config.Memory.decayIntervalDecay check rate (ms)Any number (default: 60000)
Config.Memory.maxPerNpcMax memories per NPCAny number (default: 5)
Config.Questioning.enabledWitness questioning on/offtrue / false
Config.Questioning.cooldownSeconds between questionsAny number (default: 30)
Config.Questioning.maxDistanceRange to NPC in metersAny number (default: 5.0)
Config.Questioning.requireJobJob restrictiontrue = only allowedJobs / false = everyone
Config.Questioning.allowedJobsWhich jobs can questionAdd/remove job strings
Config.TTS.enabledText-to-Speech on/offtrue / false
Config.TTS.volumeBase volume0.0 to 1.0 (default: 0.5)
Config.TTS.maxDistanceAudio range in metersAny number (default: 15.0)
Config.TTS.animationTalking animationtrue / false
Config.TTS.modeOutput mode'tts' / 'bubble' / 'both'
Config.Ambient.enabledAmbient chatter on/offtrue / false
Config.Ambient.triggerDistanceTrigger range in metersAny number (default: 8.0)
Config.Ambient.cooldownPerNpcSame-NPC repeat cooldown (sec)Any number (default: 120)
Config.Ambient.globalCooldownMin time between any chatter (sec)Any number (default: 15)
Config.Ambient.chanceTrigger chance in percent0–100 (default: 25)
Config.Ambient.checkIntervalCheck frequency (ms)Any number (default: 3000)
Config.Ambient.maxConcurrentMax NPCs talking at onceAny number (default: 1)
Config.Conversation.memoryTTLHow long NPC remembers chat (sec)Any number (default: 600)
Config.Conversation.maxHistoryMax messages per conversationAny number (default: 20)
Config.NpcMoodsList of possible NPC moodsAdd/remove any mood strings
Config.Accents.poolAccent distributionAdd/remove language codes, duplicate for higher chance
Config.Slang.enabledSlang mixing on/offtrue / false

Accent Pool — How to Adjust

The accent pool is a weighted list. The more often a code appears, the higher the chance:

lua
-- Example: 50% native, 25% Turkish, 25% Russian
Config.Accents = {
    pool = { 'en', 'en', 'tr', 'ru' },
}

Available accent codes:

CodeLanguageCodeLanguageCodeLanguage
deGermannlDutchjaJapanese
enEnglishptPortuguesesvSwedish
trTurkisharArabichiHindi
ruRussianzhChinesekoKorean
esSpanishkoKoreanroRomanian
frFrenchroRomanianelGreek
itItalianelGreek
plPolish

Moods — How to Adjust

Add any mood string. The AI interprets it freely:

lua
Config.NpcMoods = {
    'friendly', 'hostile', 'drunk', 'flirty', 'scared',
    'high', 'professional', 'crazy', 'depressed',
    -- Add as many as you want
}

Questioning Jobs — How to Adjust

lua
Config.Questioning = {
    requireJob = true,  -- Set to true to restrict
    allowedJobs = {
        'police', 'sheriff', 'trooper', 'bcso',
        'sasp', 'ranger', 'fib', 'doj',
        -- Add your custom law enforcement jobs here
    },
}

Per-NPC Customization (via Exports)

Beyond config.lua, you can customize individual NPCs at runtime:

ExportWhat It Does
SetNpcName(npcId, name)Override auto-generated name
SetNpcInfo(npcId, text)Give NPC custom knowledge/backstory
SetReputation(npcId, src, val)Set starting reputation (-100 to +100)
RegisterNpc(ped, key)Make NPC persistent across sessions

Interaction

The system auto-detects your target system:

SystemBehavior
ox_targetGlobal ped option "Talk"
qb-targetGlobal ped option "Talk"
NoneE-key fallback with proximity detection

Exports

Client Exports

lua
-- Register NPC (for persistent tracking)
exports['ai_memory']:RegisterNpc(ped, 'shop_owner_grove')

-- Unregister NPC
exports['ai_memory']:UnregisterNpc(ped)

-- Get NPC ID (registered key or auto-generated)
local id = exports['ai_memory']:GetNpcId(ped)

-- Make witness observe (clothing, props, vehicle, weapon)
exports['ai_memory']:CaptureAppearance(witnessPed, suspectPed, npcId)

-- Start witness questioning
exports['ai_memory']:QuestionWitness(npcPed)

-- Audio playback
exports['ai_memory']:PlayNpcAudio(url, coords, options)
exports['ai_memory']:StopNpcAudio(npcId)
exports['ai_memory']:StopAllAudio()
exports['ai_memory']:SetSpeakerPed(ped)

Server Exports — Memory

lua
-- Store observation
local memId = exports['ai_memory']:StoreObservation(npcId, observation, confidence)

-- Get all NPC memories
local memories = exports['ai_memory']:GetMemories(npcId)

-- Generate witness statement
local result = exports['ai_memory']:GetStatement(npcId)
-- Returns: { statement = "...", reliability = "high"|"medium"|"low" }

-- Clear memories
exports['ai_memory']:ClearMemories(npcId)

-- Force immediate decay
local stats = exports['ai_memory']:ForceDecay()
-- Returns: { processed, transitioned, forgotten }

Server Exports — Reputation

lua
-- Get reputation
local rep, level, interactions = exports['ai_memory']:GetReputation(npcId, source)
-- level: 'hostile' | 'unfriendly' | 'neutral' | 'friendly' | 'allied'

-- Modify reputation (+/- points)
local newRep, newLevel = exports['ai_memory']:ModifyReputation(npcId, source, amount, event)

-- Set reputation to exact value (-100 to +100)
exports['ai_memory']:SetReputation(npcId, source, value, event)

-- Reset reputation (single player)
exports['ai_memory']:ResetReputation(npcId, source)

-- Reset all reputations for an NPC
exports['ai_memory']:ResetNpcReputation(npcId)

-- List all reputations for an NPC (admin/debug)
local all = exports['ai_memory']:GetAllReputations(npcId)

Server Exports — Speech (TTS)

lua
-- NPC says specific text
local success, audioUrl, duration = exports['ai_memory']:NpcSay(
    npcId, "Hello!", coords, 'npc_en', { isFemale = false }
)

-- NPC says reputation-based line
local success, text, level = exports['ai_memory']:NpcSayByReputation(
    npcId, source, 'greeting', coords
)

-- NPC says AI-generated text based on context
local success, text = exports['ai_memory']:NpcSayAI(
    npcId, source, "Player was carrying crates nearby", coords
)

-- Trigger reputation event (changes rep + NPC reacts)
local success, newRep, text = exports['ai_memory']:NpcReact(
    npcId, source, 'robbery', coords
)

Server Exports — NPC Info

lua
-- Set custom knowledge for NPC (used in conversations)
exports['ai_memory']:SetNpcInfo(npcId, "I'm the owner of Benny's auto shop.")

-- Get custom info
local info = exports['ai_memory']:GetNpcInfo(npcId)

-- Remove custom info
exports['ai_memory']:RemoveNpcInfo(npcId)

-- Set custom name (overrides auto-generated name)
exports['ai_memory']:SetNpcName(npcId, 'Benny')

-- Get current NPC name
local name = exports['ai_memory']:GetNpcName(npcId)

Usage Examples

NPCs witness a robbery

lua
-- Client: nearby NPCs become witnesses
local playerPed = PlayerPedId()
for _, npcPed in ipairs(nearbyPeds) do
    if HasClearLineOfSight(npcPed, playerPed) then
        exports['ai_memory']:CaptureAppearance(npcPed, playerPed)
    end
end

Police questions a witness

lua
exports['ai_memory']:QuestionWitness(targetPed)
-- NPC speaks their memory via TTS with spatial audio

Custom NPC for a shop script

lua
-- Server-side on spawn:
exports['ai_memory']:SetNpcName(npcId, 'Carlos')
exports['ai_memory']:SetNpcInfo(npcId, "You are Carlos, owner of the 24/7 in Strawberry. You complain about shoplifters.")

-- Players can now talk to Carlos and he responds in character

Reputation-based reaction

lua
-- Server: player robs NPC
exports['ai_memory']:NpcReact(npcId, source, 'robbery', npcCoords)
-- → Reputation drops, NPC says aggressive line via TTS

TTS Voices

Voices are automatically assigned per NPC-ID hash and remain persistent. The system uses Cartesia Sonic 3.5 with 56+ voice roles across 18 languages.

Each accent has 2 male + 2 female voices (some have 4+ per gender). Voice assignment is deterministic — the same NPC always gets the same voice.

Override per export: NpcSay(npcId, text, coords, 'npc_en')


Memory Stages

StageDurationDescription
fresh0–15 minFull details, high confidence
partial15–45 minSome details lost
weak45–90 minOnly vague impressions
forgotten90+ minMemory deleted

Confidence is additionally affected by: distance, darkness, weather, masks.


Personality System

Each GTA ped model is mapped to one or more personality types. On first interaction, a personality is randomly selected and cached for the NPC's lifetime.

22 personality types: business, criminal, friendly, aggressive, shy, arrogant, street, party, intellectual, paranoid, religious, hipster, athlete, artist, conspiracy, stoner, veteran, tourist, homeless, rich, corrupt, romantic

Each type has 2–5 description variants ensuring unique behavior even among same-type NPCs.


Database

Two tables (auto-created via sql/install.sql):

TablePurpose
npc_memoriesObservations, AI descriptions, decay stage, locale
npc_reputationReputation per NPC-player pair (-100 to +100)

File Structure

ai_memory/
├── config.lua                 -- Configuration (user settings only)
├── fxmanifest.lua
├── sql/
│   └── install.sql            -- Database schema
├── bridge/
│   ├── shared.lua             -- Framework detection
│   ├── server.lua             -- Server bridge (GetPlayer, IsOfficer)
│   └── client.lua             -- Client bridge
├── server/
│   ├── main.lua               -- Prompt building, personality, conversation handler
│   ├── accents.lua            -- Accent origin/slang data (27 languages)
│   ├── store.lua              -- Database CRUD + cache
│   ├── witness.lua            -- Witness statement generation
│   ├── ai.lua                 -- AI description (Vision + Text)
│   ├── reputation.lua         -- Reputation system
│   ├── speech.lua             -- NPC dialogue
│   ├── decay.lua              -- Memory degradation
│   ├── tts.lua                -- TTS generation + cache
│   ├── tts_broadcast.lua      -- Audio broadcast to players
│   └── ollama.lua             -- AI backend connection
├── client/
│   ├── main.lua               -- NPC registration, observations, questioning
│   ├── capture.lua            -- Appearance capture (clothing, props, screenshot)
│   ├── ambient.lua            -- Ambient chatter + NPC interaction
│   └── tts.lua                -- Audio playback, 3D spatial audio
└── nui/
    └── index.html             -- Chat UI + Web Audio API

License

Proprietary — All rights reserved. Escrow-protected server code.


Made by Sab0h

Saboh Scripts - Premium FiveM Resources