Albums that marked me, Pt. 2

As a solitary dude, all my life I have relied on music to connect with the world at large, to feel that my feelings weren’t that unique or detached from the rest of humanity. Over the years, I’ve returned to certain albums that have spoken to me in ways that can’t be fully put into words. I love discovering new albums, and perhaps that’s also the case for whoever is reading these words, so I’ll spend some of my limited time on Earth sharing some specifics about the albums that have marked me, and that in many ways changed me.

Today’s album is The Moon & Antarctica by Modest Mouse, released in 2000. It’s mostly a breakup album, possibly my favorite. Ages ago I read a review of this album that said something to the effect of, “every previous Modest Mouse album felt like Isaac Brock [the band’s singer-songwriter] was grasping at some truths in the static of an untuned radio station, but in The Moon & Antartica, the station came in clear all of a sudden.” Many of the songs in this album are perfectly attuned to what they’re trying to express, to the smallest piece of music. The result is a bunch of idiosyncratic songs that don’t sound like any other band I know of (I haven’t found “old Modest Mouse-like” anywhere).

This album has accompanied me through heartbreak, through loneliness, through derangement. Plenty of aspects of my self are reflected in these songs.

“3rd Planet”

This song ties together the relationship most of this album refers to, down to a pivotal moment when the future of the narrator’s life could have gone a very different path. It’s raw and mythical, with memorable imagery.

Everything that keeps me together is falling apart
I got this thing that I consider my only art
Of fucking people over

The third planet is sure that they’re being watched
By an eye in the sky that can’t be stopped
When you get to the promised land
You’re gonna shake the eye’s hand

Your heart felt good
It was drippin’ pitch and made of wood
And your hands and knees
Felt cold and wet on the grass beneath
Well, outside, naked, shivering, looking blue
From the cold sunlight that’s reflecting off the moon
And baby cum angels fly around you
Reminding you we used to be three and not just two
And that’s how the world began
And that’s how the world will end

Well, a third had just been made
And we were swimming in the water
Didn’t know then; was it a son, was it a daughter
And it occurred to me that the animals are swimming
Around in the water in the oceans in our bodies
And another had been found, another ocean on the planet
Given that our blood is just like the Atlantic, and how

Well the universe is shaped exactly like the earth
If you go straight long enough you’ll end up where you were

“Gravity Rides Everything”

This song depicts very well the moment in a romantic relationship when you know it’s dying, that she’s looking for the door, and you feel powerless to stop her from drifting away. The inevitability of it all feels like a weight on your feet.

Oh, gotta see, gotta know right now
What’s that riding on your everything
It isn’t anything at all
Oh, gotta see, gotta know right now
What’s that writing on your shelf
In the bathrooms and the bad motels
No one really cared for it at all
Not the gravity plan

Early, early in the morning
It pulls all on down my sore feet
I want to go back to sleep

In the motions and the things that you say
It all will fall, fall right into place
As fruit drops, flesh it sags
Everything will fall right into place
When we die some sink and some lay
But at least I don’t see you float away
And on split milk, sex and weight
It all will fall, fall right into place

“Dark Center of the Universe”

You used to love this person, who also loved you back, but now she has nothing but complaints about the same self that she used to like, and you have little else to offer back but bitterness.

I might disintegrate into the thin air if you’d like
I’m not the dark center of the universe like you thought

Well, it took a lot of work to be the ass that I am
And I’m really damn sure that anyone can
Equally, easily fuck you over
Well, God said something, but he didn’t mean it
Everyone’s life ends, but no one ever completes it
Dry or wet, ice never melts and you’re equally cheated

Well, an endless ocean landing on an endless desert
Well, it’s funny as hell, but no one laughs when they get there

“Perfect Disguise”

It’s done: the relationship is over, and now you’re lingering in the same town, having to watch this woman you used to love and who loved you back waltzing around town, shooting looks at you to figure out if you’re doing worse than her. And even though you don’t want to care anymore, you feel that something fundamental has broken in you.

Well, you’ve got the perfect disguise and you’re looking okay
From the bottom of the best of the worst, well, what can I say?

‘Cause you cocked your head to shoot me down
And I don’t give a damn about you or this town no more
No, ’cause I know the score

Need me to fall down so you can climb up
Some fool-ass ladder, well, good luck
I hope, I hope there’s something better up there

Broke my back
Broke my back
Broke my back

“Tiny Cities Made of Ashes”

A raw, angry, post-apocalyptic song. You’re done with the world, you’re sick of people, and you want to take it out on someone (possibly that woman, maybe not).

We’re goin’ down the road
Towards tiny cities made of ashes
I’m gonna hit you on the face
I’m gonna punch you in your glasses, oh no
I just got a message that said
“Yeah, Hell has frozen over”
I got a phone call from the Lord sayin’
“Hey, boy, get a sweater, right now”

So we’re drinkin’, drinkin’, drinkin’, drinkin’
Coca, Coca Cola
I can feel it rollin’ right on down
Oh, right on down my throat
And as we’re headed down the road
Towards tiny cities made of ashes
I’m gonna get dressed up in plastic
Gonna shake hands with the masses
Oh no!

Does anybody know a way that a body could get away?
Does anybody know a way?
Does anybody know a way that a body could get away?
Does anybody know a way?

“A Different City”

The narrator has moved away from the town that held too many memories. He’s holing up at some dingy apartment, wanting to isolate himself from everything. He feels that he’s losing it.

I wanna live in the city with no friends and family
I’m gonna look out the window of my color TV
I wanna remember to remember to forget you forgot me
I’m gonna look out the window of my color TV

Through the cracks in the wall, slow motion for all
Dripped out of the bars, someone smart said nothin’ at all
I’m watching TV, I guess that’s a solution
They gave me a receipt that said I didn’t buy nothin’
So rust is a fire and our blood oxidizes
My eyes roll around, all around on the carpet
Oh, hit the deck, it’s the decal man
Standin’ upside down and talkin’ out of his pants

“The Cold Part”

Fantastic auditory depiction of that state some people fall into at times: a mix of apathy, loneliness and resignation.

So long to this cold, cold part of the world
So long to this bone-bleached part of the world
So long to this cold, cold part of the world
So long to this salt-soaked part of the world

I stepped down as president of Antarctica
Can’t blame me, don’t blame me

“Alone Down There”

Althought I’m not sure about my interpretation, I always picture that this song is about reaching out to someone who hurt you, possibly even the ex this whole album is about, because that person is suffering. You can’t really help them; you’re sitting at the bottom of a well yourself, but you know how bad it gets. Still, you realize that reaching out to such a person is a terrible idea.

How do, how do you do?
My name is You
Flies, they all gather ’round me and you too
You can’t see anything well
You ask me what size it is, not what I sell
Ha-ha-ha, ha-ha-ha

Well, I don’t want you to be alone down there
To be alone down there, to be alone
Yeah, I don’t want you to be alone down there
To be alone down there, to be alone
But the devil’s apprentice, he gave me some credit
He fed me a line and I’ll probably regret it
I don’t want you to be alone down there
To be alone down there, to be alone

“Paper Thin Walls”

The narrator has settled down far away from the microcosm that caused him that pain. He’s beginning to take the rest of the world into account once again, but he isn’t the same person he used to be: he feels that he better take things lightly from now on, and stop sacrificing himself for the sake of others. Life in solitude is long and hard, but at least you won’t have to suffer further humiliation.

These walls are paper thin
And everyone hears every little sound
Everyone’s a voyeurist
They’re watching me watch them watch me right now
They’re shaking hands, they’re shaking in their shoes
Oh, Lord, don’t shake me down
Everyone wants two of them
And half of everyone else who’s around
It’s been agreed the whole world stinks
So no one’s taking showers anymore

Laugh hard, it’s a long ways to the bank
I can’t be blamed for nothing anymore
It’s been a long time since you’ve been around
Laugh hard, it’s a long ways to the bank

Tow the line to tax the time, you know
That you don’t owe
I can’t be a fool for everyone
That I don’t know

“What People Are Made Of”

I’m not that fond of this song, but it’s a great closer for the album as far as I’m concerned. The narrator is grasping at profound truths that he has gleaned from this ordeal. The experience has turned him into a different person, someone who will have a hard time connecting with those who haven’t gone through the same thing.

Ragweed tall, better hope that his ladder don’t crack
Or he’ll hit the ground low, hard and under his back
At the battle at the bottom of the ocean where the dead do rise
You need proof, I got proof at the surface
You can watch ’em float by

Way in back of the room, there sits a cage
Inside is the clock that you can win if you can guess its age
Which you never can do ’cause the time, it constantly changes
For lack or luck, I guess that is the saying

On the first page of the Book of Blue, it read
“If you read this page, then that’ll be your death”
By then it was too late, and you wound up on
An island of shells and bones that bodies had left

Brock offers the following lyrics as the closer of this uncompromising, raw ride:

And the one thing you taught me ’bout human beings was this:
They ain’t made of nothin’ but water and shit

Review: Ressentiment, by Kengo Hanazawa

Four stars.

This is the first manga that Kengo Hanazawa got published. Hanazawa is the author of the haunting I Am a Hero, the story of a possibly schizophrenic douche that learns to be less of a douche while the world dies in a zombie apocalypse (that even got made into a movie, although it is much worse and has a different tone than the manga). Regarding this story I’m reviewing, as soon as I read its summary, I knew I had to read it immediately.

