From 232e416f738a08945bc027a2870e174d6c35b8da Mon Sep 17 00:00:00 2001 From: Adrian Prado Date: Mon, 17 Jun 2024 18:16:33 -0500 Subject: [PATCH 1/9] Removed solution from master branch --- app/routes/character_routes.py | 47 ++-------------------------------- 1 file changed, 2 insertions(+), 45 deletions(-) diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index 2892a23..d16651f 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -44,54 +44,11 @@ def get_characters(): @bp.get("//greetings") def get_greetings(char_id): - character = validate_model(Character, char_id) - - if not character.greetings: - return make_response(jsonify(f"No greetings found for {character.name} "), 201) - - response = {"Character Name" : character.name, - "Greetings" : []} - for greeting in character.greetings: - response["Greetings"].append({ - "greeting" : greeting.greeting_text - }) - - return jsonify(response) + pass @bp.post("//generate") def add_greetings(char_id): - character_obj = validate_model(Character, char_id) - greetings = generate_greetings(character_obj) - print(greetings) - - if character_obj.greetings: - return make_response(jsonify(f"Greetings already generated for {character_obj.name} "), 201) - - new_greetings = [] - - for greeting in greetings: - text = greeting[greeting.find(" ")+1:] - new_greeting = Greeting( - greeting_text = text.strip("\""), - character = character_obj - ) - new_greetings.append(new_greeting) - - db.session.add_all(new_greetings) - db.session.commit() - - return make_response(jsonify(f"Greetings successfully added to {character_obj.name}"), 201) - -def generate_greetings(character): - - input_message = f"I am writing a video game in the style of The Witcher. I have an npc named {character.name} who is {character.age} years old. They are a {character.occupation} who has a {character.personality} personality. Please generate a python style list of 10 stock phrases they might use when the main character talks to them" - completion = client.chat.completions.create( - model="gpt-3.5-turbo", - messages=[ - {"role": "user", "content": input_message} - ] - ) - return(completion.choices[0].message.content.split("\n")) + pass def validate_model(cls,id): try: From 4c9b012b82765c51ea7d08a9b5c8589506221137 Mon Sep 17 00:00:00 2001 From: Adrian Prado Date: Mon, 17 Jun 2024 20:59:02 -0500 Subject: [PATCH 2/9] removed OpenAI library from imports --- app/routes/character_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index d16651f..9808ce3 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -3,7 +3,7 @@ from ..models.character import Character from ..models.greeting import Greeting from sqlalchemy import func, union, except_ -from openai import OpenAI + bp = Blueprint("characters", __name__, url_prefix="/characters") client = OpenAI() From df2f4eda1733934c1cc45d7a8dc8f9ed1e058396 Mon Sep 17 00:00:00 2001 From: Adrian Prado Date: Fri, 21 Jun 2024 01:38:15 -0500 Subject: [PATCH 3/9] Remove OpenAI References --- app/routes/character_routes.py | 1 - 1 file changed, 1 deletion(-) diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index 9808ce3..6cf5b52 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -6,7 +6,6 @@ bp = Blueprint("characters", __name__, url_prefix="/characters") -client = OpenAI() @bp.post("") def create_character(): From bc81ef4ef0f7c3931792d297d9162fa32fc8caa9 Mon Sep 17 00:00:00 2001 From: Adrian Prado Date: Fri, 21 Jun 2024 01:43:10 -0500 Subject: [PATCH 4/9] remove --- migrations/README | 1 - migrations/alembic.ini | 50 -------- migrations/env.py | 113 ------------------ migrations/script.py.mako | 24 ---- migrations/versions/657ab8362756_.py | 34 ------ migrations/versions/8ed7775249e9_.py | 34 ------ .../d7a96ea32a49_add_character_model.py | 35 ------ migrations/versions/e06848138ff6_.py | 34 ------ 8 files changed, 325 deletions(-) delete mode 100644 migrations/README delete mode 100644 migrations/alembic.ini delete mode 100644 migrations/env.py delete mode 100644 migrations/script.py.mako delete mode 100644 migrations/versions/657ab8362756_.py delete mode 100644 migrations/versions/8ed7775249e9_.py delete mode 100644 migrations/versions/d7a96ea32a49_add_character_model.py delete mode 100644 migrations/versions/e06848138ff6_.py diff --git a/migrations/README b/migrations/README deleted file mode 100644 index 0e04844..0000000 --- a/migrations/README +++ /dev/null @@ -1 +0,0 @@ -Single-database configuration for Flask. diff --git a/migrations/alembic.ini b/migrations/alembic.ini deleted file mode 100644 index ec9d45c..0000000 --- a/migrations/alembic.ini +++ /dev/null @@ -1,50 +0,0 @@ -# A generic, single database configuration. - -[alembic] -# template used to generate migration files -# file_template = %%(rev)s_%%(slug)s - -# set to 'true' to run the environment during -# the 'revision' command, regardless of autogenerate -# revision_environment = false - - -# Logging configuration -[loggers] -keys = root,sqlalchemy,alembic,flask_migrate - -[handlers] -keys = console - -[formatters] -keys = generic - -[logger_root] -level = WARN -handlers = console -qualname = - -[logger_sqlalchemy] -level = WARN -handlers = -qualname = sqlalchemy.engine - -[logger_alembic] -level = INFO -handlers = -qualname = alembic - -[logger_flask_migrate] -level = INFO -handlers = -qualname = flask_migrate - -[handler_console] -class = StreamHandler -args = (sys.stderr,) -level = NOTSET -formatter = generic - -[formatter_generic] -format = %(levelname)-5.5s [%(name)s] %(message)s -datefmt = %H:%M:%S diff --git a/migrations/env.py b/migrations/env.py deleted file mode 100644 index 4c97092..0000000 --- a/migrations/env.py +++ /dev/null @@ -1,113 +0,0 @@ -import logging -from logging.config import fileConfig - -from flask import current_app - -from alembic import context - -# this is the Alembic Config object, which provides -# access to the values within the .ini file in use. -config = context.config - -# Interpret the config file for Python logging. -# This line sets up loggers basically. -fileConfig(config.config_file_name) -logger = logging.getLogger('alembic.env') - - -def get_engine(): - try: - # this works with Flask-SQLAlchemy<3 and Alchemical - return current_app.extensions['migrate'].db.get_engine() - except (TypeError, AttributeError): - # this works with Flask-SQLAlchemy>=3 - return current_app.extensions['migrate'].db.engine - - -def get_engine_url(): - try: - return get_engine().url.render_as_string(hide_password=False).replace( - '%', '%%') - except AttributeError: - return str(get_engine().url).replace('%', '%%') - - -# add your model's MetaData object here -# for 'autogenerate' support -# from myapp import mymodel -# target_metadata = mymodel.Base.metadata -config.set_main_option('sqlalchemy.url', get_engine_url()) -target_db = current_app.extensions['migrate'].db - -# other values from the config, defined by the needs of env.py, -# can be acquired: -# my_important_option = config.get_main_option("my_important_option") -# ... etc. - - -def get_metadata(): - if hasattr(target_db, 'metadatas'): - return target_db.metadatas[None] - return target_db.metadata - - -def run_migrations_offline(): - """Run migrations in 'offline' mode. - - This configures the context with just a URL - and not an Engine, though an Engine is acceptable - here as well. By skipping the Engine creation - we don't even need a DBAPI to be available. - - Calls to context.execute() here emit the given string to the - script output. - - """ - url = config.get_main_option("sqlalchemy.url") - context.configure( - url=url, target_metadata=get_metadata(), literal_binds=True - ) - - with context.begin_transaction(): - context.run_migrations() - - -def run_migrations_online(): - """Run migrations in 'online' mode. - - In this scenario we need to create an Engine - and associate a connection with the context. - - """ - - # this callback is used to prevent an auto-migration from being generated - # when there are no changes to the schema - # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html - def process_revision_directives(context, revision, directives): - if getattr(config.cmd_opts, 'autogenerate', False): - script = directives[0] - if script.upgrade_ops.is_empty(): - directives[:] = [] - logger.info('No changes in schema detected.') - - conf_args = current_app.extensions['migrate'].configure_args - if conf_args.get("process_revision_directives") is None: - conf_args["process_revision_directives"] = process_revision_directives - - connectable = get_engine() - - with connectable.connect() as connection: - context.configure( - connection=connection, - target_metadata=get_metadata(), - **conf_args - ) - - with context.begin_transaction(): - context.run_migrations() - - -if context.is_offline_mode(): - run_migrations_offline() -else: - run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako deleted file mode 100644 index 2c01563..0000000 --- a/migrations/script.py.mako +++ /dev/null @@ -1,24 +0,0 @@ -"""${message} - -Revision ID: ${up_revision} -Revises: ${down_revision | comma,n} -Create Date: ${create_date} - -""" -from alembic import op -import sqlalchemy as sa -${imports if imports else ""} - -# revision identifiers, used by Alembic. -revision = ${repr(up_revision)} -down_revision = ${repr(down_revision)} -branch_labels = ${repr(branch_labels)} -depends_on = ${repr(depends_on)} - - -def upgrade(): - ${upgrades if upgrades else "pass"} - - -def downgrade(): - ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/657ab8362756_.py b/migrations/versions/657ab8362756_.py deleted file mode 100644 index b5baa66..0000000 --- a/migrations/versions/657ab8362756_.py +++ /dev/null @@ -1,34 +0,0 @@ -"""empty message - -Revision ID: 657ab8362756 -Revises: e06848138ff6 -Create Date: 2024-06-14 10:29:34.966812 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '657ab8362756' -down_revision = 'e06848138ff6' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('greeting', schema=None) as batch_op: - batch_op.add_column(sa.Column('character_id', sa.Integer(), nullable=False)) - batch_op.create_foreign_key(None, 'character', ['character_id'], ['id']) - - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('greeting', schema=None) as batch_op: - batch_op.drop_constraint(None, type_='foreignkey') - batch_op.drop_column('character_id') - - # ### end Alembic commands ### diff --git a/migrations/versions/8ed7775249e9_.py b/migrations/versions/8ed7775249e9_.py deleted file mode 100644 index b0070e1..0000000 --- a/migrations/versions/8ed7775249e9_.py +++ /dev/null @@ -1,34 +0,0 @@ -"""empty message - -Revision ID: 8ed7775249e9 -Revises: d7a96ea32a49 -Create Date: 2024-06-11 17:29:06.612117 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = '8ed7775249e9' -down_revision = 'd7a96ea32a49' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('greeting', - sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('greeting_text', sa.String(), nullable=False), - sa.Column('character_id', sa.Integer(), nullable=False), - sa.ForeignKeyConstraint(['character_id'], ['character.id'], ), - sa.PrimaryKeyConstraint('id') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('greeting') - # ### end Alembic commands ### diff --git a/migrations/versions/d7a96ea32a49_add_character_model.py b/migrations/versions/d7a96ea32a49_add_character_model.py deleted file mode 100644 index 43d6168..0000000 --- a/migrations/versions/d7a96ea32a49_add_character_model.py +++ /dev/null @@ -1,35 +0,0 @@ -"""Add character model - -Revision ID: d7a96ea32a49 -Revises: -Create Date: 2024-06-11 11:15:08.811220 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = 'd7a96ea32a49' -down_revision = None -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.create_table('character', - sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('name', sa.String(), nullable=False), - sa.Column('personality', sa.String(), nullable=False), - sa.Column('occupation', sa.String(), nullable=False), - sa.Column('age', sa.Integer(), nullable=False), - sa.PrimaryKeyConstraint('id') - ) - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - op.drop_table('character') - # ### end Alembic commands ### diff --git a/migrations/versions/e06848138ff6_.py b/migrations/versions/e06848138ff6_.py deleted file mode 100644 index 8db8df3..0000000 --- a/migrations/versions/e06848138ff6_.py +++ /dev/null @@ -1,34 +0,0 @@ -"""empty message - -Revision ID: e06848138ff6 -Revises: 8ed7775249e9 -Create Date: 2024-06-13 17:12:14.268947 - -""" -from alembic import op -import sqlalchemy as sa - - -# revision identifiers, used by Alembic. -revision = 'e06848138ff6' -down_revision = '8ed7775249e9' -branch_labels = None -depends_on = None - - -def upgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('greeting', schema=None) as batch_op: - batch_op.drop_constraint('greeting_character_id_fkey', type_='foreignkey') - batch_op.drop_column('character_id') - - # ### end Alembic commands ### - - -def downgrade(): - # ### commands auto generated by Alembic - please adjust! ### - with op.batch_alter_table('greeting', schema=None) as batch_op: - batch_op.add_column(sa.Column('character_id', sa.INTEGER(), autoincrement=False, nullable=False)) - batch_op.create_foreign_key('greeting_character_id_fkey', 'character', ['character_id'], ['id']) - - # ### end Alembic commands ### From 4ef1e880a9b2cec72e02a0763988cffd1fd22732 Mon Sep 17 00:00:00 2001 From: Adrian Prado Date: Tue, 5 Nov 2024 10:49:00 -0600 Subject: [PATCH 5/9] added generate_greetings function header --- app/routes/character_routes.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index 6cf5b52..e0db8bf 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -4,7 +4,6 @@ from ..models.greeting import Greeting from sqlalchemy import func, union, except_ - bp = Blueprint("characters", __name__, url_prefix="/characters") @bp.post("") @@ -49,6 +48,9 @@ def get_greetings(char_id): def add_greetings(char_id): pass +def generate_greetings(character): + pass + def validate_model(cls,id): try: id = int(id) From e59eefae150fe217e0404faedbb38905bd07231b Mon Sep 17 00:00:00 2001 From: Adrian Prado Date: Tue, 12 Nov 2024 16:47:15 -0600 Subject: [PATCH 6/9] Solution created using Gemini --- app/routes/character_routes.py | 57 +++++++++++--- migrations/README | 1 + migrations/alembic.ini | 50 ++++++++++++ migrations/env.py | 113 +++++++++++++++++++++++++++ migrations/script.py.mako | 24 ++++++ migrations/versions/0344241db67d_.py | 43 ++++++++++ requirements.txt | 23 ++++++ reset_db.py | 7 ++ 8 files changed, 306 insertions(+), 12 deletions(-) create mode 100644 migrations/README create mode 100644 migrations/alembic.ini create mode 100644 migrations/env.py create mode 100644 migrations/script.py.mako create mode 100644 migrations/versions/0344241db67d_.py create mode 100644 reset_db.py diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index e0db8bf..2b363c3 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -4,6 +4,11 @@ from ..models.greeting import Greeting from sqlalchemy import func, union, except_ +import google.generativeai as genai +import os + +genai.configure(api_key=os.environ.get("GEMINI_API_KEY")) + bp = Blueprint("characters", __name__, url_prefix="/characters") @bp.post("") @@ -28,28 +33,56 @@ def get_characters(): response = [] for character in characters: - response.append( - { - "id" : character.id, - "name" : character.name, - "personality" : character.personality, - "occupation" : character.occupation, - "age" : character.age - } - ) + response.append(character.to_dict()) return jsonify(response) @bp.get("//greetings") def get_greetings(char_id): - pass + character = validate_model(Character, char_id) + + if not character.greetings: + return make_response(jsonify(f"No greetings found for {character.name} "), 201) + + response = {"Character Name" : character.name, + "Greetings" : []} + for greeting in character.greetings: + response["Greetings"].append({ + "greeting" : greeting.greeting_text + }) + + return jsonify(response) + @bp.post("//generate") def add_greetings(char_id): - pass + character_obj = validate_model(Character, char_id) + greetings = generate_greetings(character_obj) + + if character_obj.greetings: + return make_response(jsonify(f"Greetings already generated for {character_obj.name} "), 201) + + new_greetings = [] + + for greeting in greetings: + new_greeting = Greeting( + greeting_text = greeting.strip("\""), + character = character_obj + ) + new_greetings.append(new_greeting) + + db.session.add_all(new_greetings) + db.session.commit() + + return make_response(jsonify(f"Greetings successfully added to {character_obj.name}"), 201) def generate_greetings(character): - pass + model = genai.GenerativeModel("gemini-1.5-flash") + input_message = f"I am writing a video game in the style of The Witcher. I have an npc named {character.name} who is {character.age} years old. They are a {character.occupation} who has a {character.personality} personality. Please generate a python style list of 10 stock phrases they might use when the main character talks to them. Please Return just the list without a variable name and square brackets." + response = model.generate_content(input_message) + response_sani = response.text.split("\n") + return response_sani[:-1] + def validate_model(cls,id): try: diff --git a/migrations/README b/migrations/README new file mode 100644 index 0000000..0e04844 --- /dev/null +++ b/migrations/README @@ -0,0 +1 @@ +Single-database configuration for Flask. diff --git a/migrations/alembic.ini b/migrations/alembic.ini new file mode 100644 index 0000000..ec9d45c --- /dev/null +++ b/migrations/alembic.ini @@ -0,0 +1,50 @@ +# A generic, single database configuration. + +[alembic] +# template used to generate migration files +# file_template = %%(rev)s_%%(slug)s + +# set to 'true' to run the environment during +# the 'revision' command, regardless of autogenerate +# revision_environment = false + + +# Logging configuration +[loggers] +keys = root,sqlalchemy,alembic,flask_migrate + +[handlers] +keys = console + +[formatters] +keys = generic + +[logger_root] +level = WARN +handlers = console +qualname = + +[logger_sqlalchemy] +level = WARN +handlers = +qualname = sqlalchemy.engine + +[logger_alembic] +level = INFO +handlers = +qualname = alembic + +[logger_flask_migrate] +level = INFO +handlers = +qualname = flask_migrate + +[handler_console] +class = StreamHandler +args = (sys.stderr,) +level = NOTSET +formatter = generic + +[formatter_generic] +format = %(levelname)-5.5s [%(name)s] %(message)s +datefmt = %H:%M:%S diff --git a/migrations/env.py b/migrations/env.py new file mode 100644 index 0000000..4c97092 --- /dev/null +++ b/migrations/env.py @@ -0,0 +1,113 @@ +import logging +from logging.config import fileConfig + +from flask import current_app + +from alembic import context + +# this is the Alembic Config object, which provides +# access to the values within the .ini file in use. +config = context.config + +# Interpret the config file for Python logging. +# This line sets up loggers basically. +fileConfig(config.config_file_name) +logger = logging.getLogger('alembic.env') + + +def get_engine(): + try: + # this works with Flask-SQLAlchemy<3 and Alchemical + return current_app.extensions['migrate'].db.get_engine() + except (TypeError, AttributeError): + # this works with Flask-SQLAlchemy>=3 + return current_app.extensions['migrate'].db.engine + + +def get_engine_url(): + try: + return get_engine().url.render_as_string(hide_password=False).replace( + '%', '%%') + except AttributeError: + return str(get_engine().url).replace('%', '%%') + + +# add your model's MetaData object here +# for 'autogenerate' support +# from myapp import mymodel +# target_metadata = mymodel.Base.metadata +config.set_main_option('sqlalchemy.url', get_engine_url()) +target_db = current_app.extensions['migrate'].db + +# other values from the config, defined by the needs of env.py, +# can be acquired: +# my_important_option = config.get_main_option("my_important_option") +# ... etc. + + +def get_metadata(): + if hasattr(target_db, 'metadatas'): + return target_db.metadatas[None] + return target_db.metadata + + +def run_migrations_offline(): + """Run migrations in 'offline' mode. + + This configures the context with just a URL + and not an Engine, though an Engine is acceptable + here as well. By skipping the Engine creation + we don't even need a DBAPI to be available. + + Calls to context.execute() here emit the given string to the + script output. + + """ + url = config.get_main_option("sqlalchemy.url") + context.configure( + url=url, target_metadata=get_metadata(), literal_binds=True + ) + + with context.begin_transaction(): + context.run_migrations() + + +def run_migrations_online(): + """Run migrations in 'online' mode. + + In this scenario we need to create an Engine + and associate a connection with the context. + + """ + + # this callback is used to prevent an auto-migration from being generated + # when there are no changes to the schema + # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html + def process_revision_directives(context, revision, directives): + if getattr(config.cmd_opts, 'autogenerate', False): + script = directives[0] + if script.upgrade_ops.is_empty(): + directives[:] = [] + logger.info('No changes in schema detected.') + + conf_args = current_app.extensions['migrate'].configure_args + if conf_args.get("process_revision_directives") is None: + conf_args["process_revision_directives"] = process_revision_directives + + connectable = get_engine() + + with connectable.connect() as connection: + context.configure( + connection=connection, + target_metadata=get_metadata(), + **conf_args + ) + + with context.begin_transaction(): + context.run_migrations() + + +if context.is_offline_mode(): + run_migrations_offline() +else: + run_migrations_online() diff --git a/migrations/script.py.mako b/migrations/script.py.mako new file mode 100644 index 0000000..2c01563 --- /dev/null +++ b/migrations/script.py.mako @@ -0,0 +1,24 @@ +"""${message} + +Revision ID: ${up_revision} +Revises: ${down_revision | comma,n} +Create Date: ${create_date} + +""" +from alembic import op +import sqlalchemy as sa +${imports if imports else ""} + +# revision identifiers, used by Alembic. +revision = ${repr(up_revision)} +down_revision = ${repr(down_revision)} +branch_labels = ${repr(branch_labels)} +depends_on = ${repr(depends_on)} + + +def upgrade(): + ${upgrades if upgrades else "pass"} + + +def downgrade(): + ${downgrades if downgrades else "pass"} diff --git a/migrations/versions/0344241db67d_.py b/migrations/versions/0344241db67d_.py new file mode 100644 index 0000000..47a14f8 --- /dev/null +++ b/migrations/versions/0344241db67d_.py @@ -0,0 +1,43 @@ +"""empty message + +Revision ID: 0344241db67d +Revises: +Create Date: 2024-11-05 16:05:21.795648 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '0344241db67d' +down_revision = None +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('character', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(), nullable=False), + sa.Column('personality', sa.String(), nullable=False), + sa.Column('occupation', sa.String(), nullable=False), + sa.Column('age', sa.Integer(), nullable=False), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('greeting', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('greeting_text', sa.String(), nullable=False), + sa.Column('character_id', sa.Integer(), nullable=False), + sa.ForeignKeyConstraint(['character_id'], ['character.id'], ), + sa.PrimaryKeyConstraint('id') + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('greeting') + op.drop_table('character') + # ### end Alembic commands ### diff --git a/requirements.txt b/requirements.txt index f9c8b70..d3d48f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,15 +2,27 @@ alembic==1.13.1 annotated-types==0.6.0 anyio==4.3.0 blinker==1.7.0 +cachetools==5.5.0 certifi==2024.2.2 +charset-normalizer==3.4.0 click==8.1.7 distro==1.9.0 Flask==3.0.2 Flask-Migrate==4.0.5 Flask-SQLAlchemy==3.1.1 +google-ai-generativelanguage==0.6.10 +google-api-core==2.22.0 +google-api-python-client==2.151.0 +google-auth==2.35.0 +google-auth-httplib2==0.2.0 +google-generativeai==0.8.3 +googleapis-common-protos==1.65.0 greenlet==3.0.3 +grpcio==1.67.1 +grpcio-status==1.67.1 h11==0.14.0 httpcore==1.0.5 +httplib2==0.22.0 httpx==0.27.0 idna==3.7 iniconfig==2.0.0 @@ -18,15 +30,26 @@ itsdangerous==2.1.2 Jinja2==3.1.3 Mako==1.3.2 MarkupSafe==2.1.5 +openai==1.35.3 packaging==23.2 pluggy==1.4.0 +proto-plus==1.25.0 +protobuf==5.28.3 psycopg2-binary==2.9.9 +pyasn1==0.6.1 +pyasn1_modules==0.4.1 pydantic==2.7.1 pydantic_core==2.18.2 +pyparsing==3.2.0 pytest==8.0.0 python-dotenv==1.0.1 +requests==2.32.3 +rsa==4.9 sniffio==1.3.1 SQLAlchemy==2.0.25 tqdm==4.66.4 typing_extensions==4.9.0 +uritemplate==4.1.1 +urllib3==2.2.3 Werkzeug==3.0.1 +wonderwords==2.2.0 diff --git a/reset_db.py b/reset_db.py new file mode 100644 index 0000000..105f11d --- /dev/null +++ b/reset_db.py @@ -0,0 +1,7 @@ +from app import create_app, db + + +my_app = create_app() +with my_app.app_context(): + db.session.clear() + print("Session cleared.") \ No newline at end of file From b382021822ce1f559c58a1b1abda362abdd096a2 Mon Sep 17 00:00:00 2001 From: Adrian Prado Date: Tue, 12 Nov 2024 16:53:03 -0600 Subject: [PATCH 7/9] Changed variable names and added comments --- app/routes/character_routes.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index 2b363c3..82a3c6e 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -66,7 +66,7 @@ def add_greetings(char_id): for greeting in greetings: new_greeting = Greeting( - greeting_text = greeting.strip("\""), + greeting_text = greeting.strip("\""), #Removes quotes from each string character = character_obj ) new_greetings.append(new_greeting) @@ -78,10 +78,10 @@ def add_greetings(char_id): def generate_greetings(character): model = genai.GenerativeModel("gemini-1.5-flash") - input_message = f"I am writing a video game in the style of The Witcher. I have an npc named {character.name} who is {character.age} years old. They are a {character.occupation} who has a {character.personality} personality. Please generate a python style list of 10 stock phrases they might use when the main character talks to them. Please Return just the list without a variable name and square brackets." + input_message = f"I am writing a rantasy RPG video game. I have an npc named {character.name} who is {character.age} years old. They are a {character.occupation} who has a {character.personality} personality. Please generate a python style list of 10 stock phrases they might use when the main character talks to them. Please Return just the list without a variable name and square brackets." response = model.generate_content(input_message) - response_sani = response.text.split("\n") - return response_sani[:-1] + response_split = response.text.split("\n") #Splits response into a list of stock phrases, ends up with an empty string at index -1 + return response_split[:-1] #Returns the stock phrases list, just without the empty string at the end def validate_model(cls,id): From 2592fbd98507c240efc6152428c0f656be804d67 Mon Sep 17 00:00:00 2001 From: Kelsey Steven Date: Tue, 26 Nov 2024 12:20:47 -0800 Subject: [PATCH 8/9] Remove jsonify and make_response where possible --- app/routes/character_routes.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index 82a3c6e..3806916 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -1,4 +1,4 @@ -from flask import Blueprint, jsonify, request, abort, make_response +from flask import Blueprint, request, abort, make_response from ..db import db from ..models.character import Character from ..models.greeting import Greeting @@ -20,7 +20,7 @@ def create_character(): db.session.add(new_character) db.session.commit() - return make_response(new_character.to_dict(), 201) + return new_character.to_dict(), 201 except KeyError as e: abort(make_response({"message": f"missing required value: {e}"}, 400)) @@ -35,14 +35,14 @@ def get_characters(): for character in characters: response.append(character.to_dict()) - return jsonify(response) + return response @bp.get("//greetings") def get_greetings(char_id): character = validate_model(Character, char_id) if not character.greetings: - return make_response(jsonify(f"No greetings found for {character.name} "), 201) + return {"message": f"No greetings found for {character.name} "}, 201 response = {"Character Name" : character.name, "Greetings" : []} @@ -51,7 +51,7 @@ def get_greetings(char_id): "greeting" : greeting.greeting_text }) - return jsonify(response) + return response @bp.post("//generate") @@ -60,7 +60,7 @@ def add_greetings(char_id): greetings = generate_greetings(character_obj) if character_obj.greetings: - return make_response(jsonify(f"Greetings already generated for {character_obj.name} "), 201) + return {"message": f"Greetings already generated for {character_obj.name} "}, 201 new_greetings = [] @@ -74,7 +74,7 @@ def add_greetings(char_id): db.session.add_all(new_greetings) db.session.commit() - return make_response(jsonify(f"Greetings successfully added to {character_obj.name}"), 201) + return {"message": f"Greetings successfully added to {character_obj.name}"}, 201 def generate_greetings(character): model = genai.GenerativeModel("gemini-1.5-flash") @@ -88,7 +88,7 @@ def validate_model(cls,id): try: id = int(id) except: - response = response = {"message": f"{cls.__name__} {id} invalid"} + response = {"message": f"{cls.__name__} {id} invalid"} abort(make_response(response , 400)) query = db.select(cls).where(cls.id == id) From cb4eb893db5c40d2ed3186d9b756a6b6786ee2d4 Mon Sep 17 00:00:00 2001 From: Kelsey Steven Date: Tue, 26 Nov 2024 12:28:02 -0800 Subject: [PATCH 9/9] Small changes to typo & casing in prompt to match lesson --- app/routes/character_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/routes/character_routes.py b/app/routes/character_routes.py index 3806916..ad1fd59 100644 --- a/app/routes/character_routes.py +++ b/app/routes/character_routes.py @@ -78,7 +78,7 @@ def add_greetings(char_id): def generate_greetings(character): model = genai.GenerativeModel("gemini-1.5-flash") - input_message = f"I am writing a rantasy RPG video game. I have an npc named {character.name} who is {character.age} years old. They are a {character.occupation} who has a {character.personality} personality. Please generate a python style list of 10 stock phrases they might use when the main character talks to them. Please Return just the list without a variable name and square brackets." + input_message = f"I am writing a fantasy RPG video game. I have an npc named {character.name} who is {character.age} years old. They are a {character.occupation} who has a {character.personality} personality. Please generate a Python style list of 10 stock phrases they might use when the main character talks to them. Please return just the list without a variable name and square brackets." response = model.generate_content(input_message) response_split = response.text.split("\n") #Splits response into a list of stock phrases, ends up with an empty string at index -1 return response_split[:-1] #Returns the stock phrases list, just without the empty string at the end