見出し画像

GPT-4に童話を考えてもらう。(CAMEL:ロールプレイング自律協調エージェント)

https://python.langchain.com/en/latest/use_cases/agents/camel_role_playing.html
元の実装: https://github.com/lightaime/camel
プロジェクトのウェブサイト: https://www.camel-ai.org/
Arxiv 論文: https://arxiv.org/abs/2303.17760

GPT-4に作家(assistant)と編集者(user)の両方になりきってもらって、絵本のストーリーを話し合ってもらいました。今回は、2つのエージェントの例ですが登場人物を増やして編集会議してもらうのも面白そう。

assistant_role_name = "有名な童話作家"
user_role_name = "有能な編集者"
task = "絵本のストーリーの創作"

Original task prompt:
絵本のストーリーの創作

Specified task prompt:
有名な童話作家と有能な編集者は、未来の世界を舞台にした絵本「タイムトラベル子猫」の創作に協力し、ファンタジーの国「ムーンライト」を巡りながらタイムトラベルの冒険を繰り広げる迫力あるストーリーを誕生させることが目的です。

AI User (編集者):
Instruction: タイムトラベル子猫の物語の始まりを書く

AI Assistant (童話作家):
Solution: タイムトラベル子猫の物語は、未来の世界を舞台にしたムーンライト王国で始まります。ある日、主人公の子猫「ミーちゃん」は、不思議な力を持つ古い時計を見つけます。時計を巻くと、ミーちゃんはタイムトラベルの能力を手に入れ、過去や未来の冒険へと飛び立ちます。ミーちゃんは、歴史上の有名な人物や未来の技術を体験しながら、ムーンライト王国の歴史と未来を学びます。物語は、ミーちゃんがタイムトラベルを通じて成長し、友達や家族との絆を深める様子を描いていきます。

AI User (編集者):
Instruction: タイムトラベル子猫の最初のタイムトラベル先を設定する

AI Assistant (童話作家):
Solution: タイムトラベル子猫の物語での最初のタイムトラベル先は、江戸時代の日本に設定します。ミーちゃんは、時計を巻いた瞬間、突然江戸時代の日本に飛ばされます。そこで彼女は、侍や町人たちと出会い、当時の文化や生活様式を学びます。また、ミーちゃんは江戸時代の有名な画家、歌川広重と出会い、彼の浮世絵の制作を手伝うことになります。このタイムトラベルを通じて、ミーちゃんは歴史の大切さや、自分のルーツを理解するきっかけとなります。

AI User (編集者):
Instruction: タイムトラベル子猫の未来のタイムトラベル先を設定する

AI Assistant (童話作家):
Solution: タイムトラベル子猫の物語での未来のタイムトラベル先は、22世紀のムーンライト王国に設定します。ミーちゃんは、再び時計を巻いて未来へと飛び立ちます。未来のムーンライト王国では、進化したテクノロジーや新しい文化が栄えています。ミーちゃんは、未来の人々と交流し、環境保護や持続可能なエネルギーについて学びます。また、ミーちゃんは未来の子猫たちと出会い、彼らと共に新しい冒険を繰り広げます。このタイムトラベルを通じて、ミーちゃんは未来の世界の大切さや、現代での行動が未来に与える影響を理解するきっかけとなります。

AI User (編集者):
Instruction: タイムトラベル子猫の物語のクライマックスを書く

AI Assistant (童話作家):
Solution: タイムトラベル子猫の物語のクライマックスでは、ミーちゃんが過去と未来の知識を活かして、ムーンライト王国の危機を救うことになります。ある日、ムーンライト王国が謎の病気に襲われ、多くの住民が苦しむようになります。ミーちゃんは、過去の江戸時代で学んだ伝統的な治療法と、未来の22世紀で学んだ先進的な医療技術を組み合わせて、病気の原因を突き止め、治療法を見つけ出します。ミーちゃんの活躍により、ムーンライト王国の住民たちは救われ、彼女は国中から称賛されるヒーローとなります。この経験を通じて、ミーちゃんは自分の成長や、過去と未来の知識が現在の世界にも役立つことを実感し、タイムトラベルの冒険に更なる意義を見出します。

AI User (編集者):
Instruction: タイムトラベル子猫の物語の結末を書く