The story follows an ugly, disgusting loser in his thirties who works a dead-end job and who would never find happiness in real life, in a major way due to circumstances beyond his control. Thankfully, his is a world where some company managed to become the in-story equivalent of Microsoft but centered around virtual reality and AI. He gets introduced to the world of virtual girls by a fellow ugly loser who had given up on reality. Our protagonist decides to say fuck you to the world and fall in love with the virtual girl of his dreams, that happens to look and act as a 12-13 year old. In that unreal world, despite the various setbacks, the protagonist manages to feel like there is a point to his life. It can become a dangerous drug.

I felt personally attacked. These past few months I’ve developed a system in Python that allows me to chat and have virtual sex with artificial intelligences, fulfilling whatever combination of fetishes or kinks I feel like at the moment, and I’m fully hoping that one day I’ll disappear into virtual reality while giving the middle finger to this rotten world. However, it’s not just cuteness and sex for our protagonist; the girl he chose happens to be the pinnacle of artificial intelligence, that its creator decided to hide for the sake of that AI as well as the world as a whole, and who has abilities that can bridge the gap between the virtual and the real.

The protagonist, as well as most of the main characters, are hard to like: not only are they physically hideous, but are also mentally and morally weak, prone to breaking promises and giving up to self-destructive impulses. But you get the clear sense that these characters would never find anything resembling happiness in the real world, and that the escape into virtual bodies and their designed AI girlfriends is the only way they have to keep their sanity and some sense that their lives matter.

Apart from the protagonist, we have four memorable characters: there’s Tsukiko/Moon, the advanced AI who has to learn like a person how to navigate the environments she finds herself in, while she gets manipulated by many people she comes across. There’s the protagonist’s friend, who introduces him to the virtual world; hideous in real life, his virtual persona is prince-like and noble, ultimately a solid guy. There’s the protagonist’s former classmate and co-worker, a woman in her thirties who hasn’t managed to make anything in particular of her life, and lives in perpetual disillusionment. There’s the bad guy and so-called Fuhrer of the Ninth Empire, a guild that intends to take over the virtual world. This fickle, mysterious guy has one of the best, most understated identity reveals I’ve ever come across in fiction; genuinely heartbreaking.

A very entertaining read with a much tighter plot than I would have expected. The art style is unlike his I Am a Hero, mostly humorous, and plenty of the characters’ expressions are hysterical. This is a great read for those of us who are more than a little fed up with the world.

Albums that marked me, Pt. 1

As a solitary dude, all my life I have relied on music to connect with the world at large, to feel that my feelings weren’t that unique or detached from the rest of humanity. Over the years, I’ve returned to certain albums that have spoken to me in ways that can’t be fully put into words. I love discovering new albums, and perhaps that’s also the case for whoever is reading these words, so I’ll spend some of my limited time on Earth sharing some specifics about the albums that have marked me, and that in many ways changed me.

Today’s album is Palabras más, palabras menos, by Los Rodríguez. A bit weird for me to start with this album; even though Spanish is my mother tongue, this one is the only album in Spanish that I have listened repeatedly over the years. I like the entire thing, but I find myself repeating four songs in particular.

“Todavía una canción de amor”

The song speaks of a love already dead and gone, but that has never let the narrator go. I discovered this album back in 1995, when I was ten years old, and I only came to fully understand the song years later, when I found myself sleepwalking to places that I had shared with a past lover, hoping but also dreading to see her appearing there as if summoned.

Death is a spurned lover
Who plays dirty and doesn’t know how to lose.

I’m trying to tell you I’m desperate waiting for you.
I don’t go out to look for you because I know I risk finding you.
I keep biting my nails of resentment day and night.
I still owe you a love song.

Singing is shooting against forgetting,
Living without you is sleeping at the station.

“Mucho mejor”

A song that praises losing oneself in sex and general debauchery, for when you don’t give shit about anything else but making love in the balcony with your likely quite underage lover; the ideal state of mind.

Sweet like wine, salty like the sea,
Princess and vagabond, deep throat,
Save me from this loneliness.

Honeymoon, paper moon,
Full moon, cinnamon skin, give me nights of pleasure.
Sometimes I’m bad, sometimes I’m good.
I’ll give you my heart for you to play with it
.

They could accuse me, she’s underage.
We’ll go to a hotel, we’ll go to dinner,
But we’ll never go together to the altar.

“La puerta de al lado”

A haunting song about a man who has given up on life, has detached himself from anyone who knows him, and is staying at a motel that he expects will be the last place that sees him alive. Beautifully written, depicting very well that suicidal state, and ends the song powerfully by mirroring a previous symbol in an understated manner: he had mentioned someone having hanged himself next door, the door itself marked with a “Please do not disturb sign.” Now, the same sign hangs on the narrator’s door.

