evBackend / TextGen /gemini.py
Jofthomas's picture
Jofthomas HF staff
Update TextGen/gemini.py
4124932
import google.generativeai as genai
from google.api_core import retry
import os
import pathlib
import textwrap
import json
GOOGLE_API_KEY = os.environ['GOOGLE_API_KEY']
genai.configure(api_key=GOOGLE_API_KEY)
model = genai.GenerativeModel(model_name='models/gemini-1.5-pro-latest')
def generate_story(available_items):
response = model.generate_content(f"""
You are game master in a roguelike game. You should help me create an consise objective for the player to fulfill in the current level.
Our protagonist, A girl with a red hood is wandering inside a dungeon.
You are ONLY allowed to only use the following elements and not modify either the map or the enemies:
{available_items}
Example of possible Objectives:
Example 1 : Defeat N monster $monster_name and then report it to npc :$npc_name
Example 2 : Loot two treasure chest then defeat the boss $boss_name to exit.
A object of type NPC can be talked to but can't move and can't be fought, an ennemy type object can be fought but not talked to. A boss can be fought but not talked to
To escape, the player will have to pass by the portal.
""", request_options={'retry': retry.Retry()})
story = response.text
return story
def place_objects(available_items,story,myMap):
prompt = f"""
Please return JSON describing the objective of this level, the objects that should be placed as well as all enemies/npcs that shall be placed:
{{"objective": str, "objects":list[OBJECT], "enemies":list[ENEMIES], "boss":list[BOSS],"npcs": list[NPC]}}
In all of the following example, placement is the id of the room to place the object in.
# The Objects that should be placed in the treasure chests
OBJECT = {{"name": str, "description": str,"placement": int, "strength": str, "speed": str}}
# The infos necessary about the enemies
ENEMIES = {{"name": str, "placement": int}}
# The NPC that should be added to the map
NPC = {{"name": str, "persona": str, "placement": int}}
# The Boss monster of this level.
BOSS = {{"name": str, "placement": int}}
For objects, the name key represents the name of the object inside the treasure chest
when placement is requiered, it is the id of the room on the map.
All fields are not necessarily required; if null, don't add it. it should make sense with the crafted story.
Items can only be weapons or objects that can be useful for a special quest. "strength" and "speed" should only be declared for weapons and can only range between 0 and 1. 0 being a rusty sword and 1 being the best sword in the game.
Important: Only return a single piece of valid JSON text.
Here is the map:
{myMap}
X: is the starting position of the player
?: represent and interesting room where it could be interesting to place an object
numbers represent the index of the room
and the objective of this level: {story}
The objective MUST be feasible, otherwise the player will be stuck.
REMEMBER, You are ONLY allowed to only use the following elements and not modify either the map or the enemies:
{available_items}
"""
print(prompt)
response = model.generate_content(
prompt,
generation_config={'response_mime_type':'application/json'}
)
try:
map_placements=json.dumps(json.loads(response.text), indent=4)
except:
map_placements="error"
return map_placements
def get_items_string_representation(items_list):
result = ""
for item in items_list:
item_str = "Name: " + item["name"] + ", Type: " + item["type"] + ", Description: " + item["description"] + "\n"
result += item_str
return result
def generate_map_markdown(rooms, room_of_interest,index_exit):
import numpy as np
# Define the room structure with walls and markers
def create_room(room_char, index):
index_str = f"{index}".zfill(2) # Zero pad index to 2 digits if needed
if index_str[0] !="0":
first_number=index_str[0]
else:
first_number=" "
return [
f"╔═{room_char}═╗",
f"β•‘ {first_number}{index_str[1]}β•‘",
f"β•šβ•β•β•β•"
]
# Extract rooms and rooms of interest
rooms = [eval(room) for room in rooms]
rooms_of_interest = [eval(room) for room in room_of_interest]
# Determine grid size
min_x = min(room[0] for room in rooms)
max_x = max(room[0] for room in rooms)
min_y = min(room[1] for room in rooms)
max_y = max(room[1] for room in rooms)
# Create grid with empty spaces represented by a room-like structure
map_height = (max_y - min_y + 1) * 3
map_width = (max_x - min_x + 1) * 5
grid = np.full((map_height, map_width), " ")
# Populate grid with rooms and their characteristics
for i, room in enumerate(rooms):
x, y = room
x_offset = (x - min_x) * 5
y_offset = (max_y - y) * 3
if room == (0, 0):
room_char = "X"
elif room in rooms_of_interest:
room_char = "P" if i == index_exit else "?"
else:
room_char = " "
room_structure = create_room(room_char, i)
for j, row in enumerate(room_structure):
grid[y_offset + j, x_offset:x_offset + 5] = list(row)
# Convert grid to a string format suitable for display
markdown_map = "\n".join("".join(row) for row in grid)
# Return the map wrapped in triple backticks for proper display in markdown
return f"```\n{markdown_map}\n```"