Hello Everyone!
This is the first post of a series for my Development Blog, if you want to know what this is about you can check my previous article DevBlog #0 Introduction.
Introduction
OSR TTRPG Games have a lot of reference tables, such as places, monsters, weapons, and in this article I'll try to make autogenerated content using OpenAI for a Terrains Table.
I want to generate description of the following terrains:
- Valley
- Forest
- Mountains
- Grasslands
- Desert
- Swamp
And the description can vary depending on if it is day or night.
Creating RandomTableGenerator Lambda function
For this I'm going to use a Lambda Function using Python, So I have created a function called: RandomTableGenerator
using Pyhton 3.8 version.
For the purpose of this post I'm going to just use the default lambda handler: lambda_function.lambda_handler
that comes already in the lambda function.
Adding roll dice function
The first thing we need to do is to add a function that returns a random number and two variables to get the value of the dice.
import random
terrains_table = [
"Valley",
"Forest",
"Mountains",
"Grasslands",
"Desert",
"Swamp"
]
time_table = [
"day",
"night"
]
def roll_dice(number):
result = random.randint(1, number)
return result
def lambda_handler(event, context):
terrain_id = roll_dice(6)
time_id = roll_dice(2)
terrain = terrains_table[terrain_id -1]
time = time_table[time_id -1]
print(terrain)
print(time)
Creating Terrains DynamoDB Table
Now that we have the terrain value and time value, we are going to look in a DynamoDB table if the item already exists.
For this I'm going to create a Terrains
DynamoDB Table using terrain_id
as the partition_key
and time_id
as the sort_key
, that way I can get the item using both values.
Adding get terrain by time function
Now we need to add the code to look for items and create items if those doesn't exists.
import random
import boto3
def roll_dice(number):
# code
def get_terrain_by_time(terrain_id, time_id):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Terrains')
response = table.get_item(
Key={
'terrain_id': terrain_id,
'time_id': time_id
}
)
item = response.get('Item')
if not item:
return False
return item
def lambda_handler(event, context):
terrain_id = roll_dice(6)
time_id = roll_dice(2)
terrain = terrains_table[terrain_id -1]
time = time_table[time_id -1]
item = get_terrain_by_time(terrain_id, time_id)
if not item:
# item doesn't exist
return item
Adding create terrain function
Now we are going to create a new function for creating the item.
import random
import boto3
def roll_dice(number):
# code
def get_terrain_by_time(terrain_id, time_id):
# code
def create_terrain(terrain_id, time_id, name, time, description):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('Terrains')
item = {
'terrain_id': terrain_id,
'time_id': time_id,
'terrain': name,
'time': time,
'description': description
}
response = table.put_item(Item=item)
if response['ResponseMetadata']['HTTPStatusCode'] == 200:
return item
else:
return None
def lambda_handler(event, context):
terrain_id = roll_dice(6)
time_id = roll_dice(2)
terrain = terrains_table[terrain_id -1]
time = time_table[time_id -1]
description = ""
item = get_terrain_by_time(terrain_id, time_id)
if not item:
item = create_terrain(terrain_id, time_id, name, time, description)
return item
Ok now if the item we are looking for doesn't exist it will create the item and return it.
Adding OpenAI Lambda Layer
In the next step we are going to generate some description based on our input using OpenAI.
Note: OpenAI package is not availble in AWS Lambda, so what we need to to is to add a Lambda Layer containing the openai package and its dependencies, fortunately the GitHub User: erenyasarkurt (shootout to him) created a repository with releases of this lambda layet, you can find these release in the following GitHub Repo: erenyasarkurt/OpenAI-AWS-Lambda-Layer.
Download the release for your Python version and create a new layer in Lambda, after that update your Lambda function to use the layer.
Now go to Configuration / Environment variables and create a new variable called OPENAI_API_KEY
and add your key as the value.
If you don't have an OpenAI API Key you can signup and create a key, you can also follow this OpenAI Introduction.
Adding generate terrain description function
Now that we have our openai layer and our key in an environment variable, we can continue with the code.
The next step is to create a new funcion that will generate a description based on the terrain
and time
.
import os
import random
import boto3
import openai
def roll_dice(number):
# code
def get_terrain_by_time(terrain_id, time_id):
# code
def generate_terrain_description(terrain, time):
openai_api_key = os.environ.get("OPENAI_API_KEY")
prompt_template = """I am scene description Game Master.
You can give me description criteria and I will describe the scene only with the given description criteria.
My answer will be a paragraph no longer than 4 lines and will use a description in a Game Master Syle.
\n
\nDescription criteria:
\n- Terrain: _terrain_
\n- Time of the day: _time_
\n"""
my_prompt = prompt_template.replace("_terrain_", terrain)
my_prompt = my_prompt.replace("time", time)
response = openai.Completion.create(
model="text-davinci-003",
prompt=my_prompt,
temperature=0,
max_tokens=100,
top_p=1,
frequency_penalty=0.0,
presence_penalty=0.0,
stop=["\n"]
)
return response.choices[0]["text"]
def create_terrain(terrain_id, time_id, name, time, description):
# code
def lambda_handler(event, context):
terrain_id = roll_dice(6)
time_id = roll_dice(2)
terrain = terrains_table[terrain_id -1]
time = time_table[time_id -1]
item = get_terrain_by_time(terrain_id, time_id)
if not item:
description = generate_terrain_description(terrain, time)
item = create_terrain(terrain_id, time_id, terrain, time, description)
return item
Final result
If everything went well, you will have the following output in your Lambda function:
{
"terrain_id": 2,
"time_id": 2,
"description": "The forest is shrouded in darkness, the only light coming from the stars and the moon. The trees stand tall and silent, their branches swaying gently in the night breeze. The air is still and the only sound is the occasional chirp of a night bird.",
"terrain": "Forest",
"time": "night"
}
So that's all for this article, in the next one I plan to generate images using Dall-e-2 and adding all the code in a GitHub Repository.
Stay tuned!
Cover by @andrewtneel
Top comments (0)