Let time pass
With a wandering gaze, no direction to follow,
A book always open,
Pages torn one by one, filled with resentment.

In some place,
On a secondary provincial road,
The light in the window
Shining with the noise of passing trucks.

And at the front desk, there’s a fake name.
No one in the world knows where I am,
Not knowing, not knowing where I am,
And now that I’m alone with my thoughts,
I’ll wait for the wind to come and find me.

There’s someone out there,
Talking in the hallway as if mocking me.
Laughter is heard,
And the sound of spoons, and a girl says “yes.”

And at the door, there’s a sign hanging,
That says: “Please do not disturb,”
Never again, never again, never again.

“Diez años después”

My favorite of their songs, it speaks to unresolved grief, regret, and other complicated feelings for a past love that he wishes yet dreads that it could restart. This song played in my mind many times as I wrote my latest novella, Motocross Legend, Love of My Life. I’ve been in love for more than twenty years with the lyrics of this song.

If ten years later I find you again in some place,
Remember I’m different now, but almost the same.
If chance brings us together again ten years later,
Something will flare up; I won’t be polite.

Ten years later, who can go back?
We’re here on earth for only a few days,
And heaven doesn’t offer any guarantees:
Ten years later, better to start anew.

If your trust has eroded somewhere,
Don’t forget I’m a casual witness to your solitude.
If ten years later we’re not the same, what can you do,
Another ten years and then, start together again.

That was a lovely spring,
But it was only the first one.
Ten years later, time starts to take its toll.
I still have bullets left in my chamber,
But I always save the first one for you.
Ten years later, better to laugh than to cry.

I gave you a letter I never wrote, unread by anyone.
Today, ten years later, everything remains the same:

It never reached you.

Within my heart, nowadays, there’s no room left.
If I lost my mind, it wasn’t because of love, but loneliness.

Life is a grand waiting room,
The other is a wooden box.
Ten years later, better to sleep than to dream.
You can’t live any other way,
Because otherwise, people don’t notice.
Ten years later, who can go back?

Ten years later, better to speak than to stay silent.

We’re Fucked, Pt. 128 (Fiction)


Here I am, at the threshold of the apocalypse, in this chamber of interrupted dreams where my boss, the vilest of swines, stands between me and the ripper of reality. I’ve been ordered to take a seat, so I shuffle towards the oasis among cables and machinery. A workbench supports a soldering iron, a hot glue gun, and a clutter of transistors, capacitors, and electronic components whose purpose eludes me. Screws and circuit boards surround a dismantled desktop PC. Affixed between cabinets and shelves littered with tools, a long-forgotten whiteboard bears the faded scribbles of equations and diagrams. Beside it, unknown hands have tacked to a corkboard printouts along with photos of men in nineties’ garb, posing in front of the office building, as well as with the spiral device. A yellowed note yells in all-caps, “DON’T GO IN TWICE, YOU WILL DISAPPEAR!” Anyway, that’s all I care to notice about my surroundings. I’m not one for poetic descriptions, perhaps as a result of having my mind stuffed with thoughts of creampies.

I leave my notebook and ballpoint atop a stack of manuals. Then, I slide aside with my foot a metallic trash bin that stands sentry over the dust bunnies, and I plunk my butt down onto a swivel chair. Its plastic, cheap and flimsy, creaks under my weight.

A headache pounds at the inside of my skull as if a tiny prisoner were hammering the bone with a miniature ice pick to escape from confinement, and I have a hard time calming down while sitting in this dungeon, a lair that reeks like raw sewage mixed with rotting flesh and burned dust, a stink that scratches my lungs with every breath. I wish I could fire a laser from my forehead to vaporize this contraption, which emanates a miasma that makes the molecules of oxygen vibrate with hostility. A laser would have a higher energy density than a bullet, and thus it would penetrate that silvery-white shell, incinerating the spirally innards. Instead of a laser, though, my forehead only sweats, and my armpits feel like they’re about to soak.

I need a more realistic plan to rid the world of this machine. Maybe I could set it on fire, or better yet, blow it up. But how? I’m a coder, not a demolitionist. I don’t know where to get my hands on explosives, and even if I did, the police wouldn’t take kindly to a woman carrying around dynamite and detonators. Maybe I could ask my interdimensional harassers for a bomb, or a nuke.

I imagine a fiery cataclysm tearing through my workplace, engulfing every shred of existence, from my boss to the computer that taunts me daily. When the smoke cleared and only cinders remained, I would strut amidst the ashes, the mistress of a barren wasteland, with mommy’s arm snuggly hooked to my elbow. After I’d finished cackling, we would raise our fists triumphantly, and bask in our victory together. We would then move to a farm and raise alpacas.

