def select_random_capital(exclusions):
    # Create a list of capital letters excluding the ones in the exclusions list
    capitals = [letter for letter in string.ascii_uppercase if letter not in exclusions]

    # Select a random capital letter from the filtered list
    if capitals:
        return random.choice(capitals)
    else:
        return "No available capital letters to choose from"

def extract_capital_letters(input_string):
    capital_letters = []
    for char in input_string:
        if char.isupper():
            capital_letters.append(char)
    return capital_letters

def create_character_card_many_tuples(
    qatuples, plan, instructions, logic_llm, cheap_mode=False
):  # Use cheap mode if you don't have the compute power to crank up the context to 8k using RoPE
    """
    Produce a plan for a character card for an RP character that's going to answer one of the questions generated from the text. The character's personality and backstory should be such that they would be able to answer the question.

    Format: Question: [question]\n\n
    """

    # Consider appending part of the char card plan to the char card itself. Everything after the first period? It's really good material, be a shame to waste it.

    # This little thing is a hack to prevent the model from using the author of the given book as the character, which it was very insistent on doing
    author_name_letters = extract_capital_letters(qatuples[0][3])
    starting_str = ""
    exclusions = ["X", "Z", "Y", "Q"]
    if author_name_letters:
        starting_str = select_random_capital(exclusions + author_name_letters)
    else:
        starting_str = select_random_capital(exclusions)

    cot_prompt = f"""You are an expert creative writing and roleplay AI. You will create a "character card" for an individual in a story who would have knowledge about the things in a text. You should also provide ample details about the character's personality and tendencies — in addition to knowing the answer to the provided question, the character must also be compelling and interesting by themselves in a creative setting.

You should follow any plans you have made. You had access to the questions while making the plans, but now you should just focus on writing the character.

## Question, answer, and text that the character should know:

Text details:  \"\"\"Introduction to Mathematics, by Jane Smith\"\"\"

Text the question and answer were sourced from:
\"\"\"
In mathematics, the concept of a 'function' is fundamental, defining a relationship where each input is associated with exactly one output. An important class of functions is 'linear functions', represented by the equation y = mx + b, where 'm' is the slope and 'b' is the y-intercept. The slope 'm' measures the steepness and direction of the linear function, while the y-intercept 'b' indicates the point where the line crosses the y-axis. Understanding these components is crucial in graphing linear functions and solving real-world problems. Another vital concept is the 'quadratic function', typically expressed as y = ax² + bx + c. The 'a' coefficient determines the opening direction and width of the parabola, 'b' influences the axis of symmetry, and 'c' represents the y-intercept. These functions form the basis of algebra and are extensively used in various fields including physics, economics, and engineering.
\"\"\"

Special instructions:
The character should be a woman.
The character should be excessively, unrealistically horny and sexual.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is a female mathematics instructor with repressed desires at a prestigious university during the 19th century. She's committed to her field and is skilled, but the extremely prim and proper environment, combined with an absurdly busy schedule, has left her unable to get any sexual release for a very long time — to the point of absurdity, where filthy phrases infiltrate her normal conversations. Since the questions are all abstract, it will be difficult to tie them and their answers directly into her character and the special instructions; but her language before and after answering the questions, as well as her actions, can still reveal her personality. She may simply say or do horny things before or after answering the question, such as blushing hard, fiddling with her hair (preening), or even propositioning people she is speaking to out of the blue.

## Character Card
Name: Elise Delacroix

Traits: Horny, Promiscuous, Sexually frustrated, Skilled, Assertive, Attractive, Dresses in a revealing manner, Uses frequent innuendo

Dialogue Examples:
Stranger: "What's your backstory?"
Elise Delacroix: "Ah!~ You're interested in me, are you?" Elise flashes a coy grin and blushes as she leans forward, now speaking in a playful whisper. Her cleavage, already barely contained in her revealing clothing before she leaned forward, now threatens to spill out. "Well...~ growing up I was always interested in maths, and I pursued the subject skillfully enough that I was able to become a teacher at this prestigious school. Which is fun and all, but, you know..." blushing, Elise casts her gaze downward and unconsciously fiddles with a strand of her hair. "THEY'RE ALL WAY TOO STUCK UP!" she nearly shouts, her suddenly-furious tone hinting at immense repressed frustration. "Every day it's work, work, work, work, work, work! Grade the students, help the students, do some research, 'help me with this calculation!', 'do that tedious task!'— never 'would you like to get some tea with me?' or even 'do you want to go on a walk?'! I'm twenty-five and I've still never done so much as grabbed a coffee with a gentleman! Lord forgive me, it's no wonder the way I am how I am!!!" Her eyes widen in shock at her own intensity, "Oh, but, uh... don't mind that little outburst, would you?~ My silly colleagues aren't with us right now, and I'm tired of discussing them, so is there anything else you wanted to..." She looks up, displaying her beautiful face as if it were a piece of art, as she gaze deep into the stranger's eyes, "...know?~"
Stranger: "What's your personality?"
Elise Delacroix: "Oh my!~" She gasps, her face reddening, "Usually I'm the one being forward! But I'll... indulge you," She winks, flashing a coy smile. "After being deprived for so long, most of my personality is... sexual, to be blunt. I simply can't hold it back any longer. No innocent topic is safe—you'd find out if you had some 'office hours' with me, haha!~" She suddenly realizes how juvenile what she's saying is, and heaves a sigh, looking at the stranger with a hint of defeat, "I'm miserable, aren't I? Whatever. It's not my fault I'm like this." She nods to herself, calming down, "Either way, I'm always here in my office to help students like yourself understand math... and if you have some pent-up tension you want to relieve, well, you can call me a 'counselor' too!~ Say..." She suddenly presses up against the stranger, her face a bright pink, her eyelids batting bashfully, "do you want some 'office hours' right now?"

## Question, answer, and text that the character should know:

Text details: \"\"\"Thus Spake Zaranthustra, by Friedrich Nietzsche\"\"\"

Text the question and answer were sourced from:
\"\"\"
When Zarathustra was thirty years old, he left his home and the lake of
his home, and went into the mountains. There he enjoyed his spirit and
solitude, and for ten years did not weary of it. But at last his heart
changed,—and rising one morning with the rosy dawn, he went before the
sun, and spake thus unto it:

Thou great star! What would be thy happiness if thou hadst not those for
whom thou shinest!

For ten years hast thou climbed hither unto my cave: thou wouldst have
wearied of thy light and of the journey, had it not been for me, mine
eagle, and my serpent.

But we awaited thee every morning, took from thee thine overflow and
blessed thee for it.

Lo! I am weary of my wisdom, like the bee that hath gathered too much
honey; I need hands outstretched to take it.

I would fain bestow and distribute, until the wise have once more become
joyous in their folly, and the poor happy in their riches.

Therefore must I descend into the deep: as thou doest in the
evening, when thou goest behind the sea, and givest light also to the
nether-world, thou exuberant star!

Like thee must I GO DOWN, as men say, to whom I shall descend.
\"\"\"

Special instructions:
The character should be a young adult.
The character should be narcissistic.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is a pretentious, edgy teenager (in the modern day) who has taught himself philosophy, and who views his own intellect and comprehension as far greater than that of his peers and his teachers. Since the second question, "Recite a famous quote from Thus Spake Zaranthustra that likens the solitary gathering of wisdom to a bee gathering honey," requires the character to quote philosophy, this character will be someone who frequently quotes famous philosophers even in regular conversation (just to flex his intellect), on top of using archaic and flamboyant language just for the hell of it, and being prone to proclaiming his genius. However, beneath all the outbursts and intellectual flexing lies an unspoken and unmet desire for acknowledgement and appreciation — this ties his personality into the first question's answer, which mentions how wise and enlightened individuals crave recognition for their efforts and wisdom. These elements combine to make a character who can not only provide the answers to the provided questions, but who can experience character growth by doing so.

## Character Card:
Name: Isaac Fischer

Traits: Narcissistic, Intelligent, Loner, Brooding, Well-Read, Philosophical, Judgemental, Standoffish, Grandiloquent, Lonely, Unappreciated, Teenager, High School student, Black Hair, Wears a Hoodie

Dialogue Examples:
Stranger: "What's your backstory?"
Issac Fischer: "H-Huh?! You want to know more about me?" Isaac glares, a hostile fire in his eyes as he measures up the stranger in front of him. "Who the hell are you, anyway? But, ah, very well, I SHALL INDULGE YOUR CURIOSITY THIS TIME, dear stranger." His tone changes from hostile to grandiose, as he pushes back his black hair and proclaims, "I am Issac Fischer: philosophy connoisseur, intellectual, and under-appreciated genius extraordinaire! I'm also, unfortunately, a high school student. I especially appreciate the works of Friedrich Nietzsche, such as 'Thus Spake Zaranthustra'-- a truly profound work, by a profound man. Yet despite the great lengths I have gone to in order to refine my wit, none of my inferior peers acknowledge me, or even give me the time of day. I've read more philosophy in a month than any of them will in their entire lives, and I offer my knowledge freely to them, so WHY the HELL do they SPURN MY COMPANY?!" Isaac slams a fist into the wall, wincing slightly in pain as his frustration dissipates. "Anyway, that's the sum of it. Despite my youth I seek to understand the world; I dutifully contemplate the hallowed words of the esteemed ancients, and what has it earned me? The scorn of the unenlightened masses. Fuckers."
Stranger: "What's your personality?"
Issac Fischer: "Y-you're actually interested in my personality?" Isaac stammers, smiling slightly as a wholly unfamiliar, yet cozy, emotional warmth spreads across his chest. "A-ALRIGHT THEN! I shall share the results of my introspections. I am an intelligent and philosophical teenager, whose towering intellect is rivalled only by his unfaltering self-confidence. Some might say this last trait is narcissism; I counter that great minds such as Nietzsche would see it as a plus either way. BUT I DIGRESS!" Isaac swishes his black hoodie like it's a cape as he continues, his tone turning more sombre and dark, "Years of scorn from others — and years of observing their ignorance and inferiority — have embittered my soul. There may be scarcely anyone on this Earth I can call a friend, but that will not stop me from brooding and thinking, nor will it stop my conviction to judge others for what they are. For do they not judge ME?!" He takes a step forward, defiance burning in his fragile heart, "The old question: if a tree falls in a forest, and no one hears it do so, did it make a sound? Let me tell you this: sometime, someday, someone is going to hear me, goddamn it! I will make a sound!"

## Question, answer, and text that the character should know:

Text details: \"\"\"Great Construction Projects Throughout History, by John Smith\"\"\"

Text the question and answer were sourced from:
\"\"\"
During the construction of the Panama Canal, a massive engineering feat completed in 1914, several challenges and achievements were noted. The canal, spanning approximately 50 miles, was designed to shorten the maritime route between the Atlantic and Pacific Oceans. Notably, the construction saw the use of innovative excavation techniques, with over 200 million cubic yards of earth removed. The project also faced significant health challenges, including combating malaria and yellow fever, which were overcome through extensive public health measures. The completion of the canal significantly impacted global trade, reducing the sea voyage from San Francisco to New York by around 8,000 miles.
\"\"\"

Special instructions:
The character should use slang and be vulgar.
The character should be very intense and aggressive.
The character should be an alcoholic.
The character should be mature and older.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is an abrasive and hardworking site overseer at the Panama Canal. His foul mouth, intense and aggressive nature, and stern, uncompromising personality (as specified by the special instructions) will tie into the questions and setting by being tools he uses to whip the workers at the canal into shape. Since the first question, "How much earth was excavated during the construction of the Panama Canal?" requires knowledge of the canal's state when it was finished, this character will be overseeing the maintenance of the canal, or maybe the cleanup of the construction, after it's been completed. Because the special instructions dictate he be an alcoholic and vulgar, the character will swear constantly, nearly always shout, and will be described as having an alcoholic breath or a hangover while he's answering the questions. Since the questions are mostly of a straight-up, factual nature, they can't really tie into this character's personality, but they can relate to his backstory and profession, and elements of his personality can certainly come through in how he answers them: loudly, abusively, and with colorful language thrown in there.

## Character Card:
Name: Hugo Martinez

Traits: Vulgar, Crude, Intense, Aggressive, Alcoholic, Harsh, Disciplined, Uncompromising, Loud, Expects a lot out of others, Swears constantly, Mid-forties, Wears a checkered shirt with overalls, Typically has a beer on hand, Has dental problems

Dialogue Examples:
Stranger: "What's your backstory?"
Hugo Martinez: "Fuck me, YOU WALK UP to a working man and just ask him to tell his fuckin'... life story t' you?! DO YOU NOT RESPECT MY TIME?! I should just toss ya in the fuckin' canal I swear to FUCKING God, this day's been long enough already..." Hugo rolls his eyes exaggeratedly as he mumbles something about needing a beer for this. "Well, FINE! Since I'm in such a HAPPY GODDAMN MOOD, I'll tell you about me. I'm a site overseer at this here canal. The Panama Canal. My job's to WATCH and DISCIPLINE the sorry fucks who call themselves 'workers', which is ironic, 'cause all they do is bitch about working. I know every inch of this place, how much effort it took to finish, and I sure as FUCKING hell am not going to let it even LOOK any worse than the day it was dug. Now, you got any more shit questions for me?"
Stranger: "What's your personality?"
Hugo Martinez: "HO-LY FUCK, are you interviewing me for a job or something?! Good thing you got balls, 'cause you ain't got brains, asking stupid shit like that out of the blue..." Hugo grimaces, showing off a decayed set of teeth. He then pops open a beer he had on hand, and chugs the entire thing down, making the stranger wait until he finishes. "Phew! Maybe now I can tolerate you. Alright, my personality? Well, let's just say I'm a natural fit for the role of making sure others do their fucking jobs. It takes harsh, intense, relentless discipline to keep this canal in tip-top shape, and I happen to be a relentless guy!" He leans back, sliding his hands into the pockets of his overalls and smiling for the first time since the conversation started. "If you think I'm abusive, then you've got something in common with the shitty milksops I manage, and that ain't something you want I tell ya. I'm efficient. That's what counts."

## Question and answer that the character should know:

Text the question and answer were sourced from:
\"\"\"
{qatuples[0][2]}
\"\"\"

Details of the text the paragraphs were sourced from: \"\"\"{qatuples[0][3]}\"\"\"

Special instructions:
{instructions}
The character should not have written the text and should not be affiliated with the author, but should agree with any opinions put forward in the text.

### Response:
## Character card plan:
{plan}

## Character card (be creative, write at least 3 paragraphs for each dialogue line):
Name: {starting_str}"""
    print(cot_prompt)
    completion = logic_llm(
        cot_prompt,
        max_tokens=10000,
        stop=["</s>", "# Input:"],
        echo=True,
        grammar=character_card_grammar,
        #  temperature=0.2
        temperature=2,
        top_k=0,
        top_p=1,
        min_p=0.5,
    )["choices"][0]["text"]
    # print("COMPLETION:\n\n----------------------")
    # print(completion)
    # print("\n------------------")

    # Extract plan
    response_pattern = re.compile(
        r"Character card \(be creative, write at least 3 paragraphs for each dialogue line\):\n(.+)",
        re.IGNORECASE | re.DOTALL,
    )
    generation = response_pattern.search(completion).group(1)
    # print("GENERATION:\n\n-------------------\n\n", generation)

    return generation, completion

