Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
232e416
Removed solution from master branch
apradoada Jun 17, 2024
4c9b012
removed OpenAI library from imports
apradoada Jun 18, 2024
df2f4ed
Remove OpenAI References
apradoada Jun 21, 2024
bc81ef4
remove
apradoada Jun 21, 2024
4ef1e88
added generate_greetings function header
apradoada Nov 5, 2024
e59eefa
Solution created using Gemini
apradoada Nov 12, 2024
b382021
Changed variable names and added comments
apradoada Nov 12, 2024
e80f5da
Update to remove jsonify and return data structures directly followin…
kelsey-steven-ada Nov 26, 2024
2592fbd
Remove jsonify and make_response where possible
kelsey-steven-ada Nov 26, 2024
cb4eb89
Small changes to typo & casing in prompt to match lesson
kelsey-steven-ada Nov 26, 2024
d778d71
Remove duplicate response var name in validate_model
kelsey-steven-ada Nov 26, 2024
fa6ecfc
Merge pull request #3 from AdaGold/ks_change_return_values
kelsey-steven-ada Nov 26, 2024
68bc123
Merge pull request #4 from AdaGold/ks_update_solution_return_values
kelsey-steven-ada Nov 26, 2024
f82340c
Update dependencies for Python 3.13
kelsey-steven-ada Mar 6, 2025
059da5a
Fresh install dependencies to avoid building older version of depende…
kelsey-steven-ada Mar 7, 2025
1c72085
Update requirements.txt
kelsey-steven-ada Mar 10, 2025
84d53f3
Merge pull request #5 from AdaGold/ks_update_dependencies_python_3.13
kelsey-steven-ada Mar 10, 2025
3a7b9d1
Merge pull request #6 from AdaGold/ks_update_solution_dependencies
kelsey-steven-ada Mar 10, 2025
5139768
updates solution from Learn snippets
anselrognlie Dec 9, 2025
9531d34
updates formatting
anselrognlie Dec 9, 2025
0253ad3
updates formatting
anselrognlie Dec 9, 2025
afb5936
condenses api route logic
anselrognlie Dec 9, 2025
45ef268
adds get one route and condenses route logic
anselrognlie Dec 9, 2025
e7f0091
Merge branch 'main' into solution-with-gemini
anselrognlie Dec 9, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
from .db import db, migrate
from .models import character, greeting


def create_app(test_config=None):
app = Flask(__name__)

if not test_config:
db_to_use = os.environ.get("SQLALCHEMY_DATABASE_URI")
else:
db_to_use = os.environ.get("SQLALCHEMY_TEST_DATABASE_URI")


app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = db_to_use
Expand All @@ -21,4 +21,4 @@ def create_app(test_config=None):

app.register_blueprint(bp)

return app
return app
3 changes: 2 additions & 1 deletion app/models/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from sqlalchemy.orm import DeclarativeBase


class Base(DeclarativeBase):
pass
pass
23 changes: 12 additions & 11 deletions app/models/character.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
from sqlalchemy.orm import Mapped, mapped_column, relationship
from ..db import db


class Character(db.Model):
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
name: Mapped[str]
personality: Mapped[str]
occupation: Mapped[str]
age: Mapped[int]
greetings: Mapped[list["Greeting"]] = relationship(back_populates="character")

def to_dict(self):
return {
"id" : self.id,
"name" : self.name,
"personality" : self.personality,
"occupation" : self.occupation,
"age" : self.age
"id": self.id,
"name": self.name,
"personality": self.personality,
"occupation": self.occupation,
"age": self.age
}

@classmethod
def from_dict(cls, data_dict):
new_character = cls(
name = data_dict["name"],
personality = data_dict["personality"],
occupation = data_dict["occupation"],
age = data_dict["age"]
name=data_dict["name"],
personality=data_dict["personality"],
occupation=data_dict["occupation"],
age=data_dict["age"]
)

return new_character
11 changes: 6 additions & 5 deletions app/models/greeting.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
from sqlalchemy import ForeignKey
from ..db import db


class Greeting(db.Model):
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
greeting_text: Mapped[str]
character_id: Mapped[int] = mapped_column(ForeignKey("character.id"))
character_id: Mapped[int] = mapped_column(ForeignKey("character.id"))
character: Mapped["Character"] = relationship(back_populates="greetings")

def to_dict(self):
def to_dict(self):
return {
"id" : self.id,
"greeting" : self.greeting_text,
}
"id": self.id,
"greeting": self.greeting_text,
}
98 changes: 46 additions & 52 deletions app/routes/character_routes.py
Original file line number Diff line number Diff line change
@@ -1,109 +1,103 @@
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
from sqlalchemy import func, union, except_
from openai import OpenAI

from google import genai

client = genai.Client()

bp = Blueprint("characters", __name__, url_prefix="/characters")
client = OpenAI()


@bp.post("")
def create_character():

request_body = request.get_json()
try:
try:
new_character = Character.from_dict(request_body)
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))


@bp.get("")
def get_characters():
character_query = db.select(Character)

characters = db.session.scalars(character_query)
response = []

for character in characters:
response.append(
{
"id" : character.id,
"name" : character.name,
"personality" : character.personality,
"occupation" : character.occupation,
"age" : character.age
}
)
response = [character.to_dict() for character in characters]

return response


@bp.get("/<char_id>")
def get_character(char_id):
character = validate_model(Character, char_id)
return character.to_dict()

return jsonify(response)

@bp.get("/<char_id>/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)

response = [greeting.to_dict() for greeting in character.greetings]

return response


@bp.post("/<char_id>/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)

return {"message": f"Greetings already generated for {character_obj.name} "}, 201

greetings = generate_greetings(character_obj)

new_greetings = []

for greeting in greetings:
text = greeting[greeting.find(" ")+1:]
new_greeting = Greeting(
greeting_text = text.strip("\""),
character = character_obj
greeting_text=greeting,
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)
return {"message": 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}
]
def generate_greetings(character):
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 = client.models.generate_content(
model="gemini-2.5-flash", contents=input_message
)
return(completion.choices[0].message.content.split("\n"))

def validate_model(cls,id):
lines = response.text.splitlines()

# Strip leading and trailing quotes and commas from each greeting
return [line.strip("\"',") for line in lines]


def validate_model(cls, id):
try:
id = int(id)
except:
response = response = {"message": f"{cls.__name__} {id} invalid"}
abort(make_response(response , 400))
response = {"message": f"{cls.__name__} {id} invalid"}
abort(make_response(response, 400))

query = db.select(cls).where(cls.id == id)
model = db.session.scalar(query)
if model:
return model

response = {"message": f"{cls.__name__} {id} not found"}
abort(make_response(response, 404))
abort(make_response(response, 404))
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
"""Add character model
"""empty message

Revision ID: d7a96ea32a49
Revision ID: 0344241db67d
Revises:
Create Date: 2024-06-11 11:15:08.811220
Create Date: 2024-11-05 16:05:21.795648

"""
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'd7a96ea32a49'
revision = '0344241db67d'
down_revision = None
branch_labels = None
depends_on = None
Expand All @@ -26,10 +26,18 @@ def upgrade():
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 ###
34 changes: 0 additions & 34 deletions migrations/versions/657ab8362756_.py

This file was deleted.

34 changes: 0 additions & 34 deletions migrations/versions/8ed7775249e9_.py

This file was deleted.

34 changes: 0 additions & 34 deletions migrations/versions/e06848138ff6_.py

This file was deleted.

Loading