diff --git a/.gitignore b/.gitignore index 2eea525..63b3298 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -.env \ No newline at end of file +.env +__pycache__/ +.db \ No newline at end of file diff --git a/agent.py b/agent.py index 387c640..536becc 100644 --- a/agent.py +++ b/agent.py @@ -1,14 +1,16 @@ +from sqlite3 import Connection from openai import OpenAI from openai.types.responses import ResponseInputParam from pydantic import BaseModel, Field from constants import MODEL +import database class Response(BaseModel): - # inner_thoughts: str = Field( - # description="Your inner thoughts before forming the answer you respond with in utterance. This will not be visible to anyone else than you.") + inner_thoughts: str = Field( + description="Your inner thoughts before forming the answer you respond with in utterance. This will not be visible to anyone else than you.") utterance: str = Field( description="The response that you say after forming your thoughts from inner thoughts. This wil lbe spoken to the chat partner.") @@ -16,9 +18,12 @@ class Response(BaseModel): class Agent: client: OpenAI history: ResponseInputParam + connection: Connection - def __init__(self, client: OpenAI, message: str, initial_message: str | None = None): + def __init__(self, client: OpenAI, connection: Connection, message: str, initial_message: str | None = None): + assert isinstance(message, str) self.client = client + self.connection = connection # Instruct the character self.history = [ { @@ -30,6 +35,7 @@ class Agent: self.history.append({"role": "user", "content": initial_message}) def message(self, message: str) -> tuple[str, str]: + assert isinstance(message, str) self.history.append({"role": "user", "content": message}) response = self.client.responses.parse( @@ -38,8 +44,12 @@ class Agent: text_format=Response ) + database.create_usage( + self.connection, response.usage.input_tokens, response.usage.output_tokens) + content = response.output_parsed.utterance self.history.append( {"role": "system", "content": content}) - # return (content, response.output_parsed.inner_thoughts) - return (content, "") + + return (content, response.output_parsed.inner_thoughts) + # return (content, "") diff --git a/database.py b/database.py new file mode 100644 index 0000000..13635e6 --- /dev/null +++ b/database.py @@ -0,0 +1,19 @@ +from sqlite3 import Connection +import sqlite3 + + +def initialize() -> Connection: + connection = sqlite3.connect(".db") + + # Not storing anything that is not required based on GDPR data minimalism + connection.execute(""" +CREATE TABLE IF NOT EXISTS token_usages (input_tokens INTEGER, output_tokens INTEGER); +""") + + return connection + + +def create_usage(connection: Connection, input_tokens: int, output_tokens: int): + connection.execute( + """INSERT INTO token_usages (input_tokens, output_tokens) VALUES (?, ?)""", (input_tokens, output_tokens)) + connection.commit() diff --git a/main.py b/main.py index 9f30d40..13223b5 100644 --- a/main.py +++ b/main.py @@ -2,8 +2,10 @@ import os from dotenv import load_dotenv from openai import OpenAI from pydantic import BaseModel, Field + from agent import Agent from constants import CONVERSATION_TURNS, MODEL +import database class RoleSeed(BaseModel): @@ -22,12 +24,17 @@ def main(): api_key = os.environ.get("OPENAI_API_KEY") client = OpenAI(api_key=api_key) + connection = database.initialize() + response = client.responses.parse( model=MODEL, input=[{"role": "user", "content": "Create two role instructions for two opposing that have conflicting interests in an awkward confrontation. The descriptions are handed to actors to act out the roles in an improvised conversation. The opposing interests should create a funny ongoing conversation. Write it in a way that each role is aware of the other without revealing too much detail. One of the roles tries to manipulate and cheat the other. Instruct each role to be short and concise."}], text_format=RoleSeed, ) + database.create_usage( + connection, response.usage.input_tokens, response.usage.output_tokens) + role_1 = response.output_parsed.role_1_description role_1_initial = response.output_parsed.role_1_initial_message role_2 = response.output_parsed.role_2_description @@ -36,9 +43,9 @@ def main(): print(f"Role 2: {role_2}") agent_1 = Agent( - client, role_1, role_1_initial) + client, connection, role_1, role_1_initial) agent_2 = Agent( - client, role_2) + client, connection, role_2) agents = [agent_1, agent_2] # Iterable that switches between 0 and 1 to switch between agent 0 and 1 @@ -52,7 +59,7 @@ def main(): for agent_index in agent_turn_indices: current_agent = agents[agent_index] (last_message, inner_thoughts) = current_agent.message(last_message) - # print(f"\n[Agent {agent_index + 1} inner thoughts]: {inner_thoughts}") + print(f"\n[Agent {agent_index + 1} inner thoughts]: {inner_thoughts}") print( f"\n[Agent {agent_index + 1}]: {last_message}")