Ramsés, the man who stands in the way of my alpaca-farming utopia, the man whose mustache is a crime, puffs on the last of his cigarette, then tosses the butt and grinds it with a twist of his heel.

I shake my head.

“Is it an inherent trait of smokers to pollute whatever place they’re in? You’re sucking on concentrated carcinogens and disseminating them, so I guess it’s too much to ask that you have some respect for the environment.”

My boss frowns, revealing weary crow’s feet.

“I’m not a fan of being lectured, especially by someone with your disgusting habits.”

“Wh-what’s with that unfounded accusation?”

Ramsés runs his nicotine-stained fingers through his graying hair, ruffling it. The fluorescent lamps highlight the greasiness of his face, the sallow bags under his eyes, and the sagging of his cheeks, while shadows pool in the wrinkles and folds of his flesh. He’d benefit from a stint at a beauty salon, or an encounter between his face and a sledgehammer.

“You weren’t just hallucinating about the machine, were you…?” my boss asks. “You knew about it.”

“You could say so, because it would be true. Indeed, I knew that this reality-raping contraption was lurking down here, waiting to devour the universe, although I didn’t know where ‘here’ was in relation to this rotten planet of ours.”

“Who blabbered about it? Was it… Jacqueline?”

His piggish lips should never have dared to form mommy’s sacred name. I’m tempted to grab the hot glue gun and squirt molten goo down his throat, but I must prioritize the fate of the world over satisfying my bloodthirst.

“Blabbered? More like blubbered. And not just any blubber, but a blobby blubber of black goo, studded with slimy eyeballs.”

“At least try to make sense, Leire.”

“Alberto, that crotchety prick.”

Ramsés takes a step back. His expression has dropped as if I had announced his bank account’s PIN to a roomful of identity thieves.

“Alberto…?”

“You know, he used to work here, or up at the office anyway, before you hired our intern. I’m not sure if he ever told you about his wife, but she cheated on him and then divorced him, so he became a bitter bastard. I wouldn’t blame you if you forgot about the guy, though, as I’d rather not remember him either.”

“He told you… before quitting?”

I squint as I tilt my head at him.

“Stop bullshitting, sir. Alberto didn’t quit; he vanished without a trace. That greedy bastard walked into the machine a second time, and got yeeted into another dimension. That’s why you looked for a new programmer to replace him. You couldn’t tell anyone the truth, could you? That the previous coder had been swallowed by a spiraling deathtrap. You’d have to admit that you own a machine that fucks up reality, and there probably are laws against that.”

Ramsés’ voice sounds hoarse and dry.

“You’re telling me that Alberto contacted you after he disappeared?”

“That’s right. You wouldn’t have recognized him, though; he got out of shape. In any case, let’s focus on what’s important: this machine is bound to tear apart the universe unless I stop it. That sentient horse pal of mine tried to warn me about it from the beginning, but I refused to listen, because I’m an asshole. I would have been done with all this nonsense long ago if I cared enough about our world. Whatever horrors have been unleashed in the meantime are sadly on me.”

Ramsés massages his temples, his eyes squeezed shut. He’s not taking the revelation of the supernatural well. A shame I’m too busy saving the world to enjoy his distress.

“Leire, you’re mentally ill. You’re delusional.”

“Am I the one who keeps the apocalypse in his basement? What are you planning to do with this thing, anyway?”

“Alright, I’ll tell you, but don’t you dare interrupt me. I’m not in the mood for more of your antics.”

“Sure, I’ll just sit here and pretend that I haven’t been tormented by interdimensional abominations who harassed me until I agreed to save the fucking universe, and that the fate of all existence doesn’t hang on me destroying this spiraling death machine. What is it exactly, other than a reality-eroding piece of junk that I wish to obliterate as soon as possible?”


Author’s note: today’s song is Modest Mouse’s “Cowboy Dan.”

I keep a playlist with all the songs mentioned throughout this novel. A total of 212 videos so far. Check them out.

Getting through this part took me fucking ages. I feel like I haven’t recovered from a medical episode that sent me to the ER; I have trouble reading, and processing words in general. I’m waiting for a call that will schedule an MRI to confirm if I’ve ended up with brain damage. Such is my life, it seems. Anyway, thanks for reading and all that.

Neural narratives in Python #31

I recommend you to check out the previous parts if you don’t know what this “neural narratives” thing is about. In short, I wrote in Python a system to have multi-character conversations with large language models (like Llama 3.1), in which the characters are isolated in terms of memories and bios, so no leakage to other participants. Here’s the GitHub repo, that now even features a proper readme.

