#ErenshorLLMDialog v0.3-2 -- LLM-Powered NPC Dialog

1 messages · Page 1 of 1 (latest)

limber magnet
#

Replaces SimPlayer canned chat with dynamic, personality-driven responses.

  • 160 named SimPlayers each have unique personality profiles --
    • archetypes, speech patterns, quirks, vocabulary
    • all grounded in real Erenshor world lore.

What it does:
SimPlayers react to game events (death, loot, combat, zone entry,
level-ups) with personality-flavored commentary instead of canned text.
The paraphrase pipeline and 2,400+ hand-crafted templates do a lot of
heavy lifting on their own -- dialog feels natural and blends into the
game. It learns and improves the more you play via adaptive search
refinement.

Best experience: Cloud mode with OpenRouter using
liquid/lfm-2.5-1.2b-instruct:free -- it's fast, free, and produces good
results. Sign up at openrouter.ai, grab an API key, set mode to Cloud, and
you're set.

Under the hood:

  • Priority queue: combat callouts are instant, whispers are critical,
    ambient chat queues gracefully
  • 2,400+ character-specific dialog templates across 11 categories
    referencing real zones, items, enemies, deities
  • Entity validation against 2,377 known game entities to prevent
    hallucinated names
  • Curated lore knowledge: deity cosmology, BiS gear, zone progression,
    faction politics

Three modes:

  • Off -- Paraphrase pipeline + templates only, no LLM needed (still a big
    improvement over vanilla)
  • Cloud -- OpenRouter with a free model, no GPU needed (recommended)
  • Local -- Runs a quantized GGUF model on your machine (GPU recommended,
    ~470 MB model)

Install:

  1. BepInEx 5.4.x installed in Erenshor
  2. Extract zip into BepInEx/plugins/
  3. Launch -- works out of the box in paraphrase mode
  4. For cloud: set LLM Mode to Cloud, add your free OpenRouter key (Best current free model: liquid/lfm-2.5-1.2b-instruct:free)

This is a work in progress -- feedback and bug reports welcome.

Download: https://github.com/aepod/ErenshorLLM/releases/tag/v0.3-3
Source & Docs: https://github.com/aepod/ErenshorLLM

queen cobalt
#

Hey, thats a very cool idea! I tried it out, its fun but (CLOUD VERSION)

  1. It spews out alot of information at once when you start up the game. Like wayyyy too much, kinda waaay out of place? Like the guild was saying 5-6 things at once, repeating same stuff, it felt just overwhelming.

  2. They do not really respond to what you are saying, it feels more like they have predefined sentences they just repeat

3)I think it goes hand in hand with 1) but the rate limit on openrouter was hit pretty much instantly. I think it didnt even take more than 3-5 Minutes, for the bepinex console to constantly say that the rate limit is exceeded.

Overall, I think its a great idea and would probably work much better on a local setup, but right now it feels very out of place with how the NPCs talk

EDIT: I was using the recommended LFM 2.5 - 1.2b instruct free Model.
I also noticed, that if you are using the cloud version, you have to type in exactly the name for the model as you have it on github, otherwise it doesnt seem to work

limber magnet
#

You can go local, there is instructions on it, grab the proper model. It works ok, I should do a demo of it on a real model. It's still rough, the idea is to get it to paraphrase and add a little more context but not go nuts. Once I get that nailed, going to work on it making more "conversation" which is a different problem. I may end up doing the advanced stats extension first, and use the output from that as vectors in the training. It's still helpful feedback to see other people trying it and running into the errors. Thank you!

#

using Grok4-fast for instance produces some pretty amazing results haha, use of lore and personality etc. So it is about the model that is being used more than the pipeline I have built that allows for it.

shy geyser
#

what models can it even handle?

#

or is that stuff done through an api? pretty much all models use different command tokens

#

what's the minimum context size for the model? etc

limber magnet
#

