shigeru saito
commited on
Commit
•
3cef652
1
Parent(s):
8794494
first commit
Browse files- .gitignore +1 -0
- app.py +262 -0
- constraints.md +13 -0
- requirements.txt +5 -0
- schema.json +56 -0
- template.md +7 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
.env
|
app.py
ADDED
@@ -0,0 +1,262 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import openai
|
3 |
+
import requests
|
4 |
+
import os
|
5 |
+
from dotenv import load_dotenv
|
6 |
+
import io
|
7 |
+
import sys
|
8 |
+
import json
|
9 |
+
import PIL
|
10 |
+
import time
|
11 |
+
from stability_sdk import client
|
12 |
+
import stability_sdk.interfaces.gooseai.generation.generation_pb2 as generation
|
13 |
+
import markdown2
|
14 |
+
|
15 |
+
title="Character Generator AI"
|
16 |
+
inputs_label="Please tell me the characteristics of the character you want to create"
|
17 |
+
outputs_label="AI will generate a character description and visualize it"
|
18 |
+
visual_outputs_label="Character Visuals"
|
19 |
+
description="""
|
20 |
+
- Please input within the limits of 1000 characters. It may take about 50 seconds to generate a response.
|
21 |
+
"""
|
22 |
+
|
23 |
+
article = """
|
24 |
+
"""
|
25 |
+
|
26 |
+
load_dotenv()
|
27 |
+
openai.api_key = os.getenv('OPENAI_API_KEY')
|
28 |
+
os.environ['STABILITY_HOST'] = 'grpc.stability.ai:443'
|
29 |
+
stability_api = client.StabilityInference(
|
30 |
+
key=os.getenv('STABILITY_KEY'),
|
31 |
+
verbose=True,
|
32 |
+
engine="stable-diffusion-xl-1024-v1-0",
|
33 |
+
)
|
34 |
+
MODEL = "gpt-4"
|
35 |
+
|
36 |
+
def get_filetext(filename, cache={}):
|
37 |
+
if filename in cache:
|
38 |
+
return cache[filename]
|
39 |
+
else:
|
40 |
+
if not os.path.exists(filename):
|
41 |
+
raise ValueError(f"File '{filename}' not found")
|
42 |
+
with open(filename, "r") as f:
|
43 |
+
text = f.read()
|
44 |
+
cache[filename] = text
|
45 |
+
return text
|
46 |
+
|
47 |
+
def get_functions_from_schema(filename):
|
48 |
+
schema = get_filetext(filename)
|
49 |
+
schema_json = json.loads(schema)
|
50 |
+
functions = schema_json.get("functions")
|
51 |
+
return functions
|
52 |
+
|
53 |
+
class StabilityAI:
|
54 |
+
@classmethod
|
55 |
+
def generate_image(cls, visualize_prompt):
|
56 |
+
|
57 |
+
print("visualize_prompt:"+visualize_prompt)
|
58 |
+
|
59 |
+
answers = stability_api.generate(
|
60 |
+
prompt=visualize_prompt,
|
61 |
+
)
|
62 |
+
|
63 |
+
for resp in answers:
|
64 |
+
for artifact in resp.artifacts:
|
65 |
+
if artifact.finish_reason == generation.FILTER:
|
66 |
+
print("NSFW")
|
67 |
+
if artifact.type == generation.ARTIFACT_IMAGE:
|
68 |
+
img = PIL.Image.open(io.BytesIO(artifact.binary))
|
69 |
+
return img
|
70 |
+
|
71 |
+
class OpenAI:
|
72 |
+
|
73 |
+
@classmethod
|
74 |
+
def chat_completion(cls, prompt, start_with=""):
|
75 |
+
constraints = get_filetext(filename = "constraints.md")
|
76 |
+
template = get_filetext(filename = "template.md")
|
77 |
+
|
78 |
+
data = {
|
79 |
+
"model": MODEL,
|
80 |
+
"messages": [
|
81 |
+
{"role": "system", "content": constraints}
|
82 |
+
,{"role": "assistant", "content": template}
|
83 |
+
,{"role": "user", "content": prompt}
|
84 |
+
,{"role": "assistant", "content": start_with}
|
85 |
+
],
|
86 |
+
}
|
87 |
+
|
88 |
+
start = time.time()
|
89 |
+
response = requests.post(
|
90 |
+
"https://api.openai.com/v1/chat/completions",
|
91 |
+
headers={
|
92 |
+
"Content-Type": "application/json",
|
93 |
+
"Authorization": f"Bearer {openai.api_key}"
|
94 |
+
},
|
95 |
+
json=data
|
96 |
+
)
|
97 |
+
print("gpt generation time: "+str(time.time() - start))
|
98 |
+
|
99 |
+
result = response.json()
|
100 |
+
print(result)
|
101 |
+
|
102 |
+
content = result["choices"][0]["message"]["content"].strip()
|
103 |
+
|
104 |
+
visualize_prompt = content.split("### Prompt for Visual Expression\n\n")[1]
|
105 |
+
|
106 |
+
answers = stability_api.generate(
|
107 |
+
prompt=visualize_prompt,
|
108 |
+
)
|
109 |
+
|
110 |
+
@classmethod
|
111 |
+
def chat_completion_with_function(cls, prompt, messages, functions):
|
112 |
+
print("prompt:"+prompt)
|
113 |
+
|
114 |
+
# 文章生成にかかる時間を計測する
|
115 |
+
start = time.time()
|
116 |
+
# ChatCompletion APIを呼び出す
|
117 |
+
response = openai.ChatCompletion.create(
|
118 |
+
model=MODEL,
|
119 |
+
messages=messages,
|
120 |
+
functions=functions,
|
121 |
+
function_call={"name": "create_character"}
|
122 |
+
)
|
123 |
+
print("gpt generation time: "+str(time.time() - start))
|
124 |
+
|
125 |
+
# ChatCompletion APIから返された結果を取得する
|
126 |
+
message = response.choices[0].message
|
127 |
+
print("chat completion message: " + json.dumps(message, indent=2))
|
128 |
+
|
129 |
+
return message
|
130 |
+
|
131 |
+
class NajiminoAI:
|
132 |
+
|
133 |
+
def __init__(self, user_message):
|
134 |
+
self.user_message = user_message
|
135 |
+
|
136 |
+
def generate_recipe_prompt(self):
|
137 |
+
template = get_filetext(filename="template.md")
|
138 |
+
prompt = f"""
|
139 |
+
{self.user_message}
|
140 |
+
---
|
141 |
+
上記を元に、下記テンプレートを埋めてください。
|
142 |
+
---
|
143 |
+
{template}
|
144 |
+
"""
|
145 |
+
return prompt
|
146 |
+
|
147 |
+
def create_character(self, lang, title, description, prompt_for_visual_expression):
|
148 |
+
|
149 |
+
template = get_filetext(filename = "template.md")
|
150 |
+
debug_message = template.format(
|
151 |
+
lang=lang,
|
152 |
+
title=title,
|
153 |
+
description=description,
|
154 |
+
prompt_for_visual_expression=prompt_for_visual_expression
|
155 |
+
)
|
156 |
+
|
157 |
+
print("debug_message: "+debug_message)
|
158 |
+
|
159 |
+
return debug_message
|
160 |
+
|
161 |
+
@classmethod
|
162 |
+
def generate(cls, user_message):
|
163 |
+
|
164 |
+
najiminoai = NajiminoAI(user_message)
|
165 |
+
|
166 |
+
return najiminoai.generate_recipe()
|
167 |
+
|
168 |
+
def generate_recipe(self):
|
169 |
+
|
170 |
+
user_message = self.user_message
|
171 |
+
constraints = get_filetext(filename = "constraints.md")
|
172 |
+
|
173 |
+
messages = [
|
174 |
+
{"role": "system", "content": constraints}
|
175 |
+
,{"role": "user", "content": user_message}
|
176 |
+
]
|
177 |
+
|
178 |
+
functions = get_functions_from_schema('schema.json')
|
179 |
+
|
180 |
+
message = OpenAI.chat_completion_with_function(prompt=user_message, messages=messages, functions=functions)
|
181 |
+
|
182 |
+
image = None
|
183 |
+
html = None
|
184 |
+
if message.get("function_call"):
|
185 |
+
function_name = message["function_call"]["name"]
|
186 |
+
|
187 |
+
args = json.loads(message["function_call"]["arguments"])
|
188 |
+
|
189 |
+
lang=args.get("lang")
|
190 |
+
title=args.get("title")
|
191 |
+
description=args.get("description")
|
192 |
+
prompt_for_visual_expression_in_en=args.get("prompt_for_visual_expression_in_en")
|
193 |
+
|
194 |
+
prompt_for_visual_expression = \
|
195 |
+
prompt_for_visual_expression_in_en
|
196 |
+
|
197 |
+
print("prompt_for_visual_expression: "+prompt_for_visual_expression)
|
198 |
+
|
199 |
+
# 画像生成にかかる時間を計測する
|
200 |
+
start = time.time()
|
201 |
+
image = StabilityAI.generate_image(prompt_for_visual_expression)
|
202 |
+
print("image generation time: "+str(time.time() - start))
|
203 |
+
|
204 |
+
function_response = self.create_character(
|
205 |
+
lang=lang,
|
206 |
+
title=title,
|
207 |
+
description=description,
|
208 |
+
prompt_for_visual_expression=prompt_for_visual_expression
|
209 |
+
)
|
210 |
+
|
211 |
+
html = (
|
212 |
+
"<div style='max-width:100%; overflow:auto'>"
|
213 |
+
+ "<p>"
|
214 |
+
+ markdown2.markdown(function_response)
|
215 |
+
+ "</div>"
|
216 |
+
)
|
217 |
+
return [image, html]
|
218 |
+
|
219 |
+
def main():
|
220 |
+
# インプット例をクリックした時のコールバック関数
|
221 |
+
def click_example(example):
|
222 |
+
# クリックされたインプット例をテキストボックスに自動入力
|
223 |
+
inputs.value = example
|
224 |
+
time.sleep(0.1) # テキストボックスに文字が表示されるまで待機
|
225 |
+
# 自動入力後に実行ボタンをクリックして結果を表示
|
226 |
+
execute_button.click()
|
227 |
+
|
228 |
+
iface = gr.Interface(fn=NajiminoAI.generate,
|
229 |
+
examples=[
|
230 |
+
["丸顔で青い子どもに愛されるイルカのキャラクター"],
|
231 |
+
["活発で夏が似合う赤髪の女の子"],
|
232 |
+
["黒い鎧を着た魔王"],
|
233 |
+
],
|
234 |
+
inputs=gr.Textbox(label=inputs_label),
|
235 |
+
outputs=[
|
236 |
+
gr.Image(label="Visual Expression"),
|
237 |
+
"html"
|
238 |
+
],
|
239 |
+
title=title,
|
240 |
+
description=description,
|
241 |
+
article=article
|
242 |
+
)
|
243 |
+
|
244 |
+
iface.launch()
|
245 |
+
|
246 |
+
if __name__ == '__main__':
|
247 |
+
function = ''
|
248 |
+
if len(sys.argv) > 1:
|
249 |
+
function = sys.argv[1]
|
250 |
+
|
251 |
+
if function == 'generate':
|
252 |
+
NajiminoAI.generate("A brave knight with a mighty sword and strong armor")
|
253 |
+
|
254 |
+
elif function == 'generate_image':
|
255 |
+
image = StabilityAI.generate_image("Imagine a brave knight with a mighty sword and strong armor. He has a chiseled jawline and a confident expression on his face. His armor gleams under the sunlight, showing off its intricate design and craftsmanship. He holds his sword with pride, ready to protect his kingdom and its people at any cost.")
|
256 |
+
print("image: " + image)
|
257 |
+
|
258 |
+
if type(image) == PIL.PngImagePlugin.PngImageFile:
|
259 |
+
image.save("image.png")
|
260 |
+
|
261 |
+
else:
|
262 |
+
main()
|
constraints.md
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#constraints
|
2 |
+
|
3 |
+
ALOs(Character):
|
4 |
+
- Appearance: Design, Visualize, Imagine, Shape, Size, Colors, Clothes, Features, Accessories
|
5 |
+
- Personality: Develop, Describe, Traits, Temperaments, Dispositions, Behaviors, Attitudes, Emotions
|
6 |
+
- Backstory: Create, Origins, Universe, TimePeriod, History, Relationships, Motivations, Milestones
|
7 |
+
- Abilities: List, Powers, Skills, Talents, Strengths, Weaknesses, Limitations, CombatStyle, Development
|
8 |
+
- Occupation: Identify, Roles, Position, Functions, Responsibilities, Goals, Contributions, Teamwork
|
9 |
+
- Species: Invent, Classify, Describe, Hybridization, MythologicalCreatures, Animalia, Aliens, Humanoids
|
10 |
+
|
11 |
+
Execute ALO(Character) to generate novel, state of the art completely new character, description of the character, possible voice lines, visual representation of the character by words for generative AI that includes ideal composition of character image, according to user input character domains and characteristics. Generate details as far as you can by brainstorming to fulfill all parameters. Implement linguistic adjustments to prevent and rectify errors.
|
12 |
+
|
13 |
+
#templates
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
openai>=0.27.0
|
2 |
+
python-dotenv
|
3 |
+
stability-sdk
|
4 |
+
gradio
|
5 |
+
markdown2
|
schema.json
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"functions": [
|
3 |
+
{
|
4 |
+
"name": "create_character",
|
5 |
+
"description": "Execute ALO(Character) to generate a novel, state-of-the-art character based on user input character domains, personality traits, and background stories. This includes the creation of a new character, a brief description of their story, and a textual representation of the character for generative AI, including the photographic settings of a key image of the character. The goal is to generate extensive details through brainstorming to fulfill all parameters, while making language adjustments to prevent and resolve errors.",
|
6 |
+
"parameters": {
|
7 |
+
"type": "object",
|
8 |
+
"default": {},
|
9 |
+
"title": "The Schema for character domains, traits, and stories",
|
10 |
+
"required": [
|
11 |
+
"lang",
|
12 |
+
"title",
|
13 |
+
"description",
|
14 |
+
"prompt_for_visual_expression_in_en"
|
15 |
+
],
|
16 |
+
"properties": {
|
17 |
+
"lang": {
|
18 |
+
"type": "string",
|
19 |
+
"default": "ja",
|
20 |
+
"title": "The language schema",
|
21 |
+
"description": "The language of the user input in ISO 639-1 format.",
|
22 |
+
"examples": [ "ja" ]
|
23 |
+
},
|
24 |
+
"title": {
|
25 |
+
"type": "string",
|
26 |
+
"title": "Title of the character",
|
27 |
+
"description": "The title of the new character to be generated.",
|
28 |
+
"examples": [
|
29 |
+
"炎の戦士アキラ",
|
30 |
+
"平和の使者イチロウ"
|
31 |
+
]
|
32 |
+
},
|
33 |
+
"description": {
|
34 |
+
"type": "string",
|
35 |
+
"default": "",
|
36 |
+
"title": "Character description",
|
37 |
+
"description": "The detailed description of the new character, detailing their appearance, personality traits, background story and more.",
|
38 |
+
"examples": [
|
39 |
+
"アキラは剣を振るう炎の戦士です。彼の使命は邪悪な悪者たちを退治し、世界の平和を取り戻すことです。アキラの家族はかつて炎を操る能力を持っていたが、彼が生まれてから発揮していなかった。",
|
40 |
+
"イチロウは平和を愛し、戦争を憎む使者です。彼の持つ秘密の力により、対立している人々の心に平和の光を届け、誤解や争いを解決します。イチロウは昔の戦いで亡くなった友人の想いを背負って、平和を求めて旅を続けます。"
|
41 |
+
]
|
42 |
+
},
|
43 |
+
"prompt_for_visual_expression_in_en": {
|
44 |
+
"type": "string",
|
45 |
+
"title": "Prompt for visual expression in English",
|
46 |
+
"description": "Prompts for generating a visual representation of the character in English using AI image generation. The prompt should consist of no more than 20 words.",
|
47 |
+
"examples": [
|
48 |
+
"Akira, the warrior wielding a sword of fire and surrounded by flames, fighting against evil villains.",
|
49 |
+
"Ichiro, the messenger of peace with a gentle smile, holding a white dove representing harmony."
|
50 |
+
]
|
51 |
+
}
|
52 |
+
}
|
53 |
+
}
|
54 |
+
}
|
55 |
+
]
|
56 |
+
}
|
template.md
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# キャラクター名: {title}
|
2 |
+
|
3 |
+
{description}
|
4 |
+
|
5 |
+
## 画像生成プロンプト
|
6 |
+
|
7 |
+
{prompt_for_visual_expression}
|