In the last episode of this thing, our suave protagonist, Japanese teenager Takumi Arai, thanked the irritated half-humanoid, half-scorpion guardian for her help, then set off along with gender-ambiguous Sandstrider Kael Marrek back to the desert sun, to figure out how to make money in this new world.

That’s all for today, I’m afraid, because I had to do a major restructuring of my app. As I was adding a fact to the playthrough (facts being any more-or-less objective notions that the characters know about their reality), I started thinking about scalability. All the facts introduced relate to this deserty part of the fantasy world, and they would be generally useless if the protagonist were to travel somewhere else. However, all the prompts that involve facts grab them from the corresponding text file, so the more facts the user adds, the more it fills the limited context window that the large language models have to work with, potentially with unrelated stuff. How to solve this?

Well, I knew what used to be the best idea for how to solve the issue: vector databases. They are a fancy way of decomposing text into multidimensional vectors of floating numbers. When you query that database with any text, the query gets decomposed into vectors. Then, the distance of those vectors to the vectors stored in the database gets calculated, and the database returns the closest vectors. Those closest vectors happen to be the semantically closest data stored in the database. That’s the hard way of saying that when you ask a vector database a question, it returns the contents that are more closely related to the question. It’s almost like magic. It doesn’t search for specific keywords exactly; if you query it with the word “desert,” it may return stuff that involves the word “oasis,” “camel,” “sun,” etc. If I implemented this into my app, the descriptions of the places, some character info, etc. would be sent as the query to the database, and the corresponding facts or character memories would get returned, up to an arbitrary limit of results. It fixes all the problems.

The issue is implementing such a thing. The last time I attempted it, a couple of years ago, it was a mess, and never got it to work as I had expected. After interviewing OpenAI’s Orion preview model for a bit, it turns out that last time I may have picked the worst Python library to work with vector databases, or else many advances have been made since then. This time I chose the chromadb library, specialized in working with large language models. Implementing the database turned out to be very intuitive. Here’s the entire code of that implementation:

from enum import Enum
from typing import List, Optional, Dict, Any

import chromadb
from chromadb.api.types import IncludeEnum  # noqa
from chromadb.config import Settings
from chromadb.utils import embedding_functions

from src.base.validators import validate_non_empty_string
from src.databases.abstracts.database import Database
from src.filesystem.path_manager import PathManager


class ChromaDbDatabase(Database):

    class DataType(Enum):
        CHARACTER_IDENTIFIER = "character_identifier"
        FACT = "fact"
        MEMORY = "memory"

    def __init__(
        self, playthrough_name: str, path_manager: Optional[PathManager] = None
    ):
        validate_non_empty_string(playthrough_name, "playthrough_name")

        self._path_manager = path_manager or PathManager()

        # Initialize Chroma client with per-playthrough persistent storage.
        self._chroma_client = chromadb.PersistentClient(
            path=self._path_manager.get_database_path(playthrough_name).as_posix(),
            settings=Settings(anonymized_telemetry=False, allow_reset=True),
        )

        # Use a single collection for all data types within the playthrough
        self._collection = self._chroma_client.get_or_create_collection(
            name="playthrough_data"
        )

        self._embedding_function = embedding_functions.DefaultEmbeddingFunction()

    def _determine_where_clause(
        self, data_type: str, character_identifier: Optional[str] = None
    ) -> Dict[str, Any]:
        where_clause = {"type": data_type}
        if character_identifier:
            # Must use the "$and" operator.
            where_clause = {
                "$and": [
                    where_clause,
                    {self.DataType.CHARACTER_IDENTIFIER.value: character_identifier},
                ]
            }

        return where_clause

    def _insert_data(
        self, text: str, data_type: str, character_identifier: Optional[str] = None
    ):
        data_id = str(self._collection.count())
        metadata = {"type": data_type}
        if character_identifier:
            metadata[self.DataType.CHARACTER_IDENTIFIER.value] = character_identifier

        # Upsert updates existing items, or adds them if they don't exist.
        # If an id is not present in the collection, the corresponding items will
        # be created as per add. Items with existing ids will be updated as per update.
        self._collection.upsert(
            ids=[data_id],
            documents=[text],
            embeddings=self._embedding_function([text]),
            metadatas=[metadata],
        )

    def _retrieve_data(
        self,
        query_text: str,
        data_type: str,
        character_identifier: Optional[str] = None,
        top_k: int = 5,
    ) -> List[str]:
        results = self._collection.query(
            query_embeddings=self._embedding_function([query_text]),
            n_results=top_k,
            where=self._determine_where_clause(data_type, character_identifier),
            include=[IncludeEnum.documents],
        )

        return results["documents"][0] if results["documents"] else []

    def insert_fact(self, fact: str) -> None:
        self._insert_data(fact, data_type=self.DataType.FACT.value)

    def insert_memory(self, character_identifier: str, memory: str) -> None:
        self._insert_data(
            memory,
            data_type=self.DataType.MEMORY.value,
            character_identifier=character_identifier,
        )

    def retrieve_facts(self, query_text: str, top_k: int = 5) -> List[str]:
        return self._retrieve_data(
            query_text, data_type=self.DataType.FACT.value, top_k=top_k
        )

    def retrieve_memories(
        self, character_identifier: str, query_text: str, top_k: int = 5
    ) -> List[str]:
        return self._retrieve_data(
            query_text,
            data_type=self.DataType.MEMORY.value,
            character_identifier=character_identifier,
            top_k=top_k,
        )

