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_lib✅Utility library
oxmysql✅Database driver
screenshot-basic✅Vision AI captures
MariaDB / MySQL✅Data storage
sab0h_ai_server✅Node.js AI middleware (Ollama + Cartesia TTS)
Ollama✅Local 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