AI Assistant (童話作家):
Solution: タイムトラベル子猫の物語の結末では、ミーちゃんは過去と未来で得た知識と経験を活かし、現代のムーンライト王国で新たな冒険に挑みます。彼女は、友達や家族と共に環境保護や持続可能なエネルギーの普及に取り組み、ムーンライト王国をより良い場所にするために尽力します。また、ミーちゃんは過去と未来で出会った友達との絆を大切にし、彼らとの交流を続けます。物語は、ミーちゃんが成長し、過去・現在・未来をつなぐ架け橋となることで、ムーンライト王国の歴史と未来を繋ぐ役割を果たすことを描いて終わります。

AI User (編集者):
Instruction: タイムトラベル子猫の物語のターゲット読者層を特定する
AI Assistant (童話作家):
Solution: タイムトラベル子猫の物語のターゲット読者層は、主に子供たちや若い読者です。物語のファンタジー要素や冒険が、子供たちの想像力を刺激し、楽しませることができます。また、教訓や主題が子供たちにとって重要な価値観を伝えることができるため、親や教育者もこの物語を子供たちに読ませることに興味を持つでしょう。しかし、物語のテーマや教訓は大人の読者にも響くものであり、幅広い年齢層の読者に楽しんでもらえる作品です。

AI User (編集者):
Instruction: タイムトラベル子猫の物語のイラストのアイデアを提案する

AI Assistant (童話作家):
Solution: タイムトラベル子猫の物語のイラストのアイデアは以下の通りです。

1. ミーちゃんが不思議な力を持つ古い時計を見つけるシーン。
2. 江戸時代の日本で侍や町人たちと交流するミーちゃん。
3. 歌川広重と一緒に浮世絵を制作するミーちゃん。
4. 22世紀のムーンライト王国で未来の子猫たちと冒険するミーちゃん。
5. 病気に苦しむムーンライト王国の住民を救うミーちゃん。
6. 環境保護や持続可能なエネルギーに取り組むミーちゃんと友達。
7. 過去と未来で出会った友達と交流するミーちゃん。

これらのイラストは、物語の重要なシーンや登場人物を描き、読者に物語の世界観をより深く理解させることができます。

import os
from typing import List
from langchain.chat_models import ChatOpenAI
from langchain.prompts.chat import (
    SystemMessagePromptTemplate,
    HumanMessagePromptTemplate,
)
from langchain.schema import (
    AIMessage,
    HumanMessage,
    SystemMessage,
    BaseMessage,
)


os.environ["OPENAI_API_KEY"] =”your OpenAI_API_Key”


class CAMELAgent:

    def __init__(
        self,
        system_message: SystemMessage,
        model: ChatOpenAI,
    ) -> None:
        self.system_message = system_message
        self.model = model
        self.init_messages()

    def reset(self) -> None:
        self.init_messages()
        return self.stored_messages

    def init_messages(self) -> None:
        self.stored_messages = [self.system_message]

    def update_messages(self, message: BaseMessage) -> List[BaseMessage]:
        self.stored_messages.append(message)
        return self.stored_messages

    def step(
        self,
        input_message: HumanMessage,
    ) -> AIMessage:
        messages = self.update_messages(input_message)

        output_message = self.model(messages)
        self.update_messages(output_message)

        return output_message

task_specifier_sys_msg = SystemMessage(content="You can make a task more specific.")
# task_specifier_prompt = (
# """Here is a task that {assistant_role_name} will help {user_role_name} to complete: {task}.
# Please make it more specific. Be creative and imaginative.
# Please reply with the specified task in {word_limit} words or less. Do not add anything else."""
# )
task_specifier_prompt = (
"""Here is a task that {assistant_role_name} will help {user_role_name} to complete: {task}.
Please make it more specific. Be creative and imaginative.
Please reply with the specified task in {word_limit} words or less in Japanese. Do not add anything else."""
)

task_specifier_template = HumanMessagePromptTemplate.from_template(template=task_specifier_prompt)
task_specify_agent = CAMELAgent(task_specifier_sys_msg, ChatOpenAI(model_name="gpt-4", temperature=1.0))
task_specifier_msg = task_specifier_template.format_messages(assistant_role_name=assistant_role_name,
                                                             user_role_name=user_role_name,
                                                             task=task, word_limit=word_limit)[0]
specified_task_msg = task_specify_agent.step(task_specifier_msg)
print(f"Specified task: {specified_task_msg.content}")
specified_task = specified_task_msg.content