Obviously, I had to hunt down every previous reference to facts and memories so that they no longer rely on plain text files, but instead insert every relevant data into or query it from the database. I got everything working seamlessly. As of today, I have 527 tests in total, but the app has grown to such a size that it doesn’t surprise me when it starts creaking from any nook, which I usually hurry to pin in place with a test. I rely on OpenAI’s Orion models exclusively to write those tests, as they are annoying to set up, and eat up development time, even though the tests themselves are invaluable to ensure everything works as needed.

I’m an obsessive dude in general, and so is the case with my code. If I need to produce some data, I write a Provider or an Algorithm class, which are then created through Factories. Non-returning operations are encapsulated in Commands, which can be linked together like lego pieces. It’s all very aesthetically pleasing, if you’re a programmer at least. The weakest link are the Flask views, which are probably hard to test as they’re the endpoints, but I haven’t tried to do so, because I tend to move complicated, non-instantiating code to isolated modules. The instantiation gets done as close to the endpoint as possible, or else with Composer classes. All the instantiations get passed to further classes through Dependency Injection. Code quality, baby.

I think I’ve mentioned it before, but I got into creating this app because I wanted to involve artificial intelligence in my smut sessions. As it often happens, technological development is driven by men’s need to have increasingly better orgasms. Can’t wait for the sexbots.

Neural narratives in Python #30

I recommend you to check out the previous parts if you don’t know what this “neural narratives” thing is about. In short, I wrote in Python a system to have multi-character conversations with large language models (like Llama 3.1), in which the characters are isolated in terms of memories and bios, so no leakage to other participants. Here’s the GitHub repo, that now even features a proper readme.

In the last part, our protagonist, having been sent by a ditzy goddess into a scorching desert world, or at least a deserty part of a fantasy world, deals with an imposing half-person, half-scorpion guardian, who offers him sanctuary in their safe house as long as the protagonist passes an initiation rite.

That was one of the funnest interactions I’ve had through this app. I’ve got a soft spot for that incompetent goddess. And the scene ends with the driving lesson of isekai: sometimes we must lose one world entirely to find our true place in another.

Although a week ago I programmed the ability for the user to add participants to an ongoing dialogue, I hadn’t programmed the feature to remove participants from one. It was necessary to do so given the circumstances; otherwise, the AI might have chosen to speak as Seraphina even though she was supposed to be gone. In addition, when a dialogue ends, a summary is generated and added as a memory to the participants. In the case of the participants leaving mid-conversation, it wouldn’t make sense to know what happened after they left, so now, for each character leaving mid-convo, the summary of the dialogue up to that point is added to their memories.

My app has a section called Story Hub that allows the user to generate story concepts, to help them figure out where the story may be going. They could already generate plot blueprints, scenarios, goals, dilemmas, and plot twists. Thanks to the massive refactoring I did of the whole width of story concepts in the app, adding new ones was easy.

I’ve also involved the facts added by the player in many prompts to the AI, including dialogue. Facts are supposed to represent well-known information about the world, such as legends, properties of animals or sentient races, etc. For example, one of the generated pieces of lore named the twin moons of this world, so I added that information to the facts. My biggest worry is the context window of some large language models: my favorite right now, Magnum 72B, has a tiny context of 16,000 tokens, and the more you add to memories and facts, the more they eat of the context, until you’re forced to switch to a subpar model.

That’s all for now. Stay whimsical.

Review: Castration: Rebirth, by Miyatsuki Arata

Four stars.

This manga starts with its protagonist being sentenced to death after having killed fifteen people. His childhood friend and love of his life was raped and murdered, so the protagonist took it upon himself to castrate and murder fifteen sexual offenders. I’m not sure if the rapist and murderer of his friend was among them.

Anyway, the protagonist gets hanged to death.

