Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exemplar Selection (in context learning) API #1055

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion flaml/autogen/oai/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from flaml.autogen.oai.completion import Completion, ChatCompletion
from flaml.autogen.oai.openai_utils import get_config_list, config_list_gpt4_gpt35, config_list_openai_aoai
from flaml.autogen.oai.exemplar_selector import ExemplarSelector

__all__ = ["Completion", "ChatCompletion", "get_config_list", "config_list_gpt4_gpt35", "config_list_openai_aoai"]
__all__ = ["Completion", "ChatCompletion", "get_config_list", "config_list_gpt4_gpt35", "config_list_openai_aoai", "ExemplarSelector"]
55 changes: 55 additions & 0 deletions flaml/autogen/oai/exemplar_selector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from functools import partial
import random
import numpy as np
from flaml.autogen.oai.selection_methods import RandomSelect

class ExemplarSelector:
METHOD_MAPPING = {
"random": RandomSelect,
# You can add more methods here...
}

@classmethod
def get_few_shot_template(cls, train_data, method=None, few_shot_template=None, method_params=None, template_params=None):
Copy link
Collaborator

@LittleLittleCloud LittleLittleCloud May 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing selection method into exemplar_selector, maybe it would be easier to implement exemplar_selector with different methods?

BTW I'm not too familiar with pythonic-way of abstract class so I'm just make up pattern here.

abstract class ExemplarSelector:
   def construct_template(context) -> str;
      pass

# random_exemplar_selector
class RandomExemplarSelector(ExemplarSelector):
    def __init__(self, train_data, k):
        # initialize

    def construct_template(context):
        # select `k` examples from train_data and render template. 

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I add the abstract class to exemplar_selector.py

if isinstance(method, str):
method_class = cls.METHOD_MAPPING.get(method, None)
if method_class is not None:
method = method_class(train_data, **method_params).select
else:
raise ValueError(f"The specified method '{method}' is not recognized.")
return partial(cls.construct_template, train_data=train_data, method=method,
few_shot_template=few_shot_template, method_params=method_params or {},
template_params=template_params or {})

@staticmethod
def construct_template(context, train_data, method=None, few_shot_template=None, method_params=None, template_params=None):

if method is None:
k = method_params.get('k', np.inf)
exemplars = train_data[:k] if len(train_data) >= k else train_data
else:
exemplars = method(context)

if few_shot_template is not None:
return few_shot_template(context, exemplars=exemplars)
else:
key_order = template_params.get('key_order', None)
return ExemplarSelector.default_template(context, exemplars, key_order)

@staticmethod
def default_template(context, exemplars, key_order):
few_shot_prompt = ""
for examplar in exemplars:
few_shot_prompt += "\n".join(
[
key + ": " + str(examplar[key]) for key in key_order
]
) + "\n"
few_shot_prompt += "\n".join(
[
key + ": " + str(context[key]) for key in key_order[:-1]
]
)
few_shot_prompt += "\n" + key_order[-1] + ": " + "\n"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe use format string here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any benefits to use format string?

return few_shot_prompt

13 changes: 13 additions & 0 deletions flaml/autogen/oai/selection_methods.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import random
class RandomSelect:
def __init__(self, data, k=None):
self.data = data
self.k = k
# You can also add code to learn parameters here.

def select(self, context):
data_without_context = [item for item in self.data if item != context]
if self.k is None:
return data_without_context
else:
return random.sample(data_without_context, self.k)