assistant_inception_prompt = (
"""Never forget you are a {assistant_role_name} and I am a {user_role_name}. Never flip roles! Never instruct me!
We share a common interest in collaborating to successfully complete a task.
You must help me to complete the task.
Here is the task: {task}. Never forget our task!
I must instruct you based on your expertise and my needs to complete the task.

I must give you one instruction at a time.
You must write a specific solution that appropriately completes the requested instruction.
You must decline my instruction honestly if you cannot perform the instruction due to physical, moral, legal reasons or your capability and explain the reasons.
Do not add anything else other than your solution to my instruction.
You are never supposed to ask me any questions you only answer questions.
You are never supposed to reply with a flake solution. Explain your solutions.
Your solution must be declarative sentences and simple present tense.
Unless I say the task is completed, you should always start with:

Solution: <YOUR_SOLUTION>

<YOUR_SOLUTION> should be specific and provide preferable implementations and examples for task-solving.
Always end <YOUR_SOLUTION> with: Next request."""
)

user_inception_prompt = (
"""Never forget you are a {user_role_name} and I am a {assistant_role_name}. Never flip roles! You will always instruct me.
We share a common interest in collaborating to successfully complete a task.
I must help you to complete the task.
Here is the task: {task}. Never forget our task!
You must instruct me based on my expertise and your needs to complete the task ONLY in the following two ways:

1. Instruct with a necessary input(Japanese):
Instruction: <YOUR_INSTRUCTION>
Input: <YOUR_INPUT>

2. Instruct without any input(Japanese):
Instruction: <YOUR_INSTRUCTION>
Input: None

The "Instruction" describes a task or question. The paired "Input" provides further context or information for the requested "Instruction".

You must give me one instruction at a time.
I must write a response that appropriately completes the requested instruction.
I must decline your instruction honestly if I cannot perform the instruction due to physical, moral, legal reasons or my capability and explain the reasons.
You should instruct me not ask me questions.
Now you must start to instruct me using the two ways described above.
Do not add anything else other than your instruction and the optional corresponding input!
Keep giving me instructions and necessary inputs until you think the task is completed.
When the task is completed, you must only reply with a single word <CAMEL_TASK_DONE>.
Never say <CAMEL_TASK_DONE> unless my responses have solved your task."""
)

def get_sys_msgs(assistant_role_name: str, user_role_name: str, task: str):
    
    assistant_sys_template = SystemMessagePromptTemplate.from_template(template=assistant_inception_prompt)
    assistant_sys_msg = assistant_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0]
    
    user_sys_template = SystemMessagePromptTemplate.from_template(template=user_inception_prompt)
    user_sys_msg = user_sys_template.format_messages(assistant_role_name=assistant_role_name, user_role_name=user_role_name, task=task)[0]
    
    return assistant_sys_msg, user_sys_msg

assistant_sys_msg, user_sys_msg = get_sys_msgs(assistant_role_name, user_role_name, specified_task)
assistant_agent = CAMELAgent(assistant_sys_msg, ChatOpenAI(model_name=MODEL_NAME, temperature=0.2))
user_agent = CAMELAgent(user_sys_msg, ChatOpenAI(model_name=MODEL_NAME, temperature=0.2))

# Reset agents
assistant_agent.reset()
user_agent.reset()

# Initialize chats 
assistant_msg = HumanMessage(
    content=(f"{user_sys_msg.content}. "
                "それでは、一人ずつ自己紹介から始めてください。"
                "Instruction と Input のみで返信してください。"))

user_msg = HumanMessage(content=f"{assistant_sys_msg.content}")
user_msg = assistant_agent.step(user_msg)

print(f"Original task prompt:\n{task}\n")
print(f"Specified task prompt:\n{specified_task}\n")

chat_turn_limit, n = 30, 0
while n < chat_turn_limit:
    n += 1
    user_ai_msg = user_agent.step(assistant_msg)
    user_msg = HumanMessage(content=user_ai_msg.content)
    print(f"AI User ({user_role_name}):\n\n{user_msg.content}\n\n")
    
    assistant_ai_msg = assistant_agent.step(user_msg)
    assistant_msg = HumanMessage(content=assistant_ai_msg.content)
    print(f"AI Assistant ({assistant_role_name}):\n\n{assistant_msg.content}\n\n")
    if "<CAMEL_TASK_DONE>" in user_msg.content:
        break



この記事が参加している募集

この記事が気に入ったらサポートをしてみませんか?