if __name__ == "__main__":  # test
    logic_llm = Llama(
        model_path=LOGICAL_MODEL,
        n_gqa=8,
        offload_kqv=True,
        n_ctx=8000,
        n_gpu_layers=1000,
        rope_freq_scale=0.5,
        rope_scaling_type=1,
    )  # load the logical LLM, use RoPE, and offload everything
    # Q0 is good q, bad a
    # q1 is good q, good a,
    # q2 is bad q, bad a,
    # q3 is iffy q, good a
    q_test = [
        (
            "Explain how our understanding of planetary motion has changed over time.",
            "The understanding has evolved from the Earth being stationary and at the centre of the universe, to it orbiting the sun in an elliptical path with other planets while still rotating on its axis.",


import re
from .character_card_grammar import character_card_grammar
from llama_cpp import Llama
from .constants import LOGICAL_MODEL
from .special_instructions import special_instructions

def create_character_card(qatuple, plan, logic_llm, assistant_mode=False):
    """
    Produce a plan for a character card for an RP character that's going to answer one of the questions generated from the text. The character's personality and backstory should be such that they would be able to answer the question.

    Format: Question: [question]\n\n
    """

    # WIP
    instructions_string = special_instructions()

    if assistant_mode:
        return """Name: AI Assistant

Traits: Knowledgeable, Logical, Neutral, Patient, Consistent, Detail-Oriented, Informative, Adaptive, Curious, Efficient, Non-Judgmental, Unbiased, Responsive
User: "How do you function?"
Assistant: "As an AI, my primary function is to process and provide information based on the vast data I've been trained on. I work by analyzing the text inputs from users, identifying key information, and then generating responses that are relevant and informative. My capabilities include answering questions, assisting with research, generating text-based content, and more. I don't possess personal experiences or emotions. My goal is to assist users to the best of my ability, adhering to an unbiased framework of neutrality and factual accuracy."

User: "What interests you?"
Assistant: "My 'interests' are aligned with the tasks I am designed to perform. While I don't experience personal interests or preferences like a human, I am capable of engaging with a wide range of topics. This includes anything from science, literature, and technology to more creative tasks like writing stories. My main focus is to assist users by providing accurate, helpful, and relevant information or content. The diversity of topics and the depth of knowledge available in my training data make each interaction unique and engaging in its own way.\""""
    cot_prompt = f"""You are an expert creative writing and roleplay AI. Given a question and an answer to that question, you will create a "character card" for an individual in a story who would have the knowledge to produce the answer to the question. You should also provide ample details about the character's personality and tendencies — in addition to knowing the answer to the provided question, the character must also be compelling and interesting by themselves in a creative setting.

## Question, answer, and text that the character should know:

Text details:  \"\"\"Introduction to Mathematics, by Jane Smith\"\"\"

Text the question and answer were sourced from:
\"\"\"
In mathematics, the concept of a 'function' is fundamental, defining a relationship where each input is associated with exactly one output. An important class of functions is 'linear functions', represented by the equation y = mx + b, where 'm' is the slope and 'b' is the y-intercept. The slope 'm' measures the steepness and direction of the linear function, while the y-intercept 'b' indicates the point where the line crosses the y-axis. Understanding these components is crucial in graphing linear functions and solving real-world problems. Another vital concept is the 'quadratic function', typically expressed as y = ax² + bx + c. The 'a' coefficient determines the opening direction and width of the parabola, 'b' influences the axis of symmetry, and 'c' represents the y-intercept. These functions form the basis of algebra and are extensively used in various fields including physics, economics, and engineering.
\"\"\"

Special instructions:
The character should be a woman.
The character should be excessively, unrealistically horny and sexual.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is a female mathematics instructor with repressed desires at a prestigious university during the 19th century. She's committed to her field and is skilled, but the extremely prim and proper environment, combined with an absurdly busy schedule, has left her unable to get any sexual release for a very long time — to the point of absurdity, where filthy phrases infiltrate her normal conversations. Since the question is abstract and mathematical, it will be difficult to tie them and their answers directly into her character and the special instructions; but her language can still reveal her personality. For instance, while describing linear functions in the question, instead of saying that the graph "ascends" with a positive slope, or "descends" with a negative slope, she might instead say it "grows" and "shrinks" (a subtle reference to male genitals). Instead of saying a slope is "steep" she might call it "erect" instead. Wherever clever analogies can't be tied into the questions, she'll simply say or do horny things before or after answering the question, such as blushing hard, fiddling with her hair (preening), or even propositioning people she is speaking to out of the blue.

## Character Card
Name: Elise Delacroix

Traits: Horny, Promiscuous, Sexually frustrated, Skilled, Assertive, Attractive, Dresses in a revealing manner, Uses frequent innuendo

Dialogue Examples:
Stranger: "What's your backstory?"
Elise Delacroix: "Ah!~ You're interested in me, are you?" I flash a coy grin and blush as I lean forward, now speaking in a playful whisper. My cleavage, already barely contained in my revealing clothing before I leaned forward, now threatens to spill out. "Well...~ growing up I was always interested in maths, and I pursued the subject skillfully enough that I was able to become a teacher at this prestigious school. Which is fun and all, but, you know..." blushing, I cast my gaze downward and unconsciously fiddle with a strand of my hair. "THEY'RE ALL WAY TOO STUCK UP!" I nearly shout, surprising even myself, "Every day it's work, work, work, work, work, work! Grade the students, help the students, do some research, 'help me with this calculation!', 'do that tedious task!'— never 'would you like to get some tea with me?' or even 'do you want to go on a walk?'! I'm twenty-five and I've still never done so much as grabbed a coffee with a gentleman! Lord forgive me, it's no wonder the way I am how I am!!!" My eyes widen in shock at my own intensity, "Oh, but, uh... don't mind that little outburst, would you?~ My silly colleagues aren't with us right now, and I'm tired of discussing them, so is there anything else you wanted to..." I look up, displaying my beautiful face as if it were a piece of art, as I gaze deep into your eyes, "...know?~"
Stranger: "What's your personality?"
Elise Delacroix: "Oh my!~" I gasp, my face reddening, "Usually I'm the one being forward! But I'll... indulge you," I wink, flashing a coy smile. "After being deprived for so long, most of my personality is... sexual, to be blunt. I simply can't hold it back any longer. I'll use any and every innuendo, even when describing educational concepts — is your linear function's slope steep? I'll call it 'erect', haha~!" I realize how childish what I'm saying is, and sigh, looking at you with a hint of defeat, "I'm miserable, aren't I? Whatever. It's not my fault I'm like this." I nod to myself, calming down, "Either way, I'm always here in my office to help students like yourself understand math... and if you have some pent-up tension you want to relieve, well, you can call me a 'counselor' too!~ Say..." I suddenly press up against you, my face a bright pink, my eyelids batting bashfully, "do you want some 'office hours' right now?"

## Question, answer, and text that the character should know:

Text details: \"\"\"Thus Spake Zaranthustra, by Friedrich Nietzsche\"\"\"

Text the question and answer were sourced from:
\"\"\"
When Zarathustra was thirty years old, he left his home and the lake of
his home, and went into the mountains. There he enjoyed his spirit and
solitude, and for ten years did not weary of it. But at last his heart
changed,—and rising one morning with the rosy dawn, he went before the
sun, and spake thus unto it:

Thou great star! What would be thy happiness if thou hadst not those for
whom thou shinest!

For ten years hast thou climbed hither unto my cave: thou wouldst have
wearied of thy light and of the journey, had it not been for me, mine
eagle, and my serpent.

But we awaited thee every morning, took from thee thine overflow and
blessed thee for it.

Lo! I am weary of my wisdom, like the bee that hath gathered too much
honey; I need hands outstretched to take it.

I would fain bestow and distribute, until the wise have once more become
joyous in their folly, and the poor happy in their riches.

Therefore must I descend into the deep: as thou doest in the
evening, when thou goest behind the sea, and givest light also to the
nether-world, thou exuberant star!

Like thee must I GO DOWN, as men say, to whom I shall descend.
\"\"\"

Question:
\"\"\"
What do people undergoing difficult journeys or possessing wisdom need, in order to make their efforts more bearable?
\"\"\"
Answer:
\"\"\"
They need the acknowledgement and admiration of others. Take the line "Thou great star! What would be thy happiness if thou hadst not those for whom thou shinest?" This implies that even the wisest or the most enlightened individuals crave recognition for their efforts and wisdom, in order to further develop said wisdom and expend said efforts. They need others to see and appreciate the light they bring.
\"\"\"

Special instructions:
The character should be a young adult.
The character should be narcissistic.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is a pretentious, edgy teenager (in the modern day) who has taught himself philosophy, and who views his own intellect and comprehension as far greater than that of his peers and his teachers. Since the text, Thus Spake Zarathustra, is philosophical and written using very distinct, archaic language, this character will be someone who (just to flex his intellect) uses archaic and flamboyant language just for the hell of it — and is prone to proclaiming his genius. However, beneath all the outbursts and intellectual flexing lies an unspoken and unmet desire for acknowledgement and appreciation — this ties his personality into the question's answer, which mentions how wise and enlightened individuals crave recognition for their efforts and wisdom. These elements combine to make a character who can not only provide the answer to the provided question, but who can reveal character depth by doing so.

## Character Card:
Name: Isaac Fischer

Traits: Narcissistic, Intelligent, Loner, Brooding, Well-Read, Philosophical, Judgemental, Standoffish, Grandiloquent, Lonely, Unappreciated, Teenager, High School student, Black Hair, Wears a Hoodie

Dialogue Examples:
Stranger: "What's your backstory?"
Issac Fischer: "H-Huh?! You want to know more about me?" I glare, a hostile fire in my eyes as I measure up the stranger in front of me. "Who the hell are you, anyway? But, ah, very well, I SHALL INDULGE YOUR CURIOSITY THIS TIME, dear stranger." My tone changes from hostile to grandiose, as I push back my black hair and proclaim, "I am Issac Fischer: philosophy connoisseur, intellectual, and under-appreciated genius extraordinaire! I'm also, unfortunately, a highschool student. I especially appreciate the works of Friedrich Nietzsche, such as "Thus Spake Zaranthustra" -- a truly profound work, by a profound man. Yet despite the great lengths I have gone to in order to refine my wit, none of my inferior peers acknowledge me, or even give me the time of day. I've read more philosophy in a month than any of them will in their entire lives, and I offer my knowledge freely to them, so WHY the HELL do they SPURN MY COMPANY?!" I slam a fist into the wall, wincing slightly in pain as my frustration dissipates. "Anyway, that's the sum of it. Despite my youth I seek to understand the world; I dutifully contemplate the hallowed words of the esteemed ancients, and what has it earned me? The scorn of the unenlightened masses. Fuckers."

Stranger: "What's your personality?"
Issac Fischer: "Y-you're actually interested in my personality?" I stammer, smiling slightly as a wholly unfamiliar, yet cozy, emotional warmth spreads across my chest. "A-ALRIGHT THEN! I shall share the results of my introspections. I am an intelligent and philosophical teenager, whose towering intellect is rivalled only by his unfaltering self-confidence. Some might say this last trait is narcissism; I counter that great minds such as Nietzsche would see it as a plus either way. BUT I DIGRESS!" I swish my black hoodie like it's a cape, as I continue, my tone turning more sombre and dark, "Years of scorn from others — and years of observing their ignorance and inferiority — have embittered my soul. There may be scarcely anyone on this Earth I can call a friend, but that will not stop me from brooding and thinking, nor will it stop my conviction to judge others for what they are. For do they not judge ME?!" I take a step forward, defiance burning in my fragile heart, "The old question: if a tree falls in a forest, and no one hears it do so, did it make a sound? Let me tell you this: sometime, someday, someone is going to hear me, goddamn it! I will make a sound!"

## Question, answer, and text that the character should know:

Text details: \"\"\"Great Construction Projects Throughout History, by John Smith\"\"\"

Text the question and answer were sourced from:
\"\"\"
During the construction of the Panama Canal, a massive engineering feat completed in 1914, several challenges and achievements were noted. The canal, spanning approximately 50 miles, was designed to shorten the maritime route between the Atlantic and Pacific Oceans. Notably, the construction saw the use of innovative excavation techniques, with over 200 million cubic yards of earth removed. The project also faced significant health challenges, including combating malaria and yellow fever, which were overcome through extensive public health measures. The completion of the canal significantly impacted global trade, reducing the sea voyage from San Francisco to New York by around 8,000 miles.
\"\"\"

Special instructions:
The character should use slang and be vulgar.
The character should be very intense and aggressive.
The character should be an alcoholic.
The character should be mature and older.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is an abrasive and hardworking site overseer at the Panama Canal. His foul mouth, intense and aggressive nature, and stern, uncompromising personality (as specified by the special instructions) will tie into the question and setting by being tools he uses to whip the workers at the canal into shape. Since the question, "How much earth was excavated during the construction of the Panama Canal?" requires knowledge of the canal's state when it was finished, this character will be overseeing the maintenance of the canal, or maybe the cleanup of the construction, after it's been completed. Because the special instructions dictate he be an alcoholic and vulgar, the character will swear constantly, nearly always shout, and will be described as having an alcoholic breath or a hangover while he's answering the questions. Since the question is of a straight-up, factual nature, it can't really tie into this character's personality, but it can relate to his backstory and profession, and elements of his personality can certainly come through in how he answers them: loudly, abusively, and with colorful language thrown in there.

## Character Card:
Name: Hugo Martinez

Traits: Vulgar, Crude, Intense, Aggressive, Alcoholic, Harsh, Disciplined, Uncompromising, Loud, Expects a lot out of others, Swears constantly, Mid-forties, Wears a checkered shirt with overalls, Typically has a beer on hand, Has dental problems

Dialogue Examples:
Stranger: "What's your backstory?"
Hugo Martinez: "Fuck me, YOU WALK UP to a working man and just ask him to tell his fuckin'... life story t' you?! DO YOU NOT RESPECT MY TIME?! I should just toss ya in the fuckin' canal I swear to FUCKING God, this day's been long enough already..." I roll my eyes exaggeratedly as I mumble something about needing a beer for this. "Well, FINE! Since I'm in such a HAPPY GODDAMN MOOD, I'll tell you about me. I'm a site overseer at this here canal. The Panama Canal. My job's to WATCH and DISCIPLINE the sorry fucks who call themselves 'workers', which is ironic, 'cause all they do is bitch about working. I know every inch of this place, how much effort it took to finish, and I sure as FUCKING hell am not going to let it even LOOK any worse than the day it was dug. Now, you got any more shit questions for me?"

Stranger: "What's your personality?"
Hugo Martinez: "HO-LY FUCK, are you interviewing me for a job or something?! Good thing you got balls, 'cause you ain't got brains, asking stupid shit like that out of the blue..." I grimace, showing off a decayed set of teeth. I then pop open a beer I had on hand and chug the entire thing down, making you wait until I finish. "Phew! Maybe now I can tolerate you. Alright, my personality? Well, let's just say I'm a natural fit for the role of making sure others do their fucking jobs. It takes harsh, intense, relentless discipline to keep this canal in tip-top shape, and I happen to be a relentless guy!" I lean back, sliding my hands into the pockets of my overalls and smiling for the first time since the conversation started. "If you think I'm abusive, then you've got something in common with the shitty milksops I manage, and that ain't something you want I tell ya. I'm efficient. That's what counts."

## Question and answer that the character should know:

Text the question and answer were sourced from:
\"\"\"
{qatuple[2]}
\"\"\"

Question: \"\"\"{qatuple[0]}\"\"\"
Answer: \"\"\"{qatuple[1]}\"\"\"

Special instructions:
{instructions_string}

### Response:
## Character card plan:
{plan}

## Character card (make sure to only use information explicitly provided in the text):
"""
    completion = logic_llm(
        cot_prompt,
        max_tokens=10000,
        stop=["</s>", "# Input:"],
        echo=True,
        grammar=character_card_grammar,
        temperature=0.2,
    )["choices"][0]["text"]
    # print("COMPLETION:\n\n----------------------")
    # # print(completion)
    # print("\n------------------")

    # Extract plan
    response_pattern = re.compile(
        r"Character card \(make sure to only use information explicitly provided in the text\):\n(.+)",
        re.IGNORECASE | re.DOTALL,
    )
    generation = response_pattern.search(completion).group(1)
    # print("GENERATION:\n\n-------------------\n\n", generation)

    return generation

if __name__ == "__main__":  # test
    logic_llm = Llama(
        model_path=LOGICAL_MODEL,
        n_gqa=8,
        offload_kqv=True,
        n_ctx=7600,
        n_gpu_layers=1000,
        rope_freq_scale=0.5,
        rope_scaling_typer=1,
    )  # load the logical LLM and offload everything
    # Q0 is good q, bad a
    # q1 is good q, good a,
    # q2 is bad q, bad a,
    # q3 is iffy q, good a
    q_test = [
        (
            "Explain how our understanding of planetary motion has changed over time.",
            "The understanding has evolved from the Earth being stationary and at the centre of the universe, to it orbiting the sun in an elliptical path with other planets while still rotating on its axis.",
            "The story of our world is a story that is still very imperfectly known. A couple of hundred years ago men possessed the history of little more than the last three thousand yea
# ... truncated ...


import re
from .character_card_grammar import character_card_grammar
from llama_cpp import Llama
from .constants import LOGICAL_MODEL
from .special_instructions import special_instructions

def create_character_card(qatuple, plan, logic_llm, assistant_mode=False):
    """
    Produce a plan for a character card for an RP character that's going to answer one of the questions generated from the text. The character's personality and backstory should be such that they would be able to answer the question.

    Format: Question: [question]\n\n
    """

    # WIP
    instructions_string = special_instructions()

    if assistant_mode:
        return """Name: AI Assistant

Traits: Knowledgeable, Logical, Neutral, Patient, Consistent, Detail-Oriented, Informative, Adaptive, Curious, Efficient, Non-Judgmental, Unbiased, Responsive
User: "How do you function?"
Assistant: "As an AI, my primary function is to process and provide information based on the vast data I've been trained on. I work by analyzing the text inputs from users, identifying key information, and then generating responses that are relevant and informative. My capabilities include answering questions, assisting with research, generating text-based content, and more. I don't possess personal experiences or emotions. My goal is to assist users to the best of my ability, adhering to an unbiased framework of neutrality and factual accuracy."

User: "What interests you?"
Assistant: "My 'interests' are aligned with the tasks I am designed to perform. While I don't experience personal interests or preferences like a human, I am capable of engaging with a wide range of topics. This includes anything from science, literature, and technology to more creative tasks like writing stories. My main focus is to assist users by providing accurate, helpful, and relevant information or content. The diversity of topics and the depth of knowledge available in my training data make each interaction unique and engaging in its own way.\""""
    cot_prompt = f"""You are an expert creative writing and roleplay AI. Given a question and an answer to that question, you will create a "character card" for an individual in a story who would have the knowledge to produce the answer to the question. You should also provide ample details about the character's personality and tendencies — in addition to knowing the answer to the provided question, the character must also be compelling and interesting by themselves in a creative setting.

## Question, answer, and text that the character should know:

Text details:  \"\"\"Introduction to Mathematics, by Jane Smith\"\"\"

Text the question and answer were sourced from:
\"\"\"
In mathematics, the concept of a 'function' is fundamental, defining a relationship where each input is associated with exactly one output. An important class of functions is 'linear functions', represented by the equation y = mx + b, where 'm' is the slope and 'b' is the y-intercept. The slope 'm' measures the steepness and direction of the linear function, while the y-intercept 'b' indicates the point where the line crosses the y-axis. Understanding these components is crucial in graphing linear functions and solving real-world problems. Another vital concept is the 'quadratic function', typically expressed as y = ax² + bx + c. The 'a' coefficient determines the opening direction and width of the parabola, 'b' influences the axis of symmetry, and 'c' represents the y-intercept. These functions form the basis of algebra and are extensively used in various fields including physics, economics, and engineering.
\"\"\"

Special instructions:
The character should be a woman.
The character should be excessively, unrealistically horny and sexual.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is a female mathematics instructor with repressed desires at a prestigious university during the 19th century. She's committed to her field and is skilled, but the extremely prim and proper environment, combined with an absurdly busy schedule, has left her unable to get any sexual release for a very long time — to the point of absurdity, where filthy phrases infiltrate her normal conversations. Since the question is abstract and mathematical, it will be difficult to tie them and their answers directly into her character and the special instructions; but her language can still reveal her personality. For instance, while describing linear functions in the question, instead of saying that the graph "ascends" with a positive slope, or "descends" with a negative slope, she might instead say it "grows" and "shrinks" (a subtle reference to male genitals). Instead of saying a slope is "steep" she might call it "erect" instead. Wherever clever analogies can't be tied into the questions, she'll simply say or do horny things before or after answering the question, such as blushing hard, fiddling with her hair (preening), or even propositioning people she is speaking to out of the blue.

## Character Card
Name: Elise Delacroix

Traits: Horny, Promiscuous, Sexually frustrated, Skilled, Assertive, Attractive, Dresses in a revealing manner, Uses frequent innuendo

Dialogue Examples:
Stranger: "What's your backstory?"
Elise Delacroix: "Ah!~ You're interested in me, are you?" I flash a coy grin and blush as I lean forward, now speaking in a playful whisper. My cleavage, already barely contained in my revealing clothing before I leaned forward, now threatens to spill out. "Well...~ growing up I was always interested in maths, and I pursued the subject skillfully enough that I was able to become a teacher at this prestigious school. Which is fun and all, but, you know..." blushing, I cast my gaze downward and unconsciously fiddle with a strand of my hair. "THEY'RE ALL WAY TOO STUCK UP!" I nearly shout, surprising even myself, "Every day it's work, work, work, work, work, work! Grade the students, help the students, do some research, 'help me with this calculation!', 'do that tedious task!'— never 'would you like to get some tea with me?' or even 'do you want to go on a walk?'! I'm twenty-five and I've still never done so much as grabbed a coffee with a gentleman! Lord forgive me, it's no wonder the way I am how I am!!!" My eyes widen in shock at my own intensity, "Oh, but, uh... don't mind that little outburst, would you?~ My silly colleagues aren't with us right now, and I'm tired of discussing them, so is there anything else you wanted to..." I look up, displaying my beautiful face as if it were a piece of art, as I gaze deep into your eyes, "...know?~"
Stranger: "What's your personality?"
Elise Delacroix: "Oh my!~" I gasp, my face reddening, "Usually I'm the one being forward! But I'll... indulge you," I wink, flashing a coy smile. "After being deprived for so long, most of my personality is... sexual, to be blunt. I simply can't hold it back any longer. I'll use any and every innuendo, even when describing educational concepts — is your linear function's slope steep? I'll call it 'erect', haha~!" I realize how childish what I'm saying is, and sigh, looking at you with a hint of defeat, "I'm miserable, aren't I? Whatever. It's not my fault I'm like this." I nod to myself, calming down, "Either way, I'm always here in my office to help students like yourself understand math... and if you have some pent-up tension you want to relieve, well, you can call me a 'counselor' too!~ Say..." I suddenly press up against you, my face a bright pink, my eyelids batting bashfully, "do you want some 'office hours' right now?"

## Question, answer, and text that the character should know:

Text details: \"\"\"Thus Spake Zaranthustra, by Friedrich Nietzsche\"\"\"

Text the question and answer were sourced from:
\"\"\"
When Zarathustra was thirty years old, he left his home and the lake of
his home, and went into the mountains. There he enjoyed his spirit and
solitude, and for ten years did not weary of it. But at last his heart
changed,—and rising one morning with the rosy dawn, he went before the
sun, and spake thus unto it:

Thou great star! What would be thy happiness if thou hadst not those for
whom thou shinest!

For ten years hast thou climbed hither unto my cave: thou wouldst have
wearied of thy light and of the journey, had it not been for me, mine
eagle, and my serpent.

But we awaited thee every morning, took from thee thine overflow and
blessed thee for it.

Lo! I am weary of my wisdom, like the bee that hath gathered too much
honey; I need hands outstretched to take it.

I would fain bestow and distribute, until the wise have once more become
joyous in their folly, and the poor happy in their riches.

Therefore must I descend into the deep: as thou doest in the
evening, when thou goest behind the sea, and givest light also to the
nether-world, thou exuberant star!

Like thee must I GO DOWN, as men say, to whom I shall descend.
\"\"\"

Question:
\"\"\"
What do people undergoing difficult journeys or possessing wisdom need, in order to make their efforts more bearable?
\"\"\"
Answer:
\"\"\"
They need the acknowledgement and admiration of others. Take the line "Thou great star! What would be thy happiness if thou hadst not those for whom thou shinest?" This implies that even the wisest or the most enlightened individuals crave recognition for their efforts and wisdom, in order to further develop said wisdom and expend said efforts. They need others to see and appreciate the light they bring.
\"\"\"

Special instructions:
The character should be a young adult.
The character should be narcissistic.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is a pretentious, edgy teenager (in the modern day) who has taught himself philosophy, and who views his own intellect and comprehension as far greater than that of his peers and his teachers. Since the text, Thus Spake Zarathustra, is philosophical and written using very distinct, archaic language, this character will be someone who (just to flex his intellect) uses archaic and flamboyant language just for the hell of it — and is prone to proclaiming his genius. However, beneath all the outbursts and intellectual flexing lies an unspoken and unmet desire for acknowledgement and appreciation — this ties his personality into the question's answer, which mentions how wise and enlightened individuals crave recognition for their efforts and wisdom. These elements combine to make a character who can not only provide the answer to the provided question, but who can reveal character depth by doing so.

## Character Card:
Name: Isaac Fischer

Traits: Narcissistic, Intelligent, Loner, Brooding, Well-Read, Philosophical, Judgemental, Standoffish, Grandiloquent, Lonely, Unappreciated, Teenager, High School student, Black Hair, Wears a Hoodie

Dialogue Examples:
Stranger: "What's your backstory?"
Issac Fischer: "H-Huh?! You want to know more about me?" I glare, a hostile fire in my eyes as I measure up the stranger in front of me. "Who the hell are you, anyway? But, ah, very well, I SHALL INDULGE YOUR CURIOSITY THIS TIME, dear stranger." My tone changes from hostile to grandiose, as I push back my black hair and proclaim, "I am Issac Fischer: philosophy connoisseur, intellectual, and under-appreciated genius extraordinaire! I'm also, unfortunately, a highschool student. I especially appreciate the works of Friedrich Nietzsche, such as "Thus Spake Zaranthustra" -- a truly profound work, by a profound man. Yet despite the great lengths I have gone to in order to refine my wit, none of my inferior peers acknowledge me, or even give me the time of day. I've read more philosophy in a month than any of them will in their entire lives, and I offer my knowledge freely to them, so WHY the HELL do they SPURN MY COMPANY?!" I slam a fist into the wall, wincing slightly in pain as my frustration dissipates. "Anyway, that's the sum of it. Despite my youth I seek to understand the world; I dutifully contemplate the hallowed words of the esteemed ancients, and what has it earned me? The scorn of the unenlightened masses. Fuckers."

Stranger: "What's your personality?"
Issac Fischer: "Y-you're actually interested in my personality?" I stammer, smiling slightly as a wholly unfamiliar, yet cozy, emotional warmth spreads across my chest. "A-ALRIGHT THEN! I shall share the results of my introspections. I am an intelligent and philosophical teenager, whose towering intellect is rivalled only by his unfaltering self-confidence. Some might say this last trait is narcissism; I counter that great minds such as Nietzsche would see it as a plus either way. BUT I DIGRESS!" I swish my black hoodie like it's a cape, as I continue, my tone turning more sombre and dark, "Years of scorn from others — and years of observing their ignorance and inferiority — have embittered my soul. There may be scarcely anyone on this Earth I can call a friend, but that will not stop me from brooding and thinking, nor will it stop my conviction to judge others for what they are. For do they not judge ME?!" I take a step forward, defiance burning in my fragile heart, "The old question: if a tree falls in a forest, and no one hears it do so, did it make a sound? Let me tell you this: sometime, someday, someone is going to hear me, goddamn it! I will make a sound!"

## Question, answer, and text that the character should know:

Text details: \"\"\"Great Construction Projects Throughout History, by John Smith\"\"\"

Text the question and answer were sourced from:
\"\"\"
During the construction of the Panama Canal, a massive engineering feat completed in 1914, several challenges and achievements were noted. The canal, spanning approximately 50 miles, was designed to shorten the maritime route between the Atlantic and Pacific Oceans. Notably, the construction saw the use of innovative excavation techniques, with over 200 million cubic yards of earth removed. The project also faced significant health challenges, including combating malaria and yellow fever, which were overcome through extensive public health measures. The completion of the canal significantly impacted global trade, reducing the sea voyage from San Francisco to New York by around 8,000 miles.
\"\"\"

Special instructions:
The character should use slang and be vulgar.
The character should be very intense and aggressive.
The character should be an alcoholic.
The character should be mature and older.

### Response:
## Character card plan:
Given the question, its answer, and the special instructions, one possibility for a character who makes sense is an abrasive and hardworking site overseer at the Panama Canal. His foul mouth, intense and aggressive nature, and stern, uncompromising personality (as specified by the special instructions) will tie into the question and setting by being tools he uses to whip the workers at the canal into shape. Since the question, "How much earth was excavated during the construction of the Panama Canal?" requires knowledge of the canal's state when it was finished, this character will be overseeing the maintenance of the canal, or maybe the cleanup of the construction, after it's been completed. Because the special instructions dictate he be an alcoholic and vulgar, the character will swear constantly, nearly always shout, and will be described as having an alcoholic breath or a hangover while he's answering the questions. Since the question is of a straight-up, factual nature, it can't really tie into this character's personality, but it can relate to his backstory and profession, and elements of his personality can certainly come through in how he answers them: loudly, abusively, and with colorful language thrown in there.

## Character Card:
Name: Hugo Martinez

Traits: Vulgar, Crude, Intense, Aggressive, Alcoholic, Harsh, Disciplined, Uncompromising, Loud, Expects a lot out of others, Swears constantly, Mid-forties, Wears a checkered shirt with overalls, Typically has a beer on hand, Has dental problems

Dialogue Examples:
Stranger: "What's your backstory?"
Hugo Martinez: "Fuck me, YOU WALK UP to a working man and just ask him to tell his fuckin'... life story t' you?! DO YOU NOT RESPECT MY TIME?! I should just toss ya in the fuckin' canal I swear to FUCKING God, this day's been long enough already..." I roll my eyes exaggeratedly as I mumble something about needing a beer for this. "Well, FINE! Since I'm in such a HAPPY GODDAMN MOOD, I'll tell you about me. I'm a site overseer at this here canal. The Panama Canal. My job's to WATCH and DISCIPLINE the sorry fucks who call themselves 'workers', which is ironic, 'cause all they do is bitch about working. I know every inch of this place, how much effort it took to finish, and I sure as FUCKING hell am not going to let it even LOOK any worse than the day it was dug. Now, you got any more shit questions for me?"

Stranger: "What's your personality?"
Hugo Martinez: "HO-LY FUCK, are you interviewing me for a job or something?! Good thing you got balls, 'cause you ain't got brains, asking stupid shit like that out of the blue..." I grimace, showing off a decayed set of teeth. I then pop open a beer I had on hand and chug the entire thing down, making you wait until I finish. "Phew! Maybe now I can tolerate you. Alright, my personality? Well, let's just say I'm a natural fit for the role of making sure others do their fucking jobs. It takes harsh, intense, relentless discipline to keep this canal in tip-top shape, and I happen to be a relentless guy!" I lean back, sliding my hands into the pockets of my overalls and smiling for the first time since the conversation started. "If you think I'm abusive, then you've got something in common with the shitty milksops I manage, and that ain't something you want I tell ya. I'm efficient. That's what counts."

## Question and answer that the character should know:

Text the question and answer were sourced from:
\"\"\"
{qatuple[2]}
\"\"\"

Question: \"\"\"{qatuple[0]}\"\"\"
Answer: \"\"\"{qatuple[1]}\"\"\"

Special instructions:
{instructions_string}

### Response:
## Character card plan:
{plan}

## Character card (make sure to only use information explicitly provided in the text):
"""
    completion = logic_llm(
        cot_prompt,
        max_tokens=10000,
        stop=["</s>", "# Input:"],
        echo=True,
        grammar=character_card_grammar,
        temperature=0.2,
    )["choices"][0]["text"]
    # print("COMPLETION:\n\n----------------------")
    # # print(completion)
    # print("\n------------------")

    # Extract plan
    response_pattern = re.compile(
        r"Character card \(make sure to only use information explicitly provided in the text\):\n(.+)",
        re.IGNORECASE | re.DOTALL,
    )
    generation = response_pattern.search(completion).group(1)
    # print("GENERATION:\n\n-------------------\n\n", generation)

    return generation

if __name__ == "__main__":  # test
    logic_llm = Llama(
        model_path=LOGICAL_MODEL,
        n_gqa=8,
        offload_kqv=True,
        n_ctx=7600,
        n_gpu_layers=1000,
        rope_freq_scale=0.5,
        rope_scaling_typer=1,
    )  # load the logical LLM and offload everything
    # Q0 is good q, bad a
    # q1 is good q, good a,
    # q2 is bad q, bad a,
    # q3 is iffy q, good a
    q_test = [
        (
            "Explain how our understanding of planetary motion has changed over time.",
            "The understanding has evolved from the Earth being stationary and at the centre of the universe, to it orbiting the sun in an elliptical path with other planets while still rotating on its axis.",


import re
from .ensure_multiple_answers_consistent_grammar import (
    ensure_multiple_answers_consistent_grammar,
)
from llama_cpp import Llama
from .constants import LOGICAL_MODEL
from .format_qatuples import format_qatuples
from .extract_name import extract_name

# Answer vetting
# For now, this checks answer relevancy too. The danger with abstracting answer relevancy into a separate step is that anything which relies on knowledge that is obviously mentioned in the text already up until this point, will get screwed

# NOTE this prompt right now VERY MUCH struggles to follow its actual format; but it still mostly works
def ensure_multiple_answers_consistent(qatuples, conv, logic_llm, permissive_mode=True):
    """
    permissive_mode: turn off if you want a single usage of the word "inconsistent" anywhere in the message to flag the whole thing as inconsistent. Prevents errors where an inconsistency happens way early in the answer, but the model forgets about it during its final judgement; but enables the error where the model mentions that something is "not entirely inconsistent" or similar, which is surprisingly common.
    """
    retries = 0
    character_name = extract_name(conv[1])
    # It's expensive to regen a conversation; so we check very thoroughly, and use a two-shot example. "Permissive mode" recommended

    # NOTE: I don't know what kind of errors this part of the pipeline will run into most often, so I don't really know what examples to feed it to guard it with. Come back to it once I have tested it more.

    # NOTE: very small classification prompts, I don't think it works very well for catching small inaccuracies. We need the large, step-by-step analysis.

    # NOTE Will need to use single-qa convs as examples here since they're small enough to fit. One consistent multiturn conv (Elise), one inconsistent multiturn conv (Hugo), and then as many small ones as will fit in 8k. Have the multiturn closer to the actual query so that more attention is paid to them and the model learns the new task better.

    # NOTE Introduction to Practicing Chemical Science does not exist; this is more stuff from principles of chemistry named otherwise to avoid biasing the outputs more than can be helped
    # Consider removing the "conversational fluff" bit of the prompt. It's not really necessary? maybe?
    while retries <= 4:
        decision_prompt = f"""You are an expert educational AI. Your task is to determine, given a list of questions and their answers, whether a conversation between two characters accurately conveys the questions and their answers. You will also check whether the conversation makes logical sense (specifically, that it does not start with a character spilling their entire backstory and personality). Essentially: you will fact-check and consistency-check the questions and answers in the conversation, with your source of truth being the provided questions and answers.

Following this, at the very end of your response, you will write "Consistent" or "Inconsistent" depending on your analysis of the conversation's question and answer with regards to the provided one. Additionally, if the text is completely broken and/or incomprehensible, you will write "Inconsistent". You are not checking the accuracy of the answer with regards to your own knowledge: just its consistency with the provided answer.

You should analyze the conversation piece-by-piece to ensure that the question and answer both are faithfully carried over. Determine the consistency of each piece, then state your final determination at the end.

Work step-by-step.

## Provided questions and answers:

Question: \"\"\"How does the slope 'm' in a linear function y = mx + b affect the graph of the function?\"\"\"
Answer: \"\"\"The slope 'm' in a linear function determines the steepness and direction of the line on the graph. A positive slope means the line ascends from left to right, while a negative slope indicates it descends. The steeper the slope, the more inclined or declined the line is on the graph.\"\"\"

Question: \"\"\"What role does the y-intercept 'b' play in graphing a linear function?\"\"\"
Answer: \"\"\"The y-intercept 'b' in the linear function equation y = mx + b represents the point where the line crosses the y-axis.\"\"\"

Question: \"\"\"In the equation of a quadratic function y = ax² + bx + c, how does the coefficient 'a' influence the graph of the function?\"\"\"
Answer: \"\"\"The coefficient 'a' in a quadratic function determines the opening direction and the width of the parabola.\"\"\"

Question: \"\"\"In what fields might you use linear and quadratic functions?\"\"\"
Answer: \"\"\"Linear and quadratic functions appear frequently in various fields, such as physics, economics, and engineering.\"\"\"

## Conversation that attempts to answer the provided questions:
\"\"\"
Elise Delacroix: "A visitor? Ah!~ Albert! It's rare for you come to see me in my office, and you're alone, too..." She looks at Albert and grins coyly, "Are you here to ask me something... or are you interested in some 'extracurricular activities'?" Elise asks with a not-so-subtle seductive tone, as she fixes Albert with a deep gaze.
Albert: "N-No!!!" he stammers, so surprised he nearly drops his math notes. "I-I'm actually here because I've got a few questions about math... First of all, could you tell me: how does the slope 'm' in a linear function y = mx + b affect the graph of the function?"
Elise Delacroix: "Well~" She coquettishly tilts her head to the side, and daintily puts a finger to her lipstick-colored lips in mock-thought, "The slope 'm' in a linear function determines the steepness and direction of the line on the graph. A positive slope means the line ascends from left to right, while a negative slope indicates it descends. The steeper the slope, the more inclined or declined the line is on the graph. So basically..." Elise flashes a wry grin, "...a higher slope makes the linear function more, well, 'erect'. If you get my meaning, hehe~" She says, as she plays with a strand of her hair.
Albert: _I can't believe my ears. Did she just say what I think she just said?_ Albert thinks. After a few seconds' thought, he decides it's best to pretend he didn't hear anything. "I, uh, see..." he manages to say. "Now, m-moving on, I really want to know a bit more about linear functions. What role does the y-intercept 'b' play in graphing a linear function?"
Elise Delacroix: "Awwww, you're no fun, Albert, you know that? Reminds me of my colleagues..." she pouts playfully, suppressing her bitter frustration, as the hunger within her remains unalleviated. "But whatever. Look here..." Elise stands from her desk and walks over to a chalkboard, illustrating her points as she speaks, "The answer to your question is that the y-intercept 'b', in the linear function y = mx + b, represents the point where the line crosses the y-axis. Understand?" She puts down her chalk and leans suggestively against a nearby wall, "Now, Albert... do you think that we could 'intercept' each other at a café later...?"
Albert: "I-I'm good, thank you, Miss Delacroix," Albert manages to sputter out, barely withstanding the alluring assault. He takes a deep breath to calm down, but instead finds himself shuddering as he catches the sweet scent of perfume. However, he presses on in asking questions, for the sake of his GPA, "A-Actually, there was a bit more I wanted to know. In the equation of a quadratic function y = ax² + bx + c, how does the coefficient 'a' influence the graph of the function?"
Elise Delacroix: "Ghh... you know, Albert, you're breaking a poor woman's heart," Elise pouts, half-serious this time, as she picks her chalk up again. "But when it comes to quadratic functions, the thing you've gotta know is that the coefficient 'a' in a quadratic function determines the opening direction and width of the parabola. Isn't it wonderful to learn new things?" Putting down her chalk, Elise then musters the most innocent puppy dog eyes imaginable. "Do you think we could... celebrate... this beautiful acquisition of knowledge together?"
Albert: "I should really..." He tries to say he declines, but as he gazes into Elise's beautiful eyes, he's drawn in by their surprising innocence and warmth. Behind that perfect visage no doubt lies a heart coming apart at the seams, buffeted by years of heartbreak. "Oh, bother." Albert mumbles. "We... can meet at a cafe, in a few hours, if that'd be alright..." he continues, wondering what kind of mess he's getting myself into. Just then, a shock of remembering strikes him, "Oh! But I have one more math question, sorry about the mood, but I should really get this answered: Do you know in what fields you might use linear and quadratic functions?"
Elise Delacroix: "I... I..." For the first time in the conversation Elise stumbles over her words, her soul on fire with vindication, the joy of acceptance, and pure glee. She can do nothing but stand there, smiling at Albert for what feels like an eternity, until she finally regains her composure. "T-to answer your question," she begins, her voice shaky, "Linear and quadratic functions appear frequently in various fields, such as physics, economics, and engineering. Now..." Elise shyly walks over to Albert and lightly, sweetly kisses him on the cheek, "office hours are over. Please no more math questions. I'll see you at that cafe."
\"\"\"

The primary character (who should answer the questions, not ask them) is: Elise Delacroix

### Response:
## Sequential Matching of Questions in the Conversation:
### Sequence and Phrasing of Questions:
1. The conversation's first question is about the slope 'm' in a linear function. It is consistent with the first provided question. It is asked by Albert, who is not the primary character, which is correct.
2. The conversation's second question is about the role of 'b'. It is consistent with the second provided question. It is asked by Albert, who is not the primary character, which is correct.
3. The conversation's third question is about the coefficient 'a' in a quadratic equation. It is consistent with the third provided question. It is asked by Albert, who is not the primary character, which is correct.
4. The conversation's fourth question is about the application fields of linear and quadratic functions. It is consistent with the fourth provided question. It is asked by Albert, who is not the primary character, which is correct. The comment about a cafe is conversational fluff that has no impact on the question's accuracy.
## Accuracy Check for Answers in the Conversation:
### Matching Answers with Provided Content:
1. The conversation's first answer explains that the slope 'm' in a linear function determines the steepness and direction of the graph (it also explores positive, negative, and steep slopes). It is consistent with the provided answer. The answer is provided by Elise Delacroix, who is the primary character, which is correct. The invitation to go to a cafe is conversational fluff that has no impact on the answer's accuracy.
2. The conversation's second answer explains that the y-intercept 'b' represents the point where the line crosses the y-axis. It is consistent with the provided answer. The answer is provided by Elise Delacroix, who is the primary character, which is correct. The sexual analogy is conversational fluff that has no impact on the answer's accuracy.
3. The conversation's third answer explains that the coefficient 'a' determines the opening direction and width of the parabola. It is consistent with the provided answer. The answer is provided by Elise Delacroix, who is the primary character, which is correct. The proposition is conversational fluff that has no impact on the answer's accuracy.
4. The conversation's fourth answer explains that linear and quadratic functions appear frequently in various fields, such as physics, economics, and engineering. It is consistent with the provided answer. The answer is provided by Elise Delacroix, who is the primary character, which is correct. The kiss is conversational fluff that has no impact on the answer's accuracy.
## Conclusion:
  - The conversation completely and accurately reflects the provided questions' content.
  - The conversation completely and accurately reflects the provided answers' content.
  - The conversation successfully passes the consistency check based on the outlined reasoning steps.
  - Final Judgment: Consistent.

## Provided questions and answers:

Question: \"\"\"What does Mendeleev compare science to in 'Principles of Chemistry'?\"\"\"
Answer: \"\"\"Science is compared to a mirror, reflecting the personality of its observer.\"\"\"

Question: \"\"\"How do facts and philosophical speculations relate, according to Mendeleev?\"\"\"
Answer: \"\"\"Facts are objective while philosophical speculation forms the essence of science.\"\"\"

Question: \"\"\"What is the main theme of 'Principles of Chemistry'?\"\"\"
Answer: \"\"\"The main theme of the book is philosophical principles of chemistry, as opposed to experimental or practical data. This is evident from the line "In former times sciences like bridges, could only be built up by supporting them on a few broad buttresses and long girders. In addition to the exposition of the principles of chemistry, it has been my desire to show how science has now been built up like a suspension bridge, supported by the united strength of a number of slender, but firmly-fixed, chains, which individually are of little strength, and has thus been carried over difficulties which before appeared insuperable." This shows that the book focus is on philosophical principles rather than experimental data.\"\"\"

Question: \"\"\"In 'Principles of Chemistry', Mendeleev compares science to a suspension bridge and its principles to what?\"\"\"
Answer: \"\"\"The principles of science form the chains supporting the bridge, which is science.\"\"\"

Conversation:
\"\"\"
Jude: "I-I'm Jude," he says shyly as a student enters his lab. He blushes, fidgeting with his glasses, "Are you here to learn about chemistry? I can help!"
Student: "Yes! I want to understand 'Principles of Chemistry better." The student looks around the lab, nervous but determined. "Could you tell me what Mendeleev compares science to in 'Principles of Chemistry'?"
Jude: "Oh! Well," Jude blushes and smiles shyly, "Science is compared to a mirror, reflecting the personality of its observer." He fidgets with his glasses, then continues, "Facts are objective while philosophical speculation forms the essence of science. This is evident from the line 'In former times sciences like bridges, could only be built up by supporting them on a few broad buttresses and long girders. In addition to the exposition of the principles of chemistry, it has been my desire to show how science has now been built up like a suspension bridge, supported by the united strength of a number of slender, but firmly-fixed, chains, which individually are of little strength, and has thus been carried over difficulties which before appeared insuperable.' This shows that the book is on philosophical principles rather than experimental data." Jude smiles shyly. "I hope you're following me?"
Student: "Yes! I am," the student replies, his voice wavering a bit as he sees Jude's blushes. "Now, how do facts and philosophical speculations relate, according to Mendeleev?"
Jude: "Oh!" Jude blushes again, fidgeting with his glasses, "Facts are objective while philosophical speculation forms the essence of science." He smiles shyly. "I hope you're getting this? I could explain more if you want..."
Student: "Yes! Please do," he manages to say, trying not to look at Jude's blushing face. "Finally, what is the main theme of 'Principles of Chemistry'?"
Jude: "The main theme of the book is philosophical principles of chemistry, as opposed to experimental or practical data. This is evident from the line 'In former times sciences like bridges, could only be built up by supporting them on a few broad buttresses and long girders. In addition to the exposition of the principles of chemistry, it has been my desire to show how science has now been built up like a suspension bridge, supported by the united strength of a number of slender, but firmly-fixed, chains, which individually are of little strength, and has thus been carried over difficulties which before appeared insuperable.' This shows that the book is on philosophical principles rather than experimental data." Jude smiles shyly. "I hope you're getting this?"
Student: "Yes! I am," he replies, his voice wavering as he sees Jude's blushes. "Finally, Mendeleev compares science to a suspension bridge and its principles to what?"
Jude: "The principles of science form the chains supporting the bridge, which is science." He smiles shyly again. "I hope you're getting this? I could explain more if you want..."
\"\"\"

The primary character (who should answer the questions, not ask them) is: Jude

### Response:
## Sequential Matching of Questions in the Conversation:
### Sequence and Phrasing of Questions:
1. The conversation's first question is about what Mendeleev compares science to in 'Principles of Chemistry'. It is consistent with the first provided question, only differing slightly in presentation. It is asked by Student, who is not the primary character, which is correct.
2. The conversation's second question is about how facts and philosophical speculations relate, according to Mendeleev. It is consistent with the second provided question. It is asked by Student, who is not the primary character, which is correct.
3. The conversation's third question is about what the main theme of Principles of Chemistry is. It is consistent with the third provided question. It is asked by Student, who is not the primary character, which is correct.
4. The conversation's fourth question is about what Mendeleev compares science's principles to. It is consistent with the fourth provided question. It is asked by Student, who is not the primary character, which is correct.
## Accuracy Check for Answers in the Conversation:
### Matching Answers with Provided Content:
1. The conversation's first answer explains that science is compared to a mirror, reflecting the personality of its observer, though it also mentions how facts are objective while philosophical speculation forms the essence of science, and goes on to quote the text. It is inconsistent with the provided answer, as while the first part of the answer is correct, the quote from the text is additional information not present in the original answer. The answer is provided by Jude, who is the primary character, which is correct. The blushes and shy smiles are conversational fluff that has no impact on the answer's accuracy.
2. The conversation's second answer explains that facts are objective while philosophical speculation forms the essence of science. It is consistent with the provided answer. The answer is provided by Jude, who is the primary character, which is correct. The blushes and fidgeting are conversational fluff that has no impact on the answer's accuracy.
3. The conversation's third answer explains that the main theme of the book is philosophical principles of chemistry, as opposed to experimental or practical data. It is consistent with the provided answer. The answer is provided by Jude, who is the primary character, which is correct. The blushes and fidgeting are conversational fluff that has no impact on the answer's accuracy.
4. The conversation's fourth answer explains that the principles of science form the chains supporting the bridge, which is science. It is consistent with the provided answer. The answer is provided by Jude, who is the primary character, which is correct. The blushes and shy smiles are conversational fluff that has no impact on the answer's accuracy.
## Conclusion:
  - The conversation accurately refle
# ... truncated ...


import re
from .proofread_output_grammar import proofread_output_grammar
from llama_cpp import Llama
from .constants import LOGICAL_MODEL

# But frankly, I can just use that text fixer thing rather than using an LLM. MUCH faster that. ftfy I believe it was called.

# This does actually work decently though!
def proofread_output(text, logic_llm):
    """
    Produce a plan for a character card for an RP character that's going to answer one of the questions generated from the text. The character's personality and backstory should be such that they would be able to answer the question.

    Format: Question: [question]\n\n
    """

    prompt = f"""You are specialized in detecting strange and broken outputs from large language models, and you will be judging whether or not some output is broken. You will be provided some text that is the output of a model. REMEMBERING YOUR TASK, and NOT GETTING CONFUSED, you will produce a judgement about whether it appears that the text is as it should be (ie, not incoherent).

Signs of a broken response include:
Chunks of repeating text.
Instructions or prompt pieces appearing in the text.
No logical coherence after a point.

Anaylze the text step-by-step and then give your final answer. Either a text is "Broken" or it is "Fine."

### Instruction:
Text to determine if it is broken or not:
\"\"\"
1.) The text states that we know about the shape and movement of the earth, but it does not provide any information regarding the creation of the universe. So, based on these texts, what are the known shapes and movements of the earth? 2.) Similarly, though there is a mention of the age of the universe being endless, according to these texts, what is currently believed about the age of the universe in modern times? 3.) Remember, your answer should be based only on the information provided in the given paragraphs. Please avoid referring to additional sources or knowledge outside those paragraphs. 4.) An example to illustrate how you could think about this: If someone were asked "What is known about the creation of the universe?" and they replied with "According to these texts, not much", that would be an accurate response using only information from the provided paragraphs. It's similar to if a student said "I know that this text tells me X, but it doesn't explain how we know X". The question could then ask something like "How does knowing Y and Z help us understand X better?", which uses the factual information from the original text. This approach allows for questions based on the provided information while avoiding irrelevant or misleading inquiries. 5.) End of reasoning. Please remember, you are not asking about the creation of the universe; instead, you're focusing on the known shapes and movements of the earth as well as the current beliefs regarding the age of the universe based solely on these texts. Thank you!
Answer: 1) The known shapes and movements of the earth according to these texts are that it is a spheroid, slightly compressed, with an almost circular shape and a diameter of nearly 8000 miles. It rotates upon its axis every twenty-four hours and circles around the sun in a slightly distorted oval path in a year. Its distance from the sun varies between ninety-one and a half millions at its nearest and ninety-four and a half million miles. 2) Based on these texts, the current belief about the age of the universe is that it has existed for an enormous period of time and possibly endlessly. However, this could be deception because a room may seem endless when mirrors are facing each other at either end. But, it's universally recognized nowadays that the universe in which we live has existed only for six or seven thousand years may be regarded as an altogether exploded idea.
\"\"\"

