File size: 6,964 Bytes
0b75c79 97f15a5 0b75c79 97f15a5 0b75c79 97f15a5 0b75c79 97f15a5 0b75c79 97f15a5 0b75c79 97f15a5 0b75c79 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
import re
import json
import ast
import requests
import gradio as gr
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_upstage import ChatUpstage
def generate_character_creation_questions(api_key, world_summary, language="korean"):
llm = ChatUpstage(api_key=api_key)
questions_prompt_template = PromptTemplate.from_template(
"""
Based on the following novel context, generate five simple questions that a player should answer to help create a deeply personalized character for a fantasy RPG.
The questions should explore different aspects of a potential characterβs personality, background, and capabilities.
For users who are not used to the story I want you to give several choices in the question.
Write five questions in Korean(νκΈ).
Your response should be python list with strings consist of questions.
---
Novel Context: {Context}
---
Format: ['λΉμ μ ...? (λ΅λ³μ μμ: ...): ', ...]
---
Questions:
"""
)
questions_chain = questions_prompt_template | llm | StrOutputParser()
default_questions = [
"λΉμ μ μΊλ¦ν° μ΄λ¦μ 무μμΈκ°μ? (μ€ν΅ν μ μλμΌλ‘ μ΄λ¦μ΄ μμ±λ©λλ€): ",
"λΉμ μ μΊλ¦ν°μ μ±λ³μ 무μμΈκ°μ? (μ€ν΅ν μ μλμΌλ‘ μ±λ³μ΄ μ νλ©λλ€): ",
"λΉμ μ μΊλ¦ν°λ λͺμ΄μΈκ°μ? (μ€ν΅ν μ μλμΌλ‘ λμ΄κ° μ νλ©λλ€): ",
]
while True:
try:
questions = questions_chain.invoke({"Context": world_summary})
questions_list = ast.literal_eval(questions)
questions_list = [question.replace('[', '').replace(']', '') for question in questions_list]
return default_questions + questions_list
except Exception as e:
print(f"Error generating questions: {e}")
continue
def create_character_profile(api_key, questions, answers, language="korean"):
llm = ChatUpstage(api_key=api_key)
character_creation_prompt_template = PromptTemplate.from_template(
"""
Using the answers provided below, create a detailed character profile for a fantasy tabletop RPG.
The character should reflect the given attributes. Please ensure to use the specified field names and format in your output consistently.
Consider Player's answers as the input and generate a character profile based on the given context.
When player's answer is not given, please use a appropriate value for corresponding fields made by yourself.
**Output should strictly follow this format:**
- name: "character name"
- gender: "Male" or "Female"
- age: age on integer
- race: "character race"
- job: "character job"
- stamina: integer between [1, 100]
- intelligence: integer between [1, 100]
- combat_power: integer between [1, 100]
- agility: integer between [1, 100]
- background: "character background"
**Player Answers:**
qna:
{qna}
---
Please write the output in English.
"""
)
character_creation_chain = character_creation_prompt_template | llm | StrOutputParser()
qna = [f"Q: {questions[i]}\nA: {answers[i]}" for i in range(len(questions))]
character_description = character_creation_chain.invoke({"qna": qna, "Language": language})
return character_description
def parse_character_data_to_json(text):
fields = {
'name': r"- name: (.*)",
'gender': r"- gender: (.*)",
'age': r"- age: (\d+)",
'race': r"- race: (.*)",
'job': r"- job: (.*)",
'background': r"- background: (.*)"
}
param_fields = {
'stamina': r"- stamina: (\d+)",
'intelligence': r"- intelligence: (\d+)",
'combat_power': r"- combat_power: (\d+)",
'agility': r"- agility: (\d+)"
}
character_dict = {}
params_dict = {}
for key, pattern in fields.items():
match = re.search(pattern, text)
if match:
character_dict[key] = match.group(1)
for key, pattern in param_fields.items():
match = re.search(pattern, text)
if match:
params_dict[key] = int(match.group(1))
character_dict['params'] = params_dict
return character_dict
def run_question_generation(api_key, file_path):
# Read the world summary from the uploaded file
with open(file_path, 'r', encoding='utf-8') as file:
world_summary = file.read()
# Generate questions
questions = generate_character_creation_questions(api_key, world_summary)
return questions
def run_profile_generation(api_key, file_path, *answers):
questions = run_question_generation(api_key, file_path)
# Generate character profile
character_description = create_character_profile(api_key, questions, answers)
character_json = parse_character_data_to_json(character_description)
return character_description, json.dumps(character_json, indent=4, ensure_ascii=False)
def main():
with gr.Blocks() as demo:
gr.Markdown("## Fantasy RPG Character Creator")
with gr.Row():
api_key_input = gr.Textbox(label="API Key", placeholder="Enter your API key here", type="password")
file_input = gr.File(label="Upload World Summary Text File", type="filepath")
questions_output = gr.JSON(label="Generated Questions")
# Button to generate questions
generate_questions_button = gr.Button("Generate Questions")
# Answers input section
answers_input = [gr.Textbox(label=f"Answer {i+1}", placeholder="Type your answer here") for i in range(8)]
# Outputs for character description and JSON
character_description_output = gr.Textbox(label="Character Description", lines=10)
json_output = gr.JSON(label="Character JSON")
# Button to run the profile generation
generate_profile_button = gr.Button("Generate Character Profile")
# Define button click actions
def on_generate_questions(api_key, file_path):
questions = run_question_generation(api_key, file_path)
for i, question in enumerate(questions):
answers_input[i].label = question
return questions
generate_questions_button.click(
fn=on_generate_questions,
inputs=[api_key_input, file_input],
outputs=questions_output
)
generate_profile_button.click(
fn=run_profile_generation,
inputs=[api_key_input, file_input, *answers_input],
outputs=[character_description_output, json_output]
)
# Launch the Gradio interface
demo.launch()
if __name__ == "__main__":
main() |