Any openrouter should work(within reason, don't use a vision one haha), really any openapi compatible provider should work. I've only tested with shimmy(local) and openrouter. I've tested with a lot of models on openrouter, and the frontier models work amazing. The one I use for local is 500M model, and does "ok", balancing speed for usability. There is room for improvement here still. Templates and knowledge base(lore) is all edited and fed into vectors by claude using anthropic models. It's actually pretty flexible config wise.

shy geyser
#

i meant for local models specifically, cloud models have giant context sizes anyway

limber magnet
#

qwen2.5-0.5b-instruct-q4_k_m works the best that I have found for me, you may have better results. You can also run vllm,ollama or something else, and point the cloud api in bepconfig at that endpoint (yes it's still local).

shy geyser
#

redacted really hates your mod

limber magnet
#

lol why redacted

shy geyser
#

also it doesn't work on playtest sad

limber magnet
#

I bet, it has an exe it runs under the hood, two even one for local llm, and one for the router etc. They are all rust you can see the source. It's an interesting mod, it's a great idea... but it has it's challenges.

shy geyser
#

seems to call 0x00007FFBE87C5048 (winhttp) WinHttpGetIEProxyConfigForCurrentUser which crashes the game

limber magnet
#

Yeah, it is not compatible with playtest at this point, I can probably compile a version that does. This mod touches a lot of config and harmony patches are all over the board, it's certainly brittle.

shy geyser
#

i do have that function proxied so iunno whats up

limber magnet
#

But, I am building parts of it as independent chunks, so the llm and vectors that it is using is all reusable, I will be using it for memory for advanced stats, and other mods I have. I literally have dozens planned haha, the LLM is probably the most difficult besides one or other two more content related ones.

  • Easy (1-3): 19 ideas | Medium (4-6): 53 ideas | Hard (7-10): 32 ideas
  • Source code only: 78 ideas (no Unity Editor needed)

The llm was solidly in the hard haha

shy geyser
#

oh nvm i fixed it

#

no more crashing with redacted

#

you clearly didn't add enough options

limber magnet
#

haha, sorry. i will add that as a feature request 😉

shy geyser
#
[Info] === DialogContext ===
[Info] Channel: None
[Info] Player:  (Level 0 )
[Info] Zone: 
[Info] Message: ""
[Info] Handled: False
[Info] ===================

this is as much as i got working

#

i think it tried to read my / command

limber magnet
#

Oh that is neat.

#

So, I will try and recreate that. Is the sidecar loading up, whats odd is that it doesn't have the same tags
[Info :Erenshor LLM Dialog] [EventParaphraser] Aric [generic]: "aloha" -> "aloha there, kid—back in my day we just grunted hellos while trudging through Vitheo on foot, no fancy tropical talk." (4100ms, paraphrase)
[Info :Erenshor LLM Dialog] [EventParaphraser] Garret [generic]: "WTB Spell Scroll: Moon Bolt II, offering 3500 gold. Open a trade with me." -> "WTB Moon Bolt II scroll, 3500g flat—solid leverage for the price. /trade me quick, no risk." (5023ms, paraphrase)

the paraphraser is the real gold right now. The direct responses are definetly more brittle and require more work.

#

[Info :Erenshor LLM Dialog] [EventParaphraser] Vallen [generic]: "oh there's a well here!" -> "A well. Drink your fill—my thirst is penance enough." (4687ms, paraphrase)

#

[Info :Erenshor LLM Dialog] [Sidecar] INFO erenshor_llm::routes::paraphrase: Paraphrased event 'generic' for 'Blademann' (6967ms)
[Info :Erenshor LLM Dialog] [EventParaphraser] Blademann [generic]: "I JUST SPILLED MY DRINK FFS" -> "DRINK SPILL FFS LIKE A WEAK PALADIN BLOCK." (7032ms, paraphrase)
[Info :Erenshor LLM Dialog] [Sidecar] INFO erenshor_llm::routes::paraphrase: Paraphrased event 'generic' for 'Blademann' (7474ms)
[Info :Erenshor LLM Dialog] [EventParaphraser] Blademann [generic]: "WTB A TREASURE HUNTER'S JOURNAL, OFFERING 355 GOLD. OPEN A TRADE WITH ME." -> "WTB TREASURE HUNTER'S JOURNAL IN VITHEO! 355 GOLD TO CRUSH THIS DEAL—TRADE NOW OR GET SHREDDED!" (7538ms, paraphrase)

It certainly is making BLADEMANN more exciting.

shy geyser
#

it's most likely because it failed to harmony the new chat log stuff

#

since the dll failed to load it didn't bind the config stuff correctly so i cant change any settings

untold hatch
#

was only able to run this mod using a free model by openrouter, every other method failed for reasons i cannot figure out, and all the chatter was so incredibly negative or rude, am i missing something?

limber magnet
#

So depending on how you were switching model and settings it may have been not changing much. It should not be negative or rude, although there are a few players that have that personality it is very small number (except most friends' club). Grok 4 fast on openrouter is pretty top notch, and not horribly expensive to run, like .10-15/ hour for me.

untold hatch
#

I'll do some more testing later

limber magnet
#

you typically have to restart the sidecar through the bepconfig thing to change anything for real. I often drop out of game, make changes in the config and then go back in. there is an extension in C# which is basically hooking the dialog, then the sidecar which is a router written in rust which has some cool templates, and then there is the local/cloud LLM interference which functions in two ways (full mode, which it will make up an entirely new message, doesn't happen often typically triggered from asking a simplayer something out of the ordinary. Secondly it does paraphrasing, which is pretty common, where it is just swapping out a little text to add more flavor based on personality mostly. This tends to work well more in the paraphrasing side. Watch the beplog for when you are playing with it, it should be clear when it goes full ai mode, you will see context, items, zones, guild, personality, etc passed in. The lore system is actually pretty neat, it can answer some very good questions about world history etc. Initially the goal is to get it to be able to enhance existing text, figure out what breaks fast and correct before adding a ton of features, like "tell me a story" or "do this quest with me", which will take a lot more context and memory.

nova zealot
#

Any idea on what could be causing this?

[Info :Erenshor LLM Dialog] Pipeline: [RuVectorTransform] LLM fallback: Local LLM error: Local inference server error: {"error":{"code":"model_not_found","message":"Model 'qwen2.5-0.5b-instruct-q4_k_m' not found. Available models: ["phi3-lora", "qwen2.5-0.5b-instruct-q4-k-m"]","param":"model","type":"invalid_reque (status 404)

I have the .gguf in data\models

shy geyser
nova zealot
#

I tried using the recommended cloud version, that one worked

#

Local, however, didnt

limber magnet
#

I have been using grok4-fast a lot, it works extremely well. I've not given up, just doing a few other things this week.

limber magnet
#

The mod is brought up to date with release today and working, and I even added a feature or two besides refactoring the whole chat switch over.
│ Release notes covering: │
│ - Unified GlobalAddLine hook (replaces 3 legacy hooks) │
│ - Combat template fast-path with sub-1ms lookups │
│ - Dynamic template learning via background LLM generation │
│ - 4 new template API endpoints │
│ - Zone self-reference filtering for group channels │
│ - Personality-aware variant selection │
│ - 14 classified combat callout types │
│ - Graceful degradation when sidecar is down │
│ - Compatible with Mar 10 game update; auto-fallback for older builds

https://github.com/aepod/ErenshorLLM/releases/tag/v0.3-3

GitHub

What's New
Unified Chat Hook

Single GlobalAddLine hook replaces the previous 3-hook system (AddStringForDisplayPatch, LogAddColoredPatch, LogAddPlainPatch)
Uses ChatLogLine.LogType flags for c...

minor glacier
#

This is all I get

limber magnet
#

further up when you first connect is there some more info about the sidecar? It looks like maybe you don't have a local or cloud llm configured, you need one or both of them

minor glacier
#

I had it configured to use cloud, with my API. I tried both openrouter and nanoGPT

idle nymph
#

im guessing there is no way to get this working in linux since it requires separate .exe files to run?

limber magnet
#

Oh I build it on linux, I just didn't publish the sidecar that way. I will get it added.