File size: 5,151 Bytes
582aab9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Natural-language instruction templates for Flash-Instruct.
labels: dict(lang=<ibo|yor|hau|pcm|eng|cs:<l1>+<l2>>, rate=slow|normal|fast|None, pause=few|normal|many|None,
             energy=calm|neutral|lively|None, gender=male|female|None)
make(labels, rng) -> one instruction string (many surface forms per label combination).
DEFAULT = the original CosyVoice3 system prompt; ~18% of training items keep it.
"""
import random

DEFAULT = "You are a helpful assistant."
LN = {"ibo": "Igbo", "yor": "Yoruba", "hau": "Hausa", "pcm": "Nigerian Pidgin", "eng": "Nigerian English"}

RATE = {
    "slow": ["slowly", "at an unhurried pace", "at a slow, relaxed pace", "taking your time", "at a gentle, slow pace",
             "a little slower than usual", "slowly and deliberately"],
    "normal": ["at a natural pace", "at a normal speaking pace", "at a steady, everyday pace", "at a comfortable pace"],
    "fast": ["quickly", "at a brisk pace", "fast, like quick everyday conversation", "at a quick pace",
             "a little faster than usual", "briskly"],
}
PAUSE = {
    "few": ["with few pauses", "in one smooth flow with hardly any pauses", "without stopping much",
            "with minimal pausing", "running the phrases together"],
    "normal": ["with natural pauses", "with normal phrasing", "pausing where it feels natural"],
    "many": ["with plenty of pauses", "pausing often between phrases", "with frequent pauses",
             "with lots of breaks between phrases", "with deliberate pauses"],
}
ENERGY = {
    "calm": ["calm", "soft and calm", "gentle, even-toned", "relaxed and low-key", "quiet and steady"],
    "neutral": ["neutral", "plain, matter-of-fact", "even", "straightforward"],
    "lively": ["lively", "animated", "expressive and energetic", "bright and lively", "upbeat, expressive"],
}
GENDER = {"male": ["male", "man's"], "female": ["female", "woman's"]}


def art(w):
    return ("an " if w[:1].lower() in "aeiou" else "a ") + w


def lang_phrase(lang, rng):
    if lang.startswith("cs:"):
        a, b = lang[3:].split("+")
        A, B = LN.get(a, a), LN.get(b, b).replace("Nigerian English", "English")
        return rng.choice([f"an {A}-{B} mix" if A[0] in "AEIOU" else f"a {A}-{B} mix", f"mixed {A} and {B}",
                           f"{A} with some {B} mixed in", f"code-switched {A} and {B}"])
    return LN.get(lang, lang)


def make(lab, rng=random):
    parts = {}
    if lab.get("rate"):
        parts["rate"] = rng.choice(RATE[lab["rate"]])
    if lab.get("pause"):
        parts["pause"] = rng.choice(PAUSE[lab["pause"]])
    if lab.get("energy"):
        parts["energy"] = rng.choice(ENERGY[lab["energy"]])
    lang = lang_phrase(lab["lang"], rng) if lab.get("lang") else None
    g = rng.choice(GENDER[lab["gender"]]) if lab.get("gender") else None
    tone = parts.get("energy")
    adv = [parts[k] for k in ("rate", "pause") if k in parts]
    advs = ", ".join(adv)
    T = []
    # template family 1: imperative sentence
    s = "Speak"
    if lang:
        s += f" in {lang}" + (f", sounding {tone}," if tone else "")
    elif tone:
        s += f" in {art(tone)} tone"
    if advs:
        s += f" {advs}"
    T.append(s + ".")
    # family 2: read-this style
    s = "Read this"
    if advs:
        s += f" {advs}"
    if tone:
        s += f", in {art(tone)} voice"
    if lang:
        s += f". The language is {lang}"
    T.append(s + ".")
    # family 3: descriptive/caption style
    d = []
    if g:
        d.append(f"A {g} voice")
    else:
        d.append("A speaker")
    if lang:
        d.append(f"speaking {lang}")
    s = " ".join(d)
    if advs:
        s += f", {advs}"
    if tone:
        s += f"; the delivery is {tone}" if (lang or advs) else f" with {art(tone)} delivery"
    T.append(s + ".")
    # family 4: tag list
    tags = []
    if lang: tags.append(f"language: {lang}")
    if "rate" in parts: tags.append(f"pace: {lab['rate']}")
    if "pause" in parts: tags.append(f"pauses: {lab['pause']}")
    if tone: tags.append(f"tone: {lab['energy']}")
    if g: tags.append(f"voice: {lab['gender']}")
    if tags:
        T.append("Style - " + "; ".join(tags) + ".")
    # family 5: polite request
    s = "Please say this"
    if lang:
        s += f" in {lang}"
    if tone:
        s += f" with {art(tone)} delivery"
    if advs:
        s += f", {advs}"
    T.append(s + ".")
    out = rng.choice(T)
    return out[0].upper() + out[1:]


def sample_labels(full, rng, p=None):
    """drop each control independently so instructions mention subsets; keep at least one."""
    p = p or dict(lang=0.55, rate=0.75, pause=0.7, energy=0.6, gender=0.3)
    while True:
        lab = {k: (v if (v and rng.random() < p.get(k, 0.5)) else None) for k, v in full.items()}
        if any(lab.values()):
            return lab


if __name__ == "__main__":
    r = random.Random(0)
    full = dict(lang="cs:ibo+eng", rate="slow", pause="many", energy="calm", gender="female")
    for _ in range(12):
        print(make(sample_labels(full, r), r))
    for l in ["ibo", "yor", "hau", "pcm", "eng"]:
        print(make(dict(lang=l, rate="fast", pause="few", energy="lively"), r))