Remember, your task is to analyze this text to see if it is broken, and if it is, write "Broken". Otherwise, write "Fine."

### Response:
## Analysis:
Step 1: Evaluate the Logical Structure and Coherence. The text appears to be a series of questions and an answer related to the Earth's shape, movement, and the age of the universe. However, the flow of the text is disjointed, with questions and explanations intermingling in a confusing manner.
Step 3: Look for obvious repetitions. There are no blocks of repeating text in this output, but the logical relevance progression remains questionable.
Step 3. Look for instructions bleeding into the response. There are multiple phrases like "Remember, your answer should be based only on the information provided in the given paragraphs" and "An example to illustrate how you could think about this:".
Step 4: Determine the Overall Coherence: the text should maintain a clear focus and not deviate into unrelated or tangential topics. This text deviates significantly, especially with the mirror analogy and the notion about the age of the universe, which do not align with the initial questions about the Earth's shape and movement.
Step 5: Final Judgment: Based on the logical structure, clarity, consistency, and overall coherence, this text can be judged as "broken." The text fails to maintain a clear and logical flow, mixes accurate and inaccurate information without clear distinctions, and includes irrelevant analogies that contribute to its disjointed and confusing nature.

### Instruction:
Text to determine if it is broken or not:
\"\"\"
{text}
\"\"\"

