flexeval 0.18.0__tar.gz → 0.18.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flexeval-0.18.0 → flexeval-0.18.1}/PKG-INFO +3 -1
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/__init__.py +1 -0
- flexeval-0.18.1/flexeval/core/chat_dataset/image_preprocessors.py +141 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/template_based.py +15 -4
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/vllm_serve_lm.py +21 -4
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/llm_label.py +18 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/llm_score.py +19 -1
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_model/pairwise_judge_reward_model.py +30 -14
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/__init__.py +1 -0
- flexeval-0.18.1/flexeval/core/string_processor/last_choice.py +81 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/utils/jinja2_utils.py +13 -0
- flexeval-0.18.1/flexeval/preset_configs/EvalSetup/en_vision/mmmu.jsonnet +100 -0
- flexeval-0.18.1/flexeval/preset_configs/EvalSetup/ja_chat/jamcqa_chat.jsonnet +56 -0
- flexeval-0.18.1/flexeval/preset_configs/EvalSetup/ja_vision/heron_bench.jsonnet +66 -0
- flexeval-0.18.1/flexeval/preset_configs/EvalSetup/ja_vision/jmmmu.jsonnet +102 -0
- flexeval-0.18.1/flexeval/preset_configs/Metric/heron_bench_judge.jsonnet +52 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/pyproject.toml +4 -2
- {flexeval-0.18.0 → flexeval-0.18.1}/LICENSE +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/README.md +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/README.md +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/mt-en-ref-gpt4.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/mt-en.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/mt-ja-ref-gpt4.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/mt-ja-ref-gpt4o-with-human-annotation.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/mt-ja.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/rakuda-v2-ja.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/vicuna-en-ref-gpt4.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/vicuna-en.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/vicuna-ja-ref-gpt4.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/chatbot_bench_datasets/vicuna-ja.jsonl +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/openai_messages.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/chat_dataset/sacrebleu_dataset.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/eval_setups.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/evaluate_chat_response.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/evaluate_from_data.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/evaluate_generation.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/evaluate_multiple_choice.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/evaluate_pairwise.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/evaluate_perplexity.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/evaluate_reward_model.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/few_shot_generator/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/few_shot_generator/balanced.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/few_shot_generator/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/few_shot_generator/fixed.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/few_shot_generator/rand.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/generation_dataset/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/generation_dataset/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/generation_dataset/sacrebleu_dataset.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/generation_dataset/template_based.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/hf_lm.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/litellm_api.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/openai_api.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/openai_batch_api.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/language_model/vllm_model.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/bleu.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/char_f1.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/code_eval.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/common_prefix_length.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/common_string_length.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/correlation.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/exact_match.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/finish_reason.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/llm_geval_score.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/math.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/output_length_stats.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/perspective_api.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/repetition_count.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/repetition_n.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/rouge.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/sari.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/substring_match.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/tool_call.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/utils.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/metric/xer.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/multiple_choice_dataset/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/multiple_choice_dataset/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/multiple_choice_dataset/template_based.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/judge/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/judge/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/judge/llm_judge.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/match.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/match_maker/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/match_maker/all_combinations.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/match_maker/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/match_maker/random_combinations.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/scorer/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/scorer/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/scorer/bradley_terry.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/pairwise_comparison/scorer/win_rate.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/prompt_template/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/prompt_template/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/prompt_template/jinja2.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reasoning_parser/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reasoning_parser/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reasoning_parser/regex_reasoning_parser.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/result_recorder/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/result_recorder/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/result_recorder/local_recorder.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/result_recorder/wandb_recorder.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_bench_dataset/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_bench_dataset/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_bench_dataset/template_based.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_model/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_model/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_model/log_prob.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_model/sequence_classification.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/aio.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/last_line.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/lower.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/mgsm.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/nfkc.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/regex.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/string_strip.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/string_processor/template.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/text_dataset/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/text_dataset/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/text_dataset/hf.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/text_dataset/jsonl.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tokenizer/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tokenizer/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tokenizer/mecab.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tokenizer/sacrebleu_tokenizer.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tokenizer/tiktoken_tokenizer.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tokenizer/transformers_tokenizer.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tokenizer/whitespace.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tool_parser/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/tool_parser/base.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/utils/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/utils/chat_util.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/utils/data_util.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/utils/json_util.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/code_chat/mbpp_chat.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/code_generation/jhumaneval.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/code_generation/jhumaneval_tab_indent.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/code_generation/mbpp.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/code_generation/mbpp_tab_indent.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/code_generation/openai_humaneval.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/code_generation/openai_humaneval_tab_indent.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_chat/mt-en.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_chat/vicuna-en.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_generation/babi.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_generation/commonsense_qa.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_generation/gsm8k.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_generation/squad_v1.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_generation/trivia_qa.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_generation/twitter_sentiment.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_multiple_choice/arc_challenge.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_multiple_choice/arc_easy.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_multiple_choice/commonsense_qa_mc.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_multiple_choice/hellaswag.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_multiple_choice/openbookqa.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_multiple_choice/piqa.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_multiple_choice/xwinograd_en.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/en_perplexity/tiny_shakespeare.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_chat/aio_chat.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_chat/elyza_tasks_100.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_chat/mgsm_ja_chat.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_chat/mt-ja.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_chat/rakuda-v2-ja.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_chat/vicuna-ja.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/aio.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/jamcqa.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/jcommonsenseqa.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/jnli.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/jsquad.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/mgsm_ja.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/wrime_pos_neg.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_generation/xlsum_ja.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_multiple_choice/jcommonsenseqa_mc.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/ja_multiple_choice/xwinograd_ja.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/translation/wmt20_en_ja.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/translation/wmt20_ja_en.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/translation_chat/wmt20_en_ja_chat.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/EvalSetup/translation_chat/wmt20_ja_en_chat.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/Metric/assistant_eval_en_single_turn.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/Metric/assistant_eval_ja_single_turn.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/Metric/elyza_tasks_100_eval.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/PairwiseJudge/assistant_judge_en_single_turn.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/preset_configs/PairwiseJudge/assistant_judge_ja_single_turn.jsonnet +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/scripts/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/scripts/common.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/scripts/flexeval_file.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/scripts/flexeval_lm.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/scripts/flexeval_pairwise.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/scripts/flexeval_presets.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/scripts/flexeval_reward.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/utils/__init__.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/utils/hf_utils.py +0 -0
- {flexeval-0.18.0 → flexeval-0.18.1}/flexeval/utils/module_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flexeval
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.1
|
|
4
4
|
Summary:
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Author: ryokan-ri
|
|
@@ -24,6 +24,7 @@ Requires-Dist: loguru (>=0.7.2,<0.8.0)
|
|
|
24
24
|
Requires-Dist: math-verify[antlr4-13-2] (>=0.7.0,<0.8.0)
|
|
25
25
|
Requires-Dist: openai (>=2.0.0,<3.0.0)
|
|
26
26
|
Requires-Dist: peft (>=0.19.1,<0.20.0)
|
|
27
|
+
Requires-Dist: pillow (>=11.0.0,<12.0.0)
|
|
27
28
|
Requires-Dist: pyarrow (==16.1.0)
|
|
28
29
|
Requires-Dist: python-levenshtein (>=0.23.0,<0.24.0)
|
|
29
30
|
Requires-Dist: rouge (>=1.0.1,<2.0.0)
|
|
@@ -34,6 +35,7 @@ Requires-Dist: smart-open (>=7.1.0,<8.0.0)
|
|
|
34
35
|
Requires-Dist: sudachipy (>=0.6.10)
|
|
35
36
|
Requires-Dist: tiktoken (>=0.9.0,<0.10.0)
|
|
36
37
|
Requires-Dist: transformers[ja,sentencepiece,torch] (>=5.5.3,<6)
|
|
38
|
+
Requires-Dist: uv (>=0.12.14,<0.13.0) ; extra == "vllm"
|
|
37
39
|
Requires-Dist: vllm (==0.24.0) ; extra == "vllm"
|
|
38
40
|
Requires-Dist: wandb (>=0.17.2,<0.18.0) ; extra == "wandb"
|
|
39
41
|
Description-Content-Type: text/markdown
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from .base import ChatDataset, ChatInstance
|
|
2
2
|
from .chatbot_bench import ChatbotBench
|
|
3
|
+
from .image_preprocessors import ConvertImageListToBase64, ConvertImageToBase64, EnsureMinSize
|
|
3
4
|
from .openai_messages import OpenAIMessagesDataset
|
|
4
5
|
from .sacrebleu_dataset import SacreBleuChatDataset
|
|
5
6
|
from .template_based import HFChatDataset, JsonlChatDataset, Preprocessor, TemplateChatDataset, load_jinja2_template
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import base64
|
|
4
|
+
import dataclasses
|
|
5
|
+
from io import BytesIO
|
|
6
|
+
from typing import Any, Literal
|
|
7
|
+
|
|
8
|
+
from loguru import logger
|
|
9
|
+
from PIL import Image
|
|
10
|
+
|
|
11
|
+
from .template_based import Preprocessor
|
|
12
|
+
|
|
13
|
+
Data = dict[str, Any]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def image_to_base64(image: Image.Image, image_format: str, max_length: int | None = None) -> str:
|
|
17
|
+
"""Encode a PIL image as a `data:image/...;base64,...` URL string.
|
|
18
|
+
|
|
19
|
+
If `max_length` is given and the encoded string exceeds it, the image is
|
|
20
|
+
iteratively downscaled until the encoded string fits.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def _to_base64(img: Image.Image) -> str:
|
|
24
|
+
buffer = BytesIO()
|
|
25
|
+
img.convert("RGB").save(buffer, format=image_format)
|
|
26
|
+
return base64.b64encode(buffer.getvalue()).decode("utf-8")
|
|
27
|
+
|
|
28
|
+
base64_image = _to_base64(image)
|
|
29
|
+
if max_length is not None and len(base64_image) > max_length:
|
|
30
|
+
factor = 1.0
|
|
31
|
+
new_size = image.size
|
|
32
|
+
while len(base64_image) > max_length:
|
|
33
|
+
factor *= 0.9
|
|
34
|
+
new_size = (int(image.width * factor), int(image.height * factor))
|
|
35
|
+
resized_image = image.resize(new_size, resample=Image.Resampling.BILINEAR)
|
|
36
|
+
base64_image = _to_base64(resized_image)
|
|
37
|
+
logger.debug(f"Image size reduced to {new_size} to fit max_length {max_length}.")
|
|
38
|
+
return f"data:image/{image_format.lower()};base64,{base64_image}"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def load_image(image: Image.Image | dict) -> Image.Image:
|
|
42
|
+
"""Normalize an image value into a PIL Image.
|
|
43
|
+
|
|
44
|
+
Accepts PIL Image objects or dicts of the form `{"bytes": ..., "path": ...}`
|
|
45
|
+
(the raw form stored in parquet files that is obtained when images are
|
|
46
|
+
loaded without the HF `Image` feature metadata, e.g. via the `parquet`
|
|
47
|
+
dataset loader).
|
|
48
|
+
"""
|
|
49
|
+
if isinstance(image, Image.Image):
|
|
50
|
+
return image
|
|
51
|
+
if isinstance(image, dict):
|
|
52
|
+
if image.get("bytes") is not None:
|
|
53
|
+
return Image.open(BytesIO(image["bytes"]))
|
|
54
|
+
if image.get("path") is not None:
|
|
55
|
+
return Image.open(image["path"])
|
|
56
|
+
msg = f"Unsupported image value: {type(image)}"
|
|
57
|
+
raise TypeError(msg)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@dataclasses.dataclass
|
|
61
|
+
class ConvertImageToBase64(Preprocessor):
|
|
62
|
+
"""Convert an image stored under `key` to a base64 data-URL string stored
|
|
63
|
+
under `{key}_base64`, ready to be embedded as an OpenAI-compatible
|
|
64
|
+
`image_url` content part.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
key: str
|
|
68
|
+
format: Literal["PNG", "JPEG"] = "PNG"
|
|
69
|
+
max_length: int | None = None
|
|
70
|
+
|
|
71
|
+
def __call__(self, item: Data) -> Data:
|
|
72
|
+
image = item[self.key]
|
|
73
|
+
if image is None:
|
|
74
|
+
base64_image = None
|
|
75
|
+
else:
|
|
76
|
+
base64_image = image_to_base64(
|
|
77
|
+
load_image(image),
|
|
78
|
+
image_format=self.format,
|
|
79
|
+
max_length=self.max_length,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
item[f"{self.key}_base64"] = base64_image
|
|
83
|
+
return item
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclasses.dataclass
|
|
87
|
+
class ConvertImageListToBase64(Preprocessor):
|
|
88
|
+
"""Convert a list of images (e.g., for multi-image VQA) stored under `key`
|
|
89
|
+
to a list of base64 data-URL strings stored under `{key}_base64`.
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
key: str
|
|
93
|
+
format: Literal["PNG", "JPEG"] = "PNG"
|
|
94
|
+
max_length: int | None = None
|
|
95
|
+
|
|
96
|
+
def __call__(self, item: Data) -> Data:
|
|
97
|
+
images = item[self.key]
|
|
98
|
+
if images is None:
|
|
99
|
+
item[f"{self.key}_base64"] = None
|
|
100
|
+
elif isinstance(images, (list, tuple)):
|
|
101
|
+
item[f"{self.key}_base64"] = [
|
|
102
|
+
image_to_base64(load_image(image), image_format=self.format, max_length=self.max_length)
|
|
103
|
+
for image in images
|
|
104
|
+
]
|
|
105
|
+
else:
|
|
106
|
+
msg = f"Unsupported image list type: {type(images)}"
|
|
107
|
+
raise TypeError(msg)
|
|
108
|
+
|
|
109
|
+
return item
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@dataclasses.dataclass
|
|
113
|
+
class EnsureMinSize(Preprocessor):
|
|
114
|
+
"""Ensure the image under `key` is at least `min_size` pixels on its
|
|
115
|
+
shorter side, upscaling in place (preserving aspect ratio) if necessary.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
key: str
|
|
119
|
+
min_size: int
|
|
120
|
+
interpolation: Image.Resampling = Image.Resampling.BILINEAR
|
|
121
|
+
|
|
122
|
+
def __call__(self, item: Data) -> Data:
|
|
123
|
+
image = item[self.key]
|
|
124
|
+
if image is None:
|
|
125
|
+
return item
|
|
126
|
+
|
|
127
|
+
if not isinstance(image, Image.Image):
|
|
128
|
+
msg = f"Unsupported image type: {type(image)}"
|
|
129
|
+
raise TypeError(msg)
|
|
130
|
+
|
|
131
|
+
width, height = image.size
|
|
132
|
+
if width >= self.min_size and height >= self.min_size:
|
|
133
|
+
return item
|
|
134
|
+
if width <= height:
|
|
135
|
+
new_width = self.min_size
|
|
136
|
+
new_height = int(self.min_size * height / width)
|
|
137
|
+
else:
|
|
138
|
+
new_height = self.min_size
|
|
139
|
+
new_width = int(self.min_size * width / height)
|
|
140
|
+
item[self.key] = image.resize((new_width, new_height), resample=self.interpolation)
|
|
141
|
+
return item
|
|
@@ -170,7 +170,9 @@ class HFChatDataset(TemplateChatDataset):
|
|
|
170
170
|
path: The path to the Hugging Face dataset.
|
|
171
171
|
split: The split of the dataset.
|
|
172
172
|
input_template: A Jinja2 template for the user input.
|
|
173
|
-
subset: The subset of the dataset.
|
|
173
|
+
subset: The subset of the dataset. If a list is given, all subsets are
|
|
174
|
+
loaded and concatenated, and each item gains a "subset" key with
|
|
175
|
+
its subset name (unless the column already exists).
|
|
174
176
|
dataset_kwargs: The keyword arguments to pass to the Hugging Face dataset.
|
|
175
177
|
"""
|
|
176
178
|
|
|
@@ -179,7 +181,7 @@ class HFChatDataset(TemplateChatDataset):
|
|
|
179
181
|
path: str,
|
|
180
182
|
split: str,
|
|
181
183
|
input_template: str | PathLike[str],
|
|
182
|
-
subset: str | None = None,
|
|
184
|
+
subset: str | list[str] | None = None,
|
|
183
185
|
dataset_kwargs: dict[str, Any] | None = None,
|
|
184
186
|
reference_template: str | PathLike[str] | None = None,
|
|
185
187
|
reference_list_template: str | PathLike[str] | None = None,
|
|
@@ -193,8 +195,17 @@ class HFChatDataset(TemplateChatDataset):
|
|
|
193
195
|
preprocessors: list[Preprocessor] | None = None,
|
|
194
196
|
) -> None:
|
|
195
197
|
dataset_kwargs = dataset_kwargs or {}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
+
if isinstance(subset, list):
|
|
199
|
+
items = []
|
|
200
|
+
for subset_name in subset:
|
|
201
|
+
dataset = datasets.load_dataset(path, name=subset_name, split=split, **dataset_kwargs)
|
|
202
|
+
for item in dataset:
|
|
203
|
+
item_dict = dict(item)
|
|
204
|
+
item_dict.setdefault("subset", subset_name)
|
|
205
|
+
items.append(item_dict)
|
|
206
|
+
else:
|
|
207
|
+
dataset = datasets.load_dataset(path, name=subset, split=split, **dataset_kwargs)
|
|
208
|
+
items = [dict(item) for item in dataset]
|
|
198
209
|
|
|
199
210
|
super().__init__(
|
|
200
211
|
items=items,
|
|
@@ -39,15 +39,25 @@ class VLLMServerManager:
|
|
|
39
39
|
model_kwargs: Additional keyword arguments to pass as command-line options to `vllm serve`.
|
|
40
40
|
Each key-value pair is converted to a corresponding CLI argument.
|
|
41
41
|
timeout: Maximum time in seconds to wait for the server to become available.
|
|
42
|
+
vllm_version: If specified, `vllm serve` is launched via `uvx --from vllm==<vllm_version>` instead of
|
|
43
|
+
the `vllm` command on the current environment. This allows running any vllm version regardless of
|
|
44
|
+
what (if anything) is installed in the current Python environment.
|
|
42
45
|
"""
|
|
43
46
|
|
|
44
|
-
def __init__(
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
model: str,
|
|
50
|
+
model_kwargs: dict[str, Any] | None = None,
|
|
51
|
+
timeout: int = 3600,
|
|
52
|
+
vllm_version: str | None = None,
|
|
53
|
+
) -> None:
|
|
45
54
|
self.model = model
|
|
46
55
|
self.model_kwargs = model_kwargs or {}
|
|
47
56
|
self.host = "localhost"
|
|
48
57
|
self.port = find_free_port()
|
|
49
58
|
self.base_url = f"http://{self.host}:{self.port}/v1"
|
|
50
59
|
self.timeout = timeout
|
|
60
|
+
self.vllm_version = vllm_version
|
|
51
61
|
self.process: subprocess.Popen | None = None
|
|
52
62
|
self._log_threads: list[threading.Thread] = []
|
|
53
63
|
|
|
@@ -59,8 +69,8 @@ class VLLMServerManager:
|
|
|
59
69
|
logger.warning("vLLM server is already running. Skipping start.")
|
|
60
70
|
return self.host, self.port
|
|
61
71
|
|
|
62
|
-
cmd = [
|
|
63
|
-
|
|
72
|
+
cmd = ["uvx", "--from", f"vllm=={self.vllm_version}", "vllm"] if self.vllm_version is not None else ["vllm"]
|
|
73
|
+
cmd += [
|
|
64
74
|
"serve",
|
|
65
75
|
self.model,
|
|
66
76
|
"--host",
|
|
@@ -175,6 +185,10 @@ class VLLMServeLM(OpenAIChatAPI):
|
|
|
175
185
|
Do not include the prefix "--".
|
|
176
186
|
See also: https://docs.vllm.ai/en/latest/cli/index.html#options
|
|
177
187
|
booting_timeout: Maximum time in seconds to wait for the server to become available.
|
|
188
|
+
vllm_version: If specified, `vllm serve` is launched via `uvx --from vllm==<vllm_version>` instead of
|
|
189
|
+
the `vllm` command on the current environment, so that any vllm version can be used regardless
|
|
190
|
+
of the version (if any) installed in the current Python environment. Requires `uv`/`uvx` to be
|
|
191
|
+
available on PATH.
|
|
178
192
|
default_gen_kwargs: Default generation kwargs to use when calling the API.
|
|
179
193
|
developer_message: Instructions to the model that are prioritized ahead of user messages.
|
|
180
194
|
Previously called the system prompt.
|
|
@@ -191,6 +205,7 @@ class VLLMServeLM(OpenAIChatAPI):
|
|
|
191
205
|
api_headers: dict[str, str] | None = None,
|
|
192
206
|
model_kwargs: dict[str, Any] | None = None,
|
|
193
207
|
booting_timeout: int = 3600,
|
|
208
|
+
vllm_version: str | None = None,
|
|
194
209
|
default_gen_kwargs: dict[str, Any] | None = None,
|
|
195
210
|
developer_message: str | None = None,
|
|
196
211
|
string_processors: StringProcessor | list[StringProcessor] | None = None,
|
|
@@ -206,7 +221,9 @@ class VLLMServeLM(OpenAIChatAPI):
|
|
|
206
221
|
model_kwargs = model_kwargs or {}
|
|
207
222
|
if "tensor_parallel_size" not in model_kwargs and "tensor-parallel-size" not in model_kwargs:
|
|
208
223
|
model_kwargs["tensor_parallel_size"] = torch.cuda.device_count()
|
|
209
|
-
self.manager = VLLMServerManager(
|
|
224
|
+
self.manager = VLLMServerManager(
|
|
225
|
+
model=model, model_kwargs=model_kwargs, timeout=booting_timeout, vllm_version=vllm_version
|
|
226
|
+
)
|
|
210
227
|
if api_headers is None:
|
|
211
228
|
api_headers = {}
|
|
212
229
|
api_headers["base_url"] = self.manager.base_url
|
|
@@ -104,6 +104,8 @@ class LLMLabel(Metric):
|
|
|
104
104
|
category_key: A key to create category-wise mean score.
|
|
105
105
|
The category key is expected to be in extra_info.
|
|
106
106
|
metric_prefix: A prefix to be added to the metric keys in the summary and instance details.
|
|
107
|
+
output_reasoning_text: If True, store the evaluator's reasoning content
|
|
108
|
+
as `llm_label_reasoning_text` in the instance details.
|
|
107
109
|
|
|
108
110
|
Examples:
|
|
109
111
|
>>> from flexeval import OpenAIChatAPI, Jinja2PromptTemplate, LLMLabel
|
|
@@ -146,6 +148,7 @@ class LLMLabel(Metric):
|
|
|
146
148
|
valid_score_range: tuple[int, int] | None = None,
|
|
147
149
|
category_key: str | None = None,
|
|
148
150
|
metric_prefix: str | None = None,
|
|
151
|
+
output_reasoning_text: bool = False,
|
|
149
152
|
) -> None:
|
|
150
153
|
self.language_model = language_model
|
|
151
154
|
self.prompt_template = prompt_template
|
|
@@ -166,6 +169,7 @@ class LLMLabel(Metric):
|
|
|
166
169
|
self.valid_score_range = valid_score_range
|
|
167
170
|
self.category_key = category_key
|
|
168
171
|
self.metric_prefix = f"{metric_prefix}-" if metric_prefix else ""
|
|
172
|
+
self.output_reasoning_text = output_reasoning_text
|
|
169
173
|
|
|
170
174
|
def evaluate(
|
|
171
175
|
self,
|
|
@@ -218,6 +222,11 @@ class LLMLabel(Metric):
|
|
|
218
222
|
f"{self.metric_prefix}llm_label_input": eval_in,
|
|
219
223
|
f"{self.metric_prefix}llm_label_output": eval_out.text,
|
|
220
224
|
}
|
|
225
|
+
| (
|
|
226
|
+
{f"{self.metric_prefix}llm_label_reasoning_text": eval_out.reasoning_text}
|
|
227
|
+
if self.output_reasoning_text
|
|
228
|
+
else {}
|
|
229
|
+
)
|
|
221
230
|
for eval_label, eval_score, eval_in, eval_out in zip(
|
|
222
231
|
evaluator_label_list,
|
|
223
232
|
evaluator_score_list,
|
|
@@ -251,6 +260,8 @@ class ChatLLMLabel(Metric):
|
|
|
251
260
|
category_key: A key to create category-wise mean score.
|
|
252
261
|
The category key is expected to be in extra_info.
|
|
253
262
|
metric_prefix: A prefix to be added to the metric keys in the summary and instance details.
|
|
263
|
+
output_reasoning_text: If True, store the evaluator's reasoning content
|
|
264
|
+
as `llm_label_reasoning_text` in the instance details.
|
|
254
265
|
|
|
255
266
|
Examples:
|
|
256
267
|
>>> from flexeval import ChatLLMScore, OpenAIChatAPI, Jinja2PromptTemplate
|
|
@@ -294,6 +305,7 @@ class ChatLLMLabel(Metric):
|
|
|
294
305
|
disable_tqdm: bool = False,
|
|
295
306
|
category_key: str | None = None,
|
|
296
307
|
metric_prefix: str | None = None,
|
|
308
|
+
output_reasoning_text: bool = False,
|
|
297
309
|
) -> None:
|
|
298
310
|
self.language_model = language_model
|
|
299
311
|
self.prompt_template = prompt_template
|
|
@@ -314,6 +326,7 @@ class ChatLLMLabel(Metric):
|
|
|
314
326
|
self.disable_tqdm = disable_tqdm
|
|
315
327
|
self.category_key = category_key
|
|
316
328
|
self.metric_prefix = f"{metric_prefix}-" if metric_prefix else ""
|
|
329
|
+
self.output_reasoning_text = output_reasoning_text
|
|
317
330
|
|
|
318
331
|
def evaluate(
|
|
319
332
|
self,
|
|
@@ -367,6 +380,11 @@ class ChatLLMLabel(Metric):
|
|
|
367
380
|
f"{self.metric_prefix}llm_label_input": eval_in,
|
|
368
381
|
f"{self.metric_prefix}llm_label_output": eval_out.text,
|
|
369
382
|
}
|
|
383
|
+
| (
|
|
384
|
+
{f"{self.metric_prefix}llm_label_reasoning_text": eval_out.reasoning_text}
|
|
385
|
+
if self.output_reasoning_text
|
|
386
|
+
else {}
|
|
387
|
+
)
|
|
370
388
|
for eval_label, eval_score, eval_in, eval_out in zip(
|
|
371
389
|
evaluator_label_list,
|
|
372
390
|
evaluator_score_list,
|
|
@@ -161,7 +161,7 @@ def generate_evaluations(
|
|
|
161
161
|
disable=disable_tqdm,
|
|
162
162
|
desc=desc_for_tqdm,
|
|
163
163
|
) as pbar:
|
|
164
|
-
evaluator_output_list: list[
|
|
164
|
+
evaluator_output_list: list[LMOutput] = []
|
|
165
165
|
for batch_inputs in batch_iter(
|
|
166
166
|
evaluator_input_list,
|
|
167
167
|
batch_size=batch_size,
|
|
@@ -196,6 +196,8 @@ class LLMScore(Metric):
|
|
|
196
196
|
The category keys are expected to be in extra_info.
|
|
197
197
|
metric_prefix: A prefix to be added to the metric keys in the summary and instance details.
|
|
198
198
|
regex_to_parse_score: A regular expression to parse score.
|
|
199
|
+
output_reasoning_text: If True, store the evaluator's reasoning content
|
|
200
|
+
as `llm_score_reasoning_text` in the instance details.
|
|
199
201
|
|
|
200
202
|
Examples:
|
|
201
203
|
>>> from flexeval import LLMScore, OpenAIChatAPI, Jinja2PromptTemplate
|
|
@@ -231,6 +233,7 @@ class LLMScore(Metric):
|
|
|
231
233
|
category_key: str | list[str] | None = None,
|
|
232
234
|
metric_prefix: str | None = None,
|
|
233
235
|
regex_to_parse_score: str = r"(\d+)",
|
|
236
|
+
output_reasoning_text: bool = False,
|
|
234
237
|
) -> None:
|
|
235
238
|
self.language_model = language_model
|
|
236
239
|
self.prompt_template = prompt_template
|
|
@@ -240,6 +243,7 @@ class LLMScore(Metric):
|
|
|
240
243
|
self.category_key = category_key
|
|
241
244
|
self.metric_prefix = f"{metric_prefix}-" if metric_prefix else ""
|
|
242
245
|
self.regex_to_parse_score = regex_to_parse_score
|
|
246
|
+
self.output_reasoning_text = output_reasoning_text
|
|
243
247
|
|
|
244
248
|
def evaluate(
|
|
245
249
|
self,
|
|
@@ -287,6 +291,11 @@ class LLMScore(Metric):
|
|
|
287
291
|
f"{self.metric_prefix}llm_score_input": eval_in,
|
|
288
292
|
f"{self.metric_prefix}llm_score_output": eval_out.text,
|
|
289
293
|
}
|
|
294
|
+
| (
|
|
295
|
+
{f"{self.metric_prefix}llm_score_reasoning_text": eval_out.reasoning_text}
|
|
296
|
+
if self.output_reasoning_text
|
|
297
|
+
else {}
|
|
298
|
+
)
|
|
290
299
|
for eval_score, eval_in, eval_out in zip(
|
|
291
300
|
evaluator_score_list,
|
|
292
301
|
evaluator_input_list,
|
|
@@ -320,6 +329,8 @@ class ChatLLMScore(Metric):
|
|
|
320
329
|
The category keys are expected to be in extra_info.
|
|
321
330
|
metric_prefix: A prefix to be added to the metric keys in the summary and instance details.
|
|
322
331
|
regex_to_parse_score: A regular expression to parse score.
|
|
332
|
+
output_reasoning_text: If True, store the evaluator's reasoning content
|
|
333
|
+
as `llm_score_reasoning_text` in the instance details.
|
|
323
334
|
|
|
324
335
|
Examples:
|
|
325
336
|
>>> from flexeval import ChatLLMScore, OpenAIChatAPI, Jinja2PromptTemplate
|
|
@@ -357,6 +368,7 @@ class ChatLLMScore(Metric):
|
|
|
357
368
|
category_key: str | list[str] | None = None,
|
|
358
369
|
metric_prefix: str | None = None,
|
|
359
370
|
regex_to_parse_score: str = r"(\d+)",
|
|
371
|
+
output_reasoning_text: bool = False,
|
|
360
372
|
) -> None:
|
|
361
373
|
self.language_model = language_model
|
|
362
374
|
self.prompt_template = prompt_template
|
|
@@ -367,6 +379,7 @@ class ChatLLMScore(Metric):
|
|
|
367
379
|
self.category_key = category_key
|
|
368
380
|
self.metric_prefix = f"{metric_prefix}-" if metric_prefix else ""
|
|
369
381
|
self.regex_to_parse_score = regex_to_parse_score
|
|
382
|
+
self.output_reasoning_text = output_reasoning_text
|
|
370
383
|
|
|
371
384
|
def evaluate(
|
|
372
385
|
self,
|
|
@@ -412,6 +425,11 @@ class ChatLLMScore(Metric):
|
|
|
412
425
|
f"{self.metric_prefix}llm_score_input": eval_in,
|
|
413
426
|
f"{self.metric_prefix}llm_score_output": eval_out.text,
|
|
414
427
|
}
|
|
428
|
+
| (
|
|
429
|
+
{f"{self.metric_prefix}llm_score_reasoning_text": eval_out.reasoning_text}
|
|
430
|
+
if self.output_reasoning_text
|
|
431
|
+
else {}
|
|
432
|
+
)
|
|
415
433
|
for eval_score, eval_in, eval_out in zip(
|
|
416
434
|
evaluator_score_list,
|
|
417
435
|
evaluator_input_list,
|
{flexeval-0.18.0 → flexeval-0.18.1}/flexeval/core/reward_model/pairwise_judge_reward_model.py
RENAMED
|
@@ -4,7 +4,7 @@ from dataclasses import asdict, dataclass
|
|
|
4
4
|
from enum import Enum
|
|
5
5
|
from typing import Any
|
|
6
6
|
|
|
7
|
-
from flexeval.core.language_model.base import LanguageModel
|
|
7
|
+
from flexeval.core.language_model.base import LanguageModel, LMOutput
|
|
8
8
|
from flexeval.core.prompt_template.base import PromptTemplate
|
|
9
9
|
from flexeval.core.reward_bench_dataset import RewardBenchInstance
|
|
10
10
|
from flexeval.core.reward_model.base import RewardModel
|
|
@@ -40,38 +40,48 @@ def evaluate_model_output(model_output: str, gold_label: PairwiseChoice) -> bool
|
|
|
40
40
|
|
|
41
41
|
def aggregate_judge_results(
|
|
42
42
|
outputs: list[dict],
|
|
43
|
-
judge_outputs: list,
|
|
43
|
+
judge_outputs: list[LMOutput],
|
|
44
44
|
chosen_is_better_list: list[bool],
|
|
45
|
+
output_reasoning_text: bool = False,
|
|
45
46
|
) -> tuple[list[bool], list[dict]]:
|
|
46
47
|
"""
|
|
47
48
|
Aggregates the doubled-length `judge_outputs` and `chosen_is_better_list`
|
|
48
49
|
into final results for each individual instance.
|
|
49
50
|
|
|
51
|
+
Args:
|
|
52
|
+
outputs: Per-instance details to merge into the aggregated outputs.
|
|
53
|
+
judge_outputs: Judge outputs, twice the length of `outputs`.
|
|
54
|
+
chosen_is_better_list: Whether the chosen answer won, twice the length of `outputs`.
|
|
55
|
+
output_reasoning_text: If True, add `llm_reasoning_texts` to the aggregated outputs.
|
|
56
|
+
|
|
50
57
|
Returns:
|
|
51
58
|
final_results: list[bool]
|
|
52
59
|
A list indicating whether each instance is ultimately judged as correct.
|
|
60
|
+
aggregated_outputs: list[dict]
|
|
61
|
+
A list of per-instance details.
|
|
53
62
|
"""
|
|
54
63
|
aggregated_results: list[bool] = []
|
|
55
64
|
aggregated_outputs: list[dict] = []
|
|
56
65
|
|
|
57
66
|
for i, output in enumerate(outputs):
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
ab_output = judge_outputs[i * 2]
|
|
68
|
+
ba_output = judge_outputs[i * 2 + 1]
|
|
60
69
|
ab_eval = chosen_is_better_list[i * 2]
|
|
61
70
|
ba_eval = chosen_is_better_list[i * 2 + 1]
|
|
62
71
|
|
|
63
72
|
consistent = ab_eval == ba_eval
|
|
64
73
|
is_correct = consistent and ab_eval
|
|
65
74
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
aggregated_output = {
|
|
76
|
+
"llm_outputs": [ab_output.text, ba_output.text],
|
|
77
|
+
"evaluation_results": [ab_eval, ba_eval],
|
|
78
|
+
"consistent": consistent,
|
|
79
|
+
"is_correct": is_correct,
|
|
80
|
+
**output,
|
|
81
|
+
}
|
|
82
|
+
if output_reasoning_text:
|
|
83
|
+
aggregated_output["llm_reasoning_texts"] = [ab_output.reasoning_text, ba_output.reasoning_text]
|
|
84
|
+
aggregated_outputs.append(aggregated_output)
|
|
75
85
|
aggregated_results.append(is_correct)
|
|
76
86
|
|
|
77
87
|
return aggregated_results, aggregated_outputs
|
|
@@ -102,6 +112,8 @@ class PairwiseJudgeRewardModel(RewardModel):
|
|
|
102
112
|
Be sure to include {{prompt}}, {{answer_a}}, and {{answer_b}}.
|
|
103
113
|
system_message: The system message to prepend to the chat messages.
|
|
104
114
|
gen_kwargs: Generation kwargs for the language model.
|
|
115
|
+
output_reasoning_text: If True, store the judge's reasoning content
|
|
116
|
+
as `llm_reasoning_texts` in the outputs.
|
|
105
117
|
"""
|
|
106
118
|
|
|
107
119
|
def __init__(
|
|
@@ -110,6 +122,7 @@ class PairwiseJudgeRewardModel(RewardModel):
|
|
|
110
122
|
prompt_template: PromptTemplate,
|
|
111
123
|
system_message: str | PromptTemplate | None = None,
|
|
112
124
|
gen_kwargs: dict[str, Any] | None = None,
|
|
125
|
+
output_reasoning_text: bool = False,
|
|
113
126
|
) -> None:
|
|
114
127
|
if gen_kwargs is None:
|
|
115
128
|
gen_kwargs = {}
|
|
@@ -117,6 +130,7 @@ class PairwiseJudgeRewardModel(RewardModel):
|
|
|
117
130
|
self.prompt_template = prompt_template
|
|
118
131
|
self.system_message = system_message
|
|
119
132
|
self.gen_kwargs = gen_kwargs
|
|
133
|
+
self.output_reasoning_text = output_reasoning_text
|
|
120
134
|
|
|
121
135
|
def _create_input_chat_messages_list(self, pairwise_instance: PairwiseInstance) -> list[dict[str, str]]:
|
|
122
136
|
pairwise_instance_asdict = asdict(pairwise_instance)
|
|
@@ -182,6 +196,8 @@ class PairwiseJudgeRewardModel(RewardModel):
|
|
|
182
196
|
msg = "The number of outputs should be twice the number of inputs."
|
|
183
197
|
raise ValueError(msg)
|
|
184
198
|
|
|
185
|
-
aggregated_results, aggregated_outputs = aggregate_judge_results(
|
|
199
|
+
aggregated_results, aggregated_outputs = aggregate_judge_results(
|
|
200
|
+
outputs, judge_outputs, chosen_is_better_list, self.output_reasoning_text
|
|
201
|
+
)
|
|
186
202
|
|
|
187
203
|
return aggregated_results, aggregated_outputs
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import re
|
|
2
|
+
import string
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from .base import StringProcessor
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class LastChoiceExtractor(StringProcessor):
|
|
9
|
+
"""
|
|
10
|
+
StringProcessor that extracts the last mentioned multiple-choice option symbol.
|
|
11
|
+
Useful to extract an answer after a step-by-step derivation.
|
|
12
|
+
|
|
13
|
+
MCQ benchmark scores (e.g. MMMU/JMMMU `mcq_exact_match`) depend on this
|
|
14
|
+
extraction logic; changing it silently shifts reported scores, so keep it
|
|
15
|
+
stable across releases.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
lang: Language of the response, "en" or "ja".
|
|
19
|
+
With "ja", option symbols surrounded by Japanese characters
|
|
20
|
+
(e.g. "正解はAです。") are also detected.
|
|
21
|
+
option_type: The style of option symbols:
|
|
22
|
+
"number" (1, 2, ...), "alphabet" (a, b, ...), or "Alphabet" (A, B, ...).
|
|
23
|
+
max_num_options: The maximum number of options.
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
>>> from flexeval import LastChoiceExtractor
|
|
27
|
+
>>> processor = LastChoiceExtractor(lang="en")
|
|
28
|
+
>>> text = "The answer is A."
|
|
29
|
+
>>> print(processor(text))
|
|
30
|
+
A
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
lang: Literal["ja", "en"] = "en",
|
|
36
|
+
option_type: Literal["number", "alphabet", "Alphabet"] = "Alphabet",
|
|
37
|
+
max_num_options: int = 4,
|
|
38
|
+
) -> None:
|
|
39
|
+
self.lang = lang
|
|
40
|
+
if option_type == "number":
|
|
41
|
+
self.choices = [str(i) for i in range(1, max_num_options + 1)]
|
|
42
|
+
elif option_type == "alphabet":
|
|
43
|
+
self.choices = list(string.ascii_lowercase[:max_num_options])
|
|
44
|
+
elif option_type == "Alphabet":
|
|
45
|
+
self.choices = list(string.ascii_uppercase[:max_num_options])
|
|
46
|
+
else:
|
|
47
|
+
msg = f"Unsupported option_type: {option_type}"
|
|
48
|
+
raise ValueError(msg)
|
|
49
|
+
|
|
50
|
+
def _remove_punctuations(self, response: str) -> str:
|
|
51
|
+
punctuation = string.punctuation
|
|
52
|
+
if self.lang == "ja":
|
|
53
|
+
# add full-width punctuations
|
|
54
|
+
punctuation += "!”#$%&’()*+,−./:;<=>?@[\]^_`{|}〜、。¥・"
|
|
55
|
+
return response.strip().strip(punctuation)
|
|
56
|
+
|
|
57
|
+
def _find_choice_with_brackets(self, response: str) -> list[str]:
|
|
58
|
+
# e.g. (A), (B), ...
|
|
59
|
+
return [c for c in self.choices if f"({c})" in response]
|
|
60
|
+
|
|
61
|
+
def _find_choice_without_brackets(self, response: str) -> list[str]:
|
|
62
|
+
# e.g. A, B, ...
|
|
63
|
+
return [c for c in self.choices if re.search(rf"\b{c}\b", response)]
|
|
64
|
+
|
|
65
|
+
def _find_choice_between_japanese(self, response: str) -> list[str]:
|
|
66
|
+
# e.g. 正解はAです。
|
|
67
|
+
japanese_char_pattern = r"[\u3040-\u30FF\u4E00-\u9FFF]"
|
|
68
|
+
return [c for c in self.choices if re.search(rf"{japanese_char_pattern}{c}{japanese_char_pattern}", response)]
|
|
69
|
+
|
|
70
|
+
def __call__(self, text: str) -> str:
|
|
71
|
+
candidates = self._find_choice_with_brackets(text)
|
|
72
|
+
if not candidates:
|
|
73
|
+
text = self._remove_punctuations(text)
|
|
74
|
+
candidates = self._find_choice_without_brackets(text)
|
|
75
|
+
if not candidates and self.lang == "ja":
|
|
76
|
+
candidates = self._find_choice_between_japanese(text)
|
|
77
|
+
|
|
78
|
+
if not candidates:
|
|
79
|
+
return ""
|
|
80
|
+
# choose the last mentioned option if multiple options are extracted
|
|
81
|
+
return max(candidates, key=text.rfind)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
+
from ast import literal_eval as _ast_literal_eval
|
|
5
|
+
from typing import Any
|
|
4
6
|
|
|
5
7
|
import jinja2
|
|
6
8
|
from jinja2 import sandbox
|
|
@@ -19,6 +21,16 @@ def truncate_middle(s: str, length: int, filler: str = "...") -> str:
|
|
|
19
21
|
return s[:prefix_len] + filler + s[-suffix_len:]
|
|
20
22
|
|
|
21
23
|
|
|
24
|
+
def literal_eval(value: Any) -> Any: # noqa: ANN401
|
|
25
|
+
"""Parse a stringified Python literal (e.g. "['a', 'b']", a common storage
|
|
26
|
+
format for list columns in Hugging Face datasets) into the actual object.
|
|
27
|
+
Non-string values are returned unchanged.
|
|
28
|
+
"""
|
|
29
|
+
if isinstance(value, str):
|
|
30
|
+
return _ast_literal_eval(value)
|
|
31
|
+
return value
|
|
32
|
+
|
|
33
|
+
|
|
22
34
|
JINJA2_ENV = sandbox.ImmutableSandboxedEnvironment(
|
|
23
35
|
undefined=jinja2.StrictUndefined,
|
|
24
36
|
autoescape=False, # important for not escaping double quotations
|
|
@@ -26,3 +38,4 @@ JINJA2_ENV = sandbox.ImmutableSandboxedEnvironment(
|
|
|
26
38
|
)
|
|
27
39
|
JINJA2_ENV.filters["regex_replace"] = regex_replace
|
|
28
40
|
JINJA2_ENV.filters["truncate_middle"] = truncate_middle
|
|
41
|
+
JINJA2_ENV.filters["literal_eval"] = literal_eval
|