samplers.py 3.85 KB
Newer Older
1
class Sampler:
2
3
4
5
6
7
8
9
    def __init__(self, docs, task, fewshot_indices=None, rnd=None):

        self.rnd = rnd
        assert self.rnd, "must pass rnd to FewShotSampler!"

        self.task = task
        self.config = task._config

Lintang Sutawika's avatar
Lintang Sutawika committed
10
11
        self.target_delimiter = self.config.target_delimiter
        self.fewshot_delimiter = self.config.fewshot_delimiter
12

13
14
15
16
        self.doc_to_text = self.task.doc_to_text
        self.doc_to_target = self.task.doc_to_target
        self.doc_to_choice = self.task.doc_to_choice

lintangsutawika's avatar
lintangsutawika committed
17
18
        self.docs = docs  # HF dataset split, provided by task._fewshot_docs()
        if fewshot_indices:  # subset few-shot docs from
19
20
21
22
            self.docs = self.docs.select(fewshot_indices)

    def get_context(self, doc, num_fewshot):

lintangsutawika's avatar
lintangsutawika committed
23
24
25
26
27
28
        # draw an extra fewshot sample if using same split as evaluating on
        n_samples = (
            num_fewshot + 1
            if self.config.fewshot_split == self.config.test_split
            else num_fewshot
        )
29

30
        # draw `n_samples` docs from fewshot_docs
31
32
33
        fewshotex = self.sample(n_samples)

        # get rid of the doc that's the one we're evaluating, if it's in the fewshot
34
        # TODO: should we just stop people from using fewshot from same split as evaluating?
35
        selected_docs = [x for x in fewshotex if x != doc][:num_fewshot]
lintangsutawika's avatar
lintangsutawika committed
36

37
        labeled_examples = (
38
            self.fewshot_delimiter.join(
lintangsutawika's avatar
lintangsutawika committed
39
                [
40
                    # TODO: is separating doc_to_text and doc_to_target by one space always desired?
41
42
43
44
45
46
47
48
                    (
                        self.doc_to_text(doc)
                        if (
                            self.config.doc_to_choice is None
                            or type(self.doc_to_text(doc)) is str
                        )
                        else self.doc_to_choice(doc)[self.doc_to_text(doc)]
                    )
49
                    + self.target_delimiter
50
51
                    + (
                        self.doc_to_target(doc)
52
53
54
55
                        if (
                            self.config.doc_to_choice is None
                            or type(self.doc_to_target(doc)) is str
                        )
56
57
                        else self.doc_to_choice(doc)[self.doc_to_target(doc)]
                    )
lintangsutawika's avatar
lintangsutawika committed
58
59
                    for doc in selected_docs
                ]
60
            )
Hailey Schoelkopf's avatar
Hailey Schoelkopf committed
61
            + self.fewshot_delimiter
lintangsutawika's avatar
lintangsutawika committed
62
        )
63
64
65
66
67
68
69
70
71
72
73
74
75
76

        return labeled_examples

    def sample(self, n):
        """
        Draw `n` samples from our fewshot docs. This method should be overridden by subclasses.
        """

        return self.rnd.sample(self.docs, n)


class BalancedSampler(Sampler):
    def sample(self, n):
        """
lintangsutawika's avatar
lintangsutawika committed
77
        TODO: this should return approximately class-balanced samples from our fewshot examples.
78
        TODO: what order should they be in? maybe random?
79
80
81
82
83
        """

        pass


lintangsutawika's avatar
lintangsutawika committed
84
class ManualSampler(Sampler):
85
    def sample(self, n):
lintangsutawika's avatar
lintangsutawika committed
86
87
        """ """
        pass
88
89


lintangsutawika's avatar
lintangsutawika committed
90
# TODO: how should we do design here? might be better to have a single sampler and pass more kwargs at init.
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# Depends what's easier for new user to add own functionality on top of

# types of sampler:
# - class-balanced, randomly shuffled
# - class-balanced, one particular set of fewshot examples for all evaled instances
# - hand-specify number of fewshot examples per class?
# - random, varies per example (check that this is curr. default in old repo)
# - random, unified per example
# - enforce a specific fixed fewshot string! (or should we not use this, in favor of including it in prompt template directly)


# - user-specified doc indices to restrict fewshot doc options to
# - user specifies split to use for drawing fewshot instances (TODO: manually prevent this from being same split you eval!)
# - user specifies a prepended "description"/string to add in front of the (prompted) input

# - user specifies a location to draw fewshot samples from? DO THIS IN TASK CLASS