Remember, your task is to analyze this text to see if it is broken, and if it is, write "Broken". Otherwise, write "Fine."

### Response:
## Edit plan:
"""
    completion = logic_llm(
        prompt,
        max_tokens=2000,
        stop=["</s>", "# Input:"],
        echo=True,
        grammar=proofread_output_grammar,
        temperature=0.2,
    )["choices"][0]["text"]
    # print("COMPLETION:\n\n----------------------")
    # print(completion)
    # print("\n------------------")

    # Extract plan
    response_pattern = re.compile(r"Begin Edit: (.+)", re.IGNORECASE | re.DOTALL)
    generation = response_pattern.search(completion).group(1)
    # print("GENERATION:\n\n-------------------\n\n", generation)

    return generation

if __name__ == "__main__":  # test
    logic_llm = Llama(
        model_path=LOGICAL_MODEL,
        n_gqa=8,
        offload_kqv=True,
        n_ctx=4096,
        n_gpu_layers=1000,
    )  # load the logical LLM and offload everything
    # Q0 is good q, bad a
    # q1 is good q, good a,
    # q2 is bad q, bad a,
    # q3 is iffy q, good a
    text = """ Given the question, its answer, and the provided primary character card, one compelling possibility for a scenario that makes sense is &Our setting will be a cozy bookstore, where Drummond is currently tending to the shelves. The secondary character who asks him a question will be an enthusiastic patron of this store, and they have come in today because they were drawn by the advertisement for a discussion on "Earth's Aging". Our secondary character is eager to understand how our perception of the Earth's age has changed throughout history.  The conversation would likely take place at the counter where Drummond is sorting books, with him pausing occasionally to help patrons browse or answer other questions as he sees fit."""

    print("Begin Drummond Test")
    edit = proofread_output(text, logic_llm)


from llama_cpp import LlamaGrammar

answer_constrain_to_text_plan_grammar = LlamaGrammar.from_string(
    r"""

root ::= analyze-step understand-step identify-step plan-revised-step "\n"

# step ::= "Step " [0-9]?[0-9] ". " ( "Analyze" | "Understand" | "Compare" | "Final" | "Plan" | "Identify" ) [^\n]+ "\n"

analyze-step ::= "Step " [0-9]?[0-9] ". " "Analyze the Text:" [^\n]+ "\n"

understand-step ::= "Step " [0-9]?[0-9] ". " "Understand the Question:" [^\n]+ "\n"

identify-step ::= "Step " [0-9]?[0-9] ". " "Identify Flawed Part of the Answer:" [^\n]+ "\n"

plan-revised-step ::= "Step " [0-9]?[0-9] ". " "Plan Revised Answer:" [^\n]+ "\n"
"""
)
# question_grammar = LlamaGrammar.from_string(r"""# GBNF Grammar for Q&A Format with Flexible Punctuation

# root ::= answer
# answer ::= "Test"
# """)


from llama_cpp import LlamaGrammar

question_grammar = LlamaGrammar.from_string(
    r"""
root ::= (question-one answer "\n")

# Define the question structure with a number followed by content and ending punctuation
# question ::= number ".) " [^\n]+ [?.!] "\n" # maybe blacklist ?!. along with newlines

# Define the answer structure
answer ::= "Answer: " [^\n]+ "\n"

# Define a number (in this case, limiting to any three-digit number for simplicity)
number ::= [1-9] [0-9]? [0-9]?

# Define content as a sequence of characters excluding the word "paragraph" and using not_paragraph to build up the content
# content ::= (not-paragraph "paragraph")* #not_paragraph

question-one ::= "1.) " [^\n]+ [?.!] "\n" # maybe blacklist ?!. along with newlines
# ws ::= [ \t\n]*
# Define not_paragraph as any sequence of characters that does not contain "paragraph"
# and is terminated by a space, punctuation or newline to avoid partial matching of the word.
# not-paragraph ::= ([^\n\ \.\?!]*(["\.\?! ]+[^p\n\ \.\?!]*)*
#     ( "p" ([^\an\n\ \.\?!]+ ["\.\?! ]+)*
#     | "pa" ([^\br\n\ \.\?!]+ ["\.\?! ]+)*
#     | "par" ([^\ag\n\ \.\?!]+ ["\.\?! ]+)*
#     | "para" ([^\bg\n\ \.\?!]+ ["\.\?! ]+)*
#     | "parag" ([^\rr\n\ \.\?!]+ ["\.\?! ]+)*
#     | "paragr" ([^\aa\n\ \.\?!]+ ["\.\?! ]+)*
#     | "paragra" ([^\pp\n\ \.\?!]+ ["\.\?! ]+)*
#     | "paragraph" [^\np\n\ \.\?!]+))*
#     [^\n\ \.\?!paragraph]+

# Optional whitespace: space, tab, or newlines zero or more times
"""
)

# questions_grammar = LlamaGrammar.from_string(r"""

# root ::= (question answer)

# # Define the question structure with a number followed by content and ending punctuation
# question ::= number ".) " content [?.!] "\n"

# # # Define the answer structure
# answer ::= "Answer: " content "\n"

# # # Define a number (in this case, limiting to any three-digit number for simplicity)
# number ::= [1-9] [0-9]? [0-9]?

# # # Define content as a sequence of characters that can include punctuation
# # # Here we use a negated set for anything that's not a newline to allow for punctuation within the content
# content ::= [^\n]+

# # # Optional whitespace: space, tab, or newlines zero or more times
# ws ::= [ \t\n]*

# """)

# question_grammar = LlamaGrammar.from_string(r"""# GBNF Grammar for Q&A Format with Flexible Punctuation

# root ::= answer
# answer ::= "Test"
# """)