Overhauled the entire system

This commit is contained in:
BritishTeapot
2025-09-12 20:41:20 +02:00
parent 98809bbee8
commit 8b81c2f569

View File

@@ -1,7 +1,7 @@
from dataclasses import dataclass
from typing import List
from typing import List, Tuple
from openai import OpenAI
from api_key import or_api_key
from .api_key import or_api_key
# SETTINGS
@@ -39,6 +39,9 @@ Play your role. Take risks. Make it fun. The world reacts — but only through t
Description of the caracter you play is provided below.
"""
creative_model = "qwen/qwen3-30b-a3b-instruct-2507"
pedantic_model = "qwen/qwen3-30b-a3b-instruct-2507"
openai_client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=or_api_key,
@@ -51,10 +54,113 @@ class Turn:
text: str
@dataclass
class Item:
name: str
description: str
@dataclass
class Character:
name: str
personality: str
internal: str
external: str
BSM: str
position: str
inventory: List[Tuple[int, Item]]
def get_char_external_description(character: Character) -> str:
character_description = ""
character_description += f"# {character.name}\n\n"
character_description += character.external + "\n"
character_description += f"**Body State**:\n{character.BSM}\n"
character_description += f"**Position**:\n{character.position}\n"
character_description += "**Inventory**:\n"
for item in character.inventory:
character_description += f"* {item[1].name}"
character_description += f" + {item[1].description}"
character_description += f" + Quantity: {item[0]}"
return character_description
"""
Updates character definitions based on what happened in the last turn.
"""
def update_char(last_turn: Turn, character: Character) -> Character:
messages = []
char_updater_prompt = """
You are an expert DM assistant in a D&D-style adventure games. You help the DM to keep track of character states, while they are busy advancing the story. Your goal is to update character descriptions only based on what happened in the last turn. You generate factual descriptions, grounded in events described in the story.
You will receive:
1. The last turn (of a DM, or a player), describing the last unanccounted events in the story.
2. Description of the character you need to update.
3. Parameters you need to modify.
You should output:
Updated parameters as valid JSON.
Remember: you update character descriptions solely based on events described in the last turn. You never make up, infer or add any information that isn't explicitly stated in the story.
"""
messages.append({"role": "system", "content": char_updater_prompt})
user_request = f"""
Last turn (by {last_turn.character_name}):
```
{last_turn.text}
```
Character description:
{get_char_external_description(character)}
Parametets that need to be updated:
* `body_state` - a concise, and precise description of character's body state alterations relative to the character definition in "External" section.
* `position` - a concise, and precise description of character's position in a scene.
"""
messages.append({"role": "user", "content": user_request})
completion = openai_client.chat.completions.create(
model=pedantic_model,
messages=messages,
response_format={"type": "json_object"},
)
if completion.choices[0].message.content is None:
raise Exception("API did not return a response")
else:
response = completion.choices[0].message.content
import json
parsed_response = json.loads(response)
new_character = character
new_character.BSM = parsed_response["body_state"]
new_character.position = parsed_response["position"]
return new_character
"""
Narrator gets:
1. System prompt:
* Instruction on what to do.
* Story setting
2. Chat history, as is.
3. System tracker:
* list of PLAYABLE characters, and their parameters:
1. name
2. external
3. BSM
4. position
5. inventory
"""
def dm_turn(chat: List[Turn], characters: List[Character]) -> Turn:
@@ -71,8 +177,22 @@ def dm_turn(chat: List[Turn], characters: List[Character]) -> Turn:
else:
messages.append({"role": "assistant", "content": turn.text})
system_tracker = "Here is a list of characters CONTROLLED BY PLAYERS:\n"
for character in characters:
system_tracker += f"* {character.name}\n"
system_tracker += "\nHere are their descriptions:"
for character in characters:
system_tracker += get_char_external_description(character)
messages.append(
{"role": "system", "content": system_tracker},
)
completion = openai_client.chat.completions.create(
model="qwen/qwen3-235b-a22b-thinking-2507", messages=messages
model=creative_model, messages=messages
)
if completion.choices[0].message.content is None:
@@ -83,16 +203,38 @@ def dm_turn(chat: List[Turn], characters: List[Character]) -> Turn:
return Turn("narrator", response)
"""
Character gets:
1. System prompt:
* Instruction on what to do.
* Name, Internal, External from char def
2. Chat history, as is.
3. System tracker:
1. BSM
2. position
3. inventory
"""
def char_turn(chat: List[Turn], character: Character) -> Turn:
if chat[-1].character_name == "character":
raise Exception("Character's turn was last.")
messages = []
character_def = f"""
# {character.name}
{character.external}
{character.internal}
"""
messages.append(
{
"role": "system",
"content": character_impersonate_prompt + "\n" + character.personality,
"content": character_impersonate_prompt + "\n" + character_def,
}
)
@@ -102,8 +244,29 @@ def char_turn(chat: List[Turn], character: Character) -> Turn:
else:
messages.append({"role": "assistant", "content": turn.text})
system_tracker = f"""
Gustav's current state:
**Body State**:
{character.BSM}
**Position**:
{character.position}
**Inventory**:
"""
for item in character.inventory:
system_tracker += f"* {item[1].name}"
system_tracker += f" + {item[1].description}"
system_tracker += f" + Quantity: {item[0]}"
messages.append(
{"role": "system", "content": system_tracker},
)
completion = openai_client.chat.completions.create(
model="qwen/qwen3-235b-a22b-thinking-2507", messages=messages
model=creative_model, messages=messages
)
if completion.choices[0].message.content is None: