File size: 3,362 Bytes
b092c58
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from dataclasses import dataclass, asdict
import json
import os

from langchain.chat_models import ChatOpenAI
from langchain import PromptTemplate, LLMChain

from data_driven_characters.chains import FitCharLimit, define_description_chain

from data_driven_characters.constants import VERBOSE
from data_driven_characters.utils import (
    order_of_magnitude,
    apply_file_naming_convention,
)


@dataclass
class Character:
    name: str
    short_description: str
    long_description: str
    greeting: str


def generate_character_ai_description(name, corpus_summaries, char_limit):
    """Generate a character description with a certain number of characters."""
    lower_limit = char_limit - 10 ** (order_of_magnitude(char_limit))

    description_chain = define_description_chain()
    GPT4 = ChatOpenAI(model_name="gpt-3.5-turbo")
    char_limit_chain = FitCharLimit(
        chain=description_chain,
        character_range=(lower_limit, char_limit),
        llm=GPT4,
        verbose=VERBOSE,
    )
    description = char_limit_chain.run(
        corpus_summaries="\n\n".join(corpus_summaries),
        description=f"{lower_limit}-character description",  # specify a fewer characters than the limit
        name=name,
    )
    return description


def generate_greeting(name, short_description, long_description):
    """Generate a greeting for a character."""
    greeting_template = """Here are a short and long description for a character named {name}:

Short description:
---
{short_description}
---

Long description:
---
{long_description}
---

Generate a greeting that {name} would say to someone they just met, without quotations.
This greeting should reflect their personality.
"""
    GPT3 = ChatOpenAI(model_name="gpt-3.5-turbo")
    greeting = LLMChain(
        llm=GPT3, prompt=PromptTemplate.from_template(greeting_template)
    ).run(
        name=name,
        short_description=short_description,
        long_description=long_description,
    )
    # strip quotations
    greeting = greeting.replace('"', "")
    return greeting


def generate_character_definition(name, corpus_summaries):
    """Generate a Character.ai definition."""
    short_description = generate_character_ai_description(
        name=name, corpus_summaries=corpus_summaries, char_limit=50
    )
    long_description = generate_character_ai_description(
        name=name, corpus_summaries=corpus_summaries, char_limit=500
    )
    greeting = generate_greeting(name, short_description, long_description)

    # populate the dataclass
    character_definition = Character(
        name=name,
        short_description=short_description,
        long_description=long_description,
        greeting=greeting,
    )
    return character_definition


def get_character_definition(name, corpus_summaries, cache_dir, force_refresh=False):
    """Get a Character.ai definition from a cache or generate it."""
    cache_path = f"{cache_dir}/{apply_file_naming_convention(name)}.json"

    if not os.path.exists(cache_path) or force_refresh:
        character_definition = generate_character_definition(name, corpus_summaries)
        with open(cache_path, "w") as f:
            json.dump(asdict(character_definition), f)
    else:
        with open(cache_path, "r") as f:
            character_definition = Character(**json.load(f))
    return character_definition