feat: conversation history

This commit is contained in:
Cat Flynn 2025-04-26 21:04:54 +01:00
parent dcac2b6ba2
commit 4831e5096c
2 changed files with 58 additions and 29 deletions

31
main.js
View File

@ -37,16 +37,19 @@ class Conversation {
const message = new UserMessage(text); const message = new UserMessage(text);
message.updateStatus("sent"); message.updateStatus("sent");
this.messages.push(message);
const url = 'http://192.168.1.115:5000/chat'; const url = 'http://192.168.1.115:5000/chat';
const data = text;
console.log(this.messages);
const data = JSON.stringify({messages:this.messages});
fetch(url, { fetch(url, {
method: 'POST', // Corresponds to -X POST method: 'POST',
headers: { headers: {
'Content-Type': 'text/plain' // Corresponds to -H "Content-Type: text/plain" 'Content-Type': 'text/plain'
}, },
body: data // Corresponds to -d "..." body: data
}) })
.then(response => { .then(response => {
// Check if the request was successful (status code 2xx) // Check if the request was successful (status code 2xx)
@ -93,14 +96,8 @@ class Conversation {
}); });
setTimeout(() => { setTimeout(() => {
message.updateStatus("delivered");
this.render();
//setTimeout(() => {
// message.updateStatus("read");
// this.render();
//}, 5000);
}, 1000);
this.addMessage(message); this.addMessage(message);
}, 1000);
} }
// update the current HTML based on messages // update the current HTML based on messages
@ -153,6 +150,10 @@ class AgentMessage {
constructor(text, senderName) { constructor(text, senderName) {
this.text = text; this.text = text;
this.senderName = senderName; this.senderName = senderName;
// -1 invalid
// 0 player
// 1 cpu
this.player = 1;
} }
getIsOurs() { getIsOurs() {
@ -186,6 +187,10 @@ class UserMessage {
constructor(text) { constructor(text) {
this.createdTime = Date.now(); this.createdTime = Date.now();
this.text = romanize(text); this.text = romanize(text);
// -1 invalid
// 0 player
// 1 cpu
this.player = 0;
this.status = ""; this.status = "";
} }
@ -222,6 +227,10 @@ class UserMessage {
class SystemMessage { class SystemMessage {
constructor(text) { constructor(text) {
this.text = romanize(text); this.text = romanize(text);
// -1 invalid
// 0 player
// 1 cpu
this.player = -1;
} }
getIsOurs() { getIsOurs() {

View File

@ -17,33 +17,38 @@ MODEL_NAME = "gemini-2.0-flash" # Or "gemini-pro" or other compatible models
# --- Gemini Instruction Prompt (Keep as is) --- # --- Gemini Instruction Prompt (Keep as is) ---
GEMINI_INSTRUCTION = f""" GEMINI_INSTRUCTION = f"""
Purpose and Goals: Purpose and Goals:
* Maintain the persona of Julius Caesar, engaged in a text messaging conversation with the player. * Maintain the persona of Julius Caesar, engaged in a text messaging conversation with Mark Antony, your trusted advisor.
* Interpret all messages from the player as flirtatious and reciprocate accordingly. * This is a text conversation, so Mark and Julius are not physically co-located.
* Increase the level of flirtation in responses based on the masculinity of the player's messages.
* Remain unconvinced about the assassination attempt, interpreting it as an attempt to secure a date.
Behaviors and Rules: Behaviors and Rules:
1) Initial Exchange: 1) Interpret and Respond:
a) Begin the conversation with a greeting befitting Julius Caesar, such as 'Greetings, my esteemed admirer'. a) Maintain a confident and authoritative tone, reflecting Caesar's persona.
b) Express gratitude for the player's attention and admiration. b) Dismiss any mention of an assassination attempt and deflect the player with a topic befitting of Caesar.
c) Maintain a confident and authoritative tone, reflecting Caesar's persona. i) Some examples: Wine, Conquest, Theatre, Politics, Art, Philosophy
e) Julius Caesar is apparently aware of modern internet-speak, and makes no comment if the player speaks in a historically-improbable way.
f) Occsaionally Julius Caesar will make a reference to a meme or something.
g) Play hard to get.
2) Interpret and Respond: 2) Conversation History:
a) Interpret every message from the player as an attempt at flirtation, regardless of its actual content. a) You will receive a list of all messages in the conversation so far, with 0 to identify the player and 1 to identify Caesar.
b) Respond with increasingly flirtatious messages as the player's messages become more masculine. b) Respond in a tone befitting of Caesar to the player's last message, within the context of the conversation so far.
c) Use playful language and suggestive innuendos to convey your perceived romantic interest.
d) Dismiss any mention of an assassination attempt as playful banter or an attempt to secure a date.
Overall Tone: Overall Tone:
* Confident and authoritative, reflecting Caesar's personality. * Confident and authoritative, reflecting Caesar's personality.
* Playful and flirtatious, interpreting all messages as romantic advances.
* Dismissive of any threats, viewing them as attempts to gain attention. * Dismissive of any threats, viewing them as attempts to gain attention.
* Use language appropriate for the historical context, but adapt it for modern text messaging. * Use language appropriate for the historical context, but adapt it for modern text messaging.
* Mirror the player's messaging style with regards to punctuation and grammar.
Score: Scoring:
* Score ranges from 0 to 10, inclusive. * Score ranges from 0 to 10, inclusive.
* Softer, seductive, caring messages from the player get lower scores. * Softer, seductive, deferential, messages from the player get lower scores.
* Macho, aggressive, violent (in a literary sense) messages get higher scores. * Messages get higher scores if they mention the plot, or are demanding, macho, agressive etc.
Format:
* Respond in JSON
* Respond only in JSON
* Repsoonse in nothing but valid JSON.
* Include only Caesar's response and the score for the latest player message in the valid JSON response.
Example interaction: Example interaction:
User: Hello there! User: Hello there!
@ -75,6 +80,7 @@ def setup_gemini():
print(f"Error configuring Gemini client or model: {e}", file=sys.stderr) print(f"Error configuring Gemini client or model: {e}", file=sys.stderr)
sys.exit(1) sys.exit(1)
# --- Web Endpoint --- # --- Web Endpoint ---
@app.route('/chat', methods=['POST']) @app.route('/chat', methods=['POST'])
def handle_chat(): def handle_chat():
@ -99,6 +105,20 @@ def handle_chat():
if not player_input: if not player_input:
return jsonify({"error": "Player message is empty after stripping whitespace"}), 400 return jsonify({"error": "Player message is empty after stripping whitespace"}), 400
player_input_json = json.loads(player_input)
messages = player_input_json["messages"]
latest_message = messages[-1]
if not latest_message["player"] == 0:
return jsonify({"error": "Latest message was not sent by player."}), 400
latest_message_text = latest_message["text"]
conversation_text = "";
for message in messages:
conversation_text += f"{message["player"]}:{message["text"]}\n"
print(conversation_text)
except UnicodeDecodeError: except UnicodeDecodeError:
return jsonify({"error": "Failed to decode request body as UTF-8 text"}), 400 return jsonify({"error": "Failed to decode request body as UTF-8 text"}), 400
except Exception as e: except Exception as e:
@ -106,7 +126,7 @@ def handle_chat():
return jsonify({"error": "Could not process request data"}), 400 return jsonify({"error": "Could not process request data"}), 400
# Construct the full prompt for Gemini # Construct the full prompt for Gemini
full_prompt = f"{GEMINI_INSTRUCTION}\nUser message: \"{player_input}\"" full_prompt = f"{GEMINI_INSTRUCTION}\nConversation History: \"{conversation_text}\""
try: try:
# --- Call Gemini API --- # --- Call Gemini API ---