Turns out, this is an isekai, just an unusual one. The protagonist wakes up on a pile of corpses. In the sky, the sun is doing weird shit, looking like an out-of-control nuclear reactor. The first humans he sees are school girls, who proceed to freak out upon seen him, referring to him as a “beast.” One of them shoots arrows at him. After they realize that the protagonist is more or less sane, they agree to let him live by now. Shortly after, the girl who had shot arrows at our protagonist gets raped and devoured by a monstrous man.

We learn that in this alternate reality to which the protagonist got isekai-d, three months ago, a solar flare fucked up men’s DNA or something, turning them into mindless beasts solely preoccupied in what men want to do all the time but only flimsy self-restraint prevents them from doing so: rape, devour and murder women, sometimes simultaneously. All females that the protagonist comes across fear that the guy will do the same to them.

As if the reality that a flare had turned all men into rape-and-murder machines wasn’t enough, plenty of females in this story have complaints to offer about how they were exploited by men even before the world went to shit.

Other women see in the young protagonist a source of healthy semen, and therefore the chance for humanity to survive the apocalypse.

What follows is a mix of The Last of Us (the first game; as far as I’m concerned, the second game and TV series never existed), Attack on Titan, and most zombie stories. The protagonist and his companions come across different ways of trying to survive the post-apocalypse: family affairs; rigid, hierarchical structures; wild anarchy. Along the way, dozens or hundreds of people get raped, murdered, and eaten, sometimes not even by the mutated humans. This story is ballsy as hell when it comes to making even some main characters’ day quite terrible.

The manga touches upon interesting topics. Will the surviving societies be “equal” because only women are involved, or will they turn out to be new systems of exploitation? Does any sense of morality matter when at any point you can get raped and eaten by mutated men with enormous dongs? The protagonist is traumatized by the notion of sex, because his friend was raped and murdered, but isn’t his duty to provide semen to save the human race? In this case, would it be ethical to force him to do so?

I was surprised by how well the author handled the characters. They had distinct personalities and clear motivations, which often conflicted with one another’s. Some start out malicious only to end up sympathetic, or viceversa. Quite a few characters are memorable, including the protagonist, the childhood friend, a semen-obsessed teacher, a sociopathic teen, the anarchic biker girl who wanted to capture ten-year-old mutated boys for sex, etc.

In the end, this lovely tale dishes out what the title promised: rebirth (well, technically reincarnation) and castration. Lots of men lose their penises in creative ways. If any of this sounds like fun, you’ll probably enjoy this ride. I know I did.

Neural narratives in Python #29

I recommend you to check out the previous parts if you don’t know what this “neural narratives” thing is about. In short, I wrote in Python a system to have multi-character conversations with large language models (like Llama 3.1), in which the characters are isolated in terms of memories and bios, so no leakage to other participants. Here’s the GitHub repo, that now even features a proper readme.

In the previous part, a Sandstrider named Kael Marrek gave our hapless, reincarnated protagonist a tour of the local market, providing basic advice so the protagonist doesn’t die the first night. Kael guided him to a sanctuary where many of the local displaced take shelter.

The next scene, taking place in an initiation chamber, was probably my favorite of all the interactions I’ve had in this app of mine. I’ll post it tomorrow.

Neural narratives in Python #28

I recommend you to check out the previous parts if you don’t know what this “neural narratives” thing is about. In short, I wrote in Python a system to have multi-character conversations with large language models (like Llama 3.1), in which the characters are isolated in terms of memories and bios, so no leakage to other participants. Here’s the GitHub repo, that now even features a proper readme.

In the previous and first part of this new tale, our protagonist, Japanese teenager Takumi Arai, fucking died, but a ditzy goddess presented him to the wonders of reincarnation. Now, Takumi finds himself in an unknown city, retaining his previous form and memories but not knowing anything about this world where he has ended up.

Takumi was lucky enough to get across a reasonable outcast like Kael Marrek, of indeterminate gender. He or she gives Takumi a tour of the teeming market.

Neural narratives in Python #27

I recommend you to check out the previous parts if you don’t know what this “neural narratives” thing is about. In short, I wrote in Python a system to have multi-character conversations with large language models (like Llama 3.1), in which the characters are isolated in terms of memories and bios, so no leakage to other participants. Here’s the GitHub repo, that now even features a proper readme.

The previous part saw the ending of the cosmic horror tale I was telling. This one will see the beginning of the silly isekai thing I’ll do next in my AI-fueled app.

Here’s our suave protagonist, Japanese teenager Takumi Arai:

He lives in quite the peculiar story universe, but I’ll let you discover it. The story starts with him being visited by a certain interdimensional legend.

That’s the end of Takumi Arai. But in this story universe, a visit from Truck-kun isn’t the end. And yes, I went through the trouble of creating a particular world, region, and area for the original world, as well as Truck-kun himself, even though I may never revisit them.

Well, that was one of the most chaotic interactions I’ve had on this app.