Files
2025-05-23 22:01:00 +08:00

768 lines
35 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import random
import json
import uuid
from games.base.game import Game
from base.data import Data
from games.tasks.object_counting.scripts.object_counting_verifier import ObjectCountingVerifier
from games.tasks.object_counting.scripts.object_counting_prompt import CHINESE_PROMPTS, ENGLISH_PROMPTS
import argparse
import pathlib
class ObjectCounting(Game):
def __init__(self,
min_sequence_length=3,
max_sequence_length=6,
min_count=5,
max_count=100,
min_my_items_per_category=2,
max_my_items_per_category=5,
min_others_possessions=25,
max_others_possessions=40,
available_categories=None,
min_categories=3,
max_categories=7,
story_type_probs=(0.4, 0.4, 0.2), # 无故事, 简单故事, 复杂故事的概率
language=None): # 新增语言参数,None表示随机选择
"""
初始化物品计数问题生成器
参数:
min_sequence_length: 故事中数字序列的最小长度
max_sequence_length: 故事中数字序列的最大长度
min_count: 生成的数字最小值
max_count: 生成的数字最大值
min_my_items_per_category: 我在每个类别中拥有的最少物品数
max_my_items_per_category: 我在每个类别中拥有的最多物品数
min_others_possessions: 其他人拥有的最少物品总数
max_others_possessions: 其他人拥有的最多物品总数
available_categories: 要使用的物品类别列表,默认值为None表示每次生成问题时随机选择
min_categories: 随机选择时的最小类别数
max_categories: 随机选择时的最大类别数
story_type_probs: 三元组 (无故事概率, 简单故事概率, 复杂故事概率),总和应为1
language: 使用的语言,可选 'en' 或 'zh',None 表示随机选择
"""
super().__init__("Object Counting", ObjectCountingVerifier)
# 验证故事类型概率
if sum(story_type_probs) != 1.0:
raise ValueError("故事类型概率总和必须为1.0")
self.no_story_prob = story_type_probs[0]
self.simple_story_prob = story_type_probs[1]
self.complex_story_prob = story_type_probs[2]
# 初始化序列和数字范围
self.min_sequence_length = min_sequence_length
self.max_sequence_length = max_sequence_length
self.min_count = min_count
self.max_count = max_count
self.min_my_items_per_category = min_my_items_per_category
self.max_my_items_per_category = max_my_items_per_category
self.min_others_possessions = min_others_possessions
self.max_others_possessions = max_others_possessions
self.min_categories = min_categories
self.max_categories = max_categories
# 保存用户指定的类别(如果有)
self.specified_categories = available_categories
# 存储当前使用的语言
self.language = language
# 定义英文人物列表
self.en_people = ["I", "My aunt", "My uncle", "My brother", "My sister", "My mother", "My father",
"My grandmother", "My grandfather", "My cousin", "My friend", "My colleague",
"My neighbor", "My teacher", "My professor", "My roommate", "My boss"]
# 定义中文人物列表
self.zh_people = ["我", "我的阿姨", "我的叔叔", "我的哥哥", "我的姐姐", "我的母亲", "我的父亲",
"我的奶奶", "我的爷爷", "我的表兄弟", "我的朋友", "我的同事",
"我的邻居", "我的老师", "我的教授", "我的室友", "我的老板"]
# 英文物品类别
self.en_fruits = ["apples", "bananas", "oranges", "grapes", "strawberries", "watermelons",
"pineapples", "mangoes", "kiwis", "peaches", "plums", "cherries",
"breadfruits", "nectarines", "apricots", "lemons", "guavas", "dates",
"plantains", "envy apples", "jonagold apples", "dragonfruit", "lychee",
"persimmons", "pomegranates", "raspberries", "blueberries", "blackberries"]
self.en_animals = ["dogs", "cats", "birds", "hamsters", "rabbits", "turtles", "fish",
"snakes", "lizards", "frogs", "monkeys", "opossums", "wolves",
"beavers", "falcons", "ducks", "parrots", "tarantulas", "scorpions",
"hedgehogs", "ferrets", "chinchillas", "guinea pigs", "mice", "rats",
"geckos", "iguanas", "chameleons", "crabs", "shrimps"]
self.en_cars = ["toyota corolla", "honda civic", "ford mustang", "tesla model 3",
"nissan altima", "chevrolet camaro", "hyundai elantra", "mazda cx-5",
"kia niro", "jeep gladiator", "toyota tundra", "honda element",
"nissan sentra", "mazda cx-90", "hyundai santa fe", "nissan armada",
"nissan pathfinder", "toyota highlander", "nissan kicks", "mazda cx-50",
"bmw x5", "audi a4", "mercedes c-class", "lexus rx", "volvo xc90",
"subaru outback", "volkswagen golf", "porsche 911", "jaguar f-type"]
self.en_electronics = ["smartphones", "laptops", "tablets", "smartwatches", "headphones",
"bluetooth speakers", "digital cameras", "video game consoles", "drones",
"e-readers", "smart TVs", "VR headsets", "wireless earbuds", "monitors",
"desktop computers", "routers", "hard drives", "graphics cards", "keyboards"]
self.en_books = ["mystery novels", "sci-fi books", "fantasy books", "history books",
"biographies", "cookbooks", "self-help books", "poetry collections",
"graphic novels", "children's books", "textbooks", "encyclopedias",
"travel guides", "art books", "reference books", "comics", "magazines"]
self.en_furniture = ["chairs", "tables", "sofas", "bookshelves", "desks", "beds",
"coffee tables", "dining tables", "nightstands", "dressers", "ottomans",
"bean bags", "rocking chairs", "benches", "armchairs", "recliners", "stools"]
self.en_clothes = ["t-shirts", "jeans", "dresses", "sweaters", "jackets", "hoodies",
"skirts", "shorts", "suits", "ties", "scarves", "hats", "gloves",
"socks", "shoes", "boots", "sneakers", "coats", "pajamas", "swimsuits"]
# 中文物品类别
self.zh_fruits = ["苹果", "香蕉", "橙子", "葡萄", "草莓", "西瓜",
"菠萝", "芒果", "猕猴桃", "桃子", "李子", "樱桃",
"面包果", "油桃", "杏子", "柠檬", "番石榴", "枣",
"芭蕉", "爱妃苹果", "乔纳金苹果", "火龙果", "荔枝",
"柿子", "石榴", "覆盆子", "蓝莓", "黑莓"]
self.zh_animals = ["狗", "猫", "鸟", "仓鼠", "兔子", "乌龟", "鱼",
"蛇", "蜥蜴", "青蛙", "猴子", "负鼠", "狼",
"海狸", "猎鹰", "鸭子", "鹦鹉", "狼蛛", "蝎子",
"刺猬", "雪貂", "龙猫", "豚鼠", "老鼠", "大鼠",
"壁虎", "鬣蜥", "变色龙", "螃蟹", "虾"]
self.zh_cars = ["丰田卡罗拉", "本田思域", "福特野马", "特斯拉Model 3",
"日产天籁", "雪佛兰科迈罗", "现代伊兰特", "马自达CX-5",
"起亚Niro", "吉普角斗士", "丰田坦途", "本田Element",
"日产轩逸", "马自达CX-90", "现代胜达", "日产Armada",
"日产途达", "丰田汉兰达", "日产劲客", "马自达CX-50",
"宝马X5", "奥迪A4", "奔驰C级", "雷克萨斯RX", "沃尔沃XC90",
"斯巴鲁傲虎", "大众高尔夫", "保时捷911", "捷豹F-Type"]
self.zh_electronics = ["智能手机", "笔记本电脑", "平板电脑", "智能手表", "耳机",
"蓝牙音箱", "数码相机", "游戏机", "无人机",
"电子阅读器", "智能电视", "VR头盔", "无线耳塞", "显示器",
"台式电脑", "路由器", "硬盘", "显卡", "键盘"]
self.zh_books = ["推理小说", "科幻书籍", "奇幻书籍", "历史书籍",
"传记", "烹饪书", "自助书籍", "诗集",
"图画小说", "儿童书籍", "教科书", "百科全书",
"旅游指南", "艺术书籍", "参考书", "漫画", "杂志"]
self.zh_furniture = ["椅子", "桌子", "沙发", "书架", "书桌", "床",
"咖啡桌", "餐桌", "床头柜", "梳妆台", "脚凳",
"豆袋", "摇椅", "长凳", "扶手椅", "躺椅", "凳子"]
self.zh_clothes = ["T恤", "牛仔裤", "连衣裙", "毛衣", "夹克", "卫衣",
"裙子", "短裤", "西装", "领带", "围巾", "帽子", "手套",
"袜子", "鞋子", "靴子", "运动鞋", "外套", "睡衣", "泳装"]
# 英文物品类别集合
self.en_all_categories = {
"fruit": self.en_fruits,
"animal": self.en_animals,
"car": self.en_cars,
"electronic": self.en_electronics,
"book": self.en_books,
"furniture": self.en_furniture,
"clothes": self.en_clothes
}
# 中文物品类别集合
self.zh_all_categories = {
"fruit": self.zh_fruits,
"animal": self.zh_animals,
"car": self.zh_cars,
"electronic": self.zh_electronics,
"book": self.zh_books,
"furniture": self.zh_furniture,
"clothes": self.zh_clothes
}
# 英文简单故事描述
self.en_simple_descriptions = [
"(happy to have them)",
"(they are very delicious)",
"(I bought them yesterday)",
"(they are my favorite)",
"(they were on sale at the market)",
"(I collect them as a hobby)",
"(they are organic/eco-friendly)",
"(I plan to use them for a project)",
"(perfect for my needs)",
"(my neighbors gave them to me)",
"(I won them in a contest)",
"(they were a birthday gift)",
"(I inherited them from my grandparents)",
"(I got a great deal on them)",
"(they are quite rare nowadays)"
]
# 中文简单故事描述
self.zh_simple_descriptions = [
"(很高兴拥有它们)",
"(它们非常美味)",
"(我昨天买的)",
"(它们是我最喜欢的)",
"(它们在市场上打折)",
"(我把收集它们作为爱好)",
"(它们是有机/环保的)",
"(我打算用它们做个项目)",
"(非常适合我的需求)",
"(我的邻居给了我这些)",
"(我在比赛中赢得了它们)",
"(它们是生日礼物)",
"(这些是我从祖父母那里继承的)",
"(我买到了很划算的价格)",
"(现在它们相当稀有)"
]
def get_item_category(self, item, language='en'):
"""确定物品属于哪个类别"""
if language == 'en':
categories = self.en_all_categories
else:
categories = self.zh_all_categories
for category_name, items in categories.items():
if any(specific_item == item for specific_item in items):
return category_name
return ""
def generate_complex_story(self, count, complexity="simple", language="en", category=None):
"""
生成带有数字和故事的复杂描述
参数:
count: 物品数量
complexity: 故事复杂度,可选 'simple' 或 'complex'
language: 语言,可选 'en' 或 'zh'
category: 物品类别,确保故事与类别匹配
"""
if complexity not in ["simple", "complex"]:
raise ValueError("复杂度必须是 'simple' 或 'complex'")
# 根据类别选择相应的故事模板
if language == "en":
# 英文故事模板 - 使用英文括号
fruit_stories = [
" (which are organic)",
" (which are fresh from the market)",
" (which are ripe and juicy)",
" (which I bought yesterday)",
" (which are for a fruit salad)"
]
animal_stories = [
" (which are very friendly)",
" (which I'm taking care of)",
" (which need to be fed)",
" (which are in the backyard)",
" (which belong to the shelter)"
]
car_stories = [
" (which are in the garage)",
" (which need maintenance)",
" (which I'm selling)",
" (which are vintage models)",
" (which have low mileage)"
]
electronic_stories = [
" (which need charging)",
" (which are brand new)",
" (which I use for work)",
" (which have high specs)",
" (which were on sale)"
]
book_stories = [
" (which I haven't read yet)",
" (which are bestsellers)",
" (which are on my bookshelf)",
" (which I borrowed from the library)",
" (which have interesting plots)"
]
furniture_stories = [
" (which are antique)",
" (which need assembly)",
" (which match the decor)",
" (which I just purchased)",
" (which are handcrafted)"
]
clothes_stories = [
" (which are in my closet)",
" (which need washing)",
" (which are my favorite)",
" (which are for special occasions)",
" (which are brand new)"
]
default_stories = [
" (which I recently acquired)",
" (which are quite useful)",
" (which I keep at home)",
" (which I like very much)",
" (which are valuable to me)"
]
else:
# 中文故事模板 - 使用中文括号
fruit_stories = [
"(都是有机的)",
"(都是从市场新鲜购买的)",
"(都很新鲜多汁)",
"(是我昨天买的)",
"(准备用来做水果沙拉的)"
]
animal_stories = [
"(它们都很友好)",
"(我正在照顾它们)",
"(需要喂食)",
"(在后院活动)",
"(来自收容所)"
]
car_stories = [
"(都停在车库里)",
"(需要维修保养)",
"(我打算出售的)",
"(都是古董车型)",
"(行驶里程很少)"
]
electronic_stories = [
"(需要充电)",
"(都是全新的)",
"(我用来工作的)",
"(配置很高)",
"(是打折时买的)"
]
book_stories = [
"(我还没读过)",
"(都是畅销书)",
"(放在我的书架上)",
"(是从图书馆借的)",
"(情节很有趣)"
]
furniture_stories = [
"(都是古董)",
"(需要组装)",
"(与装修风格相配)",
"(我刚购买的)",
"(是手工制作的)"
]
clothes_stories = [
"(都在我的衣柜里)",
"(需要洗涤)",
"(是我最喜欢的)",
"(是特殊场合穿的)",
"(是全新的)"
]
default_stories = [
"(我最近获得的)",
"(非常实用的)",
"(我放在家里的)",
"(我非常喜欢的)",
"(对我很有价值的)"
]
# 根据类别选择合适的故事模板
if category == "fruit":
simple_stories = fruit_stories
elif category == "animal":
simple_stories = animal_stories
elif category == "car":
simple_stories = car_stories
elif category == "electronic":
simple_stories = electronic_stories
elif category == "book":
simple_stories = book_stories
elif category == "furniture":
simple_stories = furniture_stories
elif category == "clothes":
simple_stories = clothes_stories
else:
simple_stories = default_stories
# 根据复杂度选择故事
if complexity == "simple":
# 简单故事:随机选择一个简单故事
return random.choice(simple_stories)
else: # 合并complex和calculation为一种灵活的故事类型
# 生成随机的数量序列,最后一个数量必须是count
sequence_length = random.randint(self.min_sequence_length, self.max_sequence_length)
# 直接生成非负数字序列
sequence = []
# 第一个数字随机生成
sequence.append(random.randint(self.min_count, self.max_count))
# 生成中间数字,确保和前一个不同
for i in range(sequence_length - 2):
# 生成与前一个不同的随机数
while True:
new_value = random.randint(self.min_count, self.max_count)
if new_value != sequence[-1]:
break
sequence.append(new_value)
# 最后一个数字必须是count
sequence.append(count)
# 构建故事,根据语言选择不同的模板
if language == 'en':
story = f"(here's how I ended up with {count} of them: initially I had {sequence[0]}"
for i in range(1, len(sequence)):
change = sequence[i] - sequence[i-1]
if change > 0:
story += f", then I got {change} more making it {sequence[i]}"
elif change < 0:
story += f", then I lost {abs(change)} of them leaving me with {sequence[i]}"
else:
story = f"(我是这样拥有这{count}个的:最初我有{sequence[0]}个"
for i in range(1, len(sequence)):
change = sequence[i] - sequence[i-1]
if change > 0:
story += f",然后我又获得了{change}个,总共有{sequence[i]}个"
elif change < 0:
story += f",然后我失去了{abs(change)}个,剩下{sequence[i]}个"
story += ")"
return story
def get_category_display_name(self, category, language='en'):
"""获取类别的显示名称(包含复数形式处理)"""
if language == 'en':
if category == "fruit":
return "fruits"
elif category == "animal":
return "animals"
elif category == "car":
return "cars"
elif category == "electronic":
return "electronics"
elif category == "book":
return "books"
elif category == "furniture":
return "furniture items" # furniture通常没有简单的复数形式
elif category == "clothes":
return "clothing items" # clothes已经是复数
return category + "s" # 默认添加s作为复数
else:
# 中文类别显示名称
if category == "fruit":
return "水果"
elif category == "animal":
return "动物"
elif category == "car":
return "汽车"
elif category == "electronic":
return "电子产品"
elif category == "book":
return "书籍"
elif category == "furniture":
return "家具"
elif category == "clothes":
return "衣物"
return category # 默认直接返回类别名
def generate_problem(self):
"""生成物品计数问题"""
# 决定使用的语言
if self.language == "mixed":
current_language = random.choice(['en', 'zh'])
else:
current_language = self.language
# 根据语言选择对应的人物和类别
if current_language == 'en':
people = self.en_people
all_categories = self.en_all_categories
i_pronoun = "I"
else:
people = self.zh_people
all_categories = self.zh_all_categories
i_pronoun = "我"
# 每次生成问题时选择可用类别
if self.specified_categories is None:
# 随机选择类别
num_categories = random.randint(self.min_categories, self.max_categories)
available_categories = random.sample(list(all_categories.keys()), num_categories)
else:
# 使用用户指定的类别
for category in self.specified_categories:
if category not in all_categories:
raise ValueError(f"Invalid category: {category}")
available_categories = self.specified_categories
# 创建嵌套字典结构,格式为 {人物: {物品种类: [(具体物品, 数量, 描述), ...], ...}, ...}
possessions = {
person: {
category: [] for category in available_categories
} for person in people
}
# 为"我"生成各类物品,包含复杂描述
for category in available_categories:
items_list = all_categories[category]
for _ in range(random.randint(self.min_my_items_per_category, self.max_my_items_per_category)):
# 获取还没分配给"我"的物品
assigned_items = [item for item, _, _ in possessions[i_pronoun][category]]
available_items = [item for item in items_list if item not in assigned_items]
if available_items:
item = random.choice(available_items)
count = random.randint(self.min_count, self.max_count)
# 根据概率决定故事类型
story_type_rand = random.random()
if story_type_rand < self.no_story_prob:
description = "" # 无故事
elif story_type_rand < self.no_story_prob + self.simple_story_prob:
description = self.generate_complex_story(count, "simple", current_language, category)
else:
description = self.generate_complex_story(count, "complex", current_language, category)
possessions[i_pronoun][category].append((item, count, description))
# 生成其他人拥有的物品
for _ in range(random.randint(self.min_others_possessions, self.max_others_possessions)):
person = random.choice([p for p in people if p != i_pronoun]) # 除了"我"以外的人
category = random.choice(available_categories)
items_list = all_categories[category]
# 获取还没分配给这个人的物品
assigned_items = [item for item, _, _ in possessions[person][category]]
available_items = [item for item in items_list if item not in assigned_items]
if available_items:
item = random.choice(available_items)
count = random.randint(self.min_count, self.max_count)
possessions[person][category].append((item, count, ""))
# 将所有物品描述整合为一个列表,用于随机穿插
all_statements = []
# 将其他人的物品添加到列表
for person in [p for p in people if p != i_pronoun]:
for category in available_categories:
for item, count, _ in possessions[person][category]:
all_statements.append((person, item, count, ""))
# 将"我"的物品添加到列表
for category in available_categories:
for item, count, description in possessions[i_pronoun][category]:
all_statements.append((i_pronoun, item, count, description))
# 随机打乱所有物品的顺序
random.shuffle(all_statements)
# 记录每个人是否已经提到过物品
person_mentioned = {person: False for person in people}
# 构建问题文本
problem_text = ""
# 按混合后的顺序添加所有物品描述
for person, item, count, description in all_statements:
category = self.get_item_category(item, current_language)
if current_language == 'en':
if person == "I":
if person_mentioned["I"]:
problem_text += f"I also have {count} {item}{description}. "
else:
problem_text += f"I have {count} {item}{description}. "
person_mentioned["I"] = True
else:
if person_mentioned[person]:
problem_text += f"{person} also has {count} {item}{description}. "
else:
problem_text += f"{person} has {count} {item}{description}. "
person_mentioned[person] = True
else:
if person == "我":
if person_mentioned["我"]:
problem_text += f"我还有{count}个{item}{description}。"
else:
problem_text += f"我有{count}个{item}{description}。"
person_mentioned["我"] = True
else:
if person_mentioned[person]:
problem_text += f"{person}还有{count}个{item}{description}。"
else:
problem_text += f"{person}有{count}个{item}{description}。"
person_mentioned[person] = True
# 确定我拥有物品的类别
my_categories = [cat for cat in available_categories if possessions[i_pronoun][cat]]
if len(my_categories) >= 2:
# 随机选择问题类型
question_type = random.randint(1, 3)
if question_type <= 2: # 两个类别的问题
# 随机选择两个不同的类别
cat1, cat2 = random.sample(my_categories, 2)
# 计算每个类别的总数
total_1 = sum(count for _, count, _ in possessions[i_pronoun][cat1])
total_2 = sum(count for _, count, _ in possessions[i_pronoun][cat2])
# 使用正确的复数形式
cat1_name = self.get_category_display_name(cat1, current_language)
cat2_name = self.get_category_display_name(cat2, current_language)
if question_type == 1: # 求和
answer = total_1 + total_2
if current_language == 'en':
question = f"What is the total number of {cat1_name} and {cat2_name} that I have?"
else:
question = f"我总共有多少个{cat1_name}和{cat2_name}?"
else: # 求差的绝对值
answer = abs(total_1 - total_2)
if current_language == 'en':
question = f"What is the absolute difference between the number of {cat1_name} and {cat2_name} that I have?"
else:
question = f"我拥有的{cat1_name}和{cat2_name}的数量差的绝对值是多少?"
else: # 一个类别求总数
# 随机选择一个类别
cat = random.choice(my_categories)
# 计算这个类别的总数
total = sum(count for _, count, _ in possessions[i_pronoun][cat])
answer = total
# 使用正确的复数形式
cat_name = self.get_category_display_name(cat, current_language)
if current_language == 'en':
question = f"How many {cat_name} do I have in total?"
else:
question = f"我总共有多少个{cat_name}?"
elif len(my_categories) == 1:
# 只有一个类别,就问这个类别的总数
cat = my_categories[0]
total = sum(count for _, count, _ in possessions[i_pronoun][cat])
answer = total
# 使用正确的复数形式
cat_name = self.get_category_display_name(cat, current_language)
if current_language == 'en':
question = f"How many {cat_name} do I have in total?"
else:
question = f"我总共有多少个{cat_name}?"
else:
# 没有类别,出错了
raise ValueError("No categories with items assigned to me!")
# 随机选择一个对应语言的提示模板
if current_language == 'en':
prompt_template = random.choice(ENGLISH_PROMPTS)
else:
prompt_template = random.choice(CHINESE_PROMPTS)
# 用问题文本和问题替换提示模板中的占位符
formatted_prompt = prompt_template.format(context=problem_text, problem=question)
return formatted_prompt, str(answer), possessions, available_categories, current_language
def create_data_entry(self):
"""创建一个DATA"""
problem, answer, possessions, used_categories, language = self.generate_problem()
trace_id = uuid.uuid4()
return Data(
question=problem,
answer=answer,
difficulty=1,
metadata={
"possessions": possessions,
"used_categories": used_categories,
"language": language
}
)
def generate(self, num_of_questions: int = 100, max_attempts: int = 100):
"""生成多个问题并可选择性地写入文件"""
problems = []
for _ in range(num_of_questions):
problem_data = self.create_data_entry()
problems.append(problem_data)
return problems
def extract_answer(self, test_solution: str):
return self.verifier.extract_answer(test_solution)
def verify(self, data: Data, test_solution: str):
return self.verifier.verify(data, test_solution)
# 使用示例
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="物品计数游戏生成器")
parser.add_argument("--num_of_data", type=int, default=1000, help="生成的题目数量")
parser.add_argument("--max_attempts", type=int, default=1000, help="每个题目的最大尝试次数")
parser.add_argument("--min_sequence_length", type=int, default=3, help="故事中数字序列的最小长度")
parser.add_argument("--max_sequence_length", type=int, default=6, help="故事中数字序列的最大长度")
parser.add_argument("--min_count", type=int, default=5, help="生成的数字最小值")
parser.add_argument("--max_count", type=int, default=100, help="生成的数字最大值")
parser.add_argument("--min_my_items_per_category", type=int, default=2, help="我在每个类别中拥有的最少物品数")
parser.add_argument("--max_my_items_per_category", type=int, default=5, help="我在每个类别中拥有的最多物品数")
parser.add_argument("--min_categories", type=int, default=3, help="随机选择时的最小类别数")
parser.add_argument("--max_categories", type=int, default=7, help="随机选择时的最大类别数")
parser.add_argument("--language", type=str, choices=["en", "zh"], default="mixed", help="使用的语言,不指定则随机选择")
args = parser.parse_args()
# 创建数据目录
data_dir = pathlib.Path(__file__).parent.parent / "data"
if not data_dir.exists():
data_dir.mkdir(parents=True, exist_ok=True)
# 使用参数缩写构建文件名
language_suffix = f"_{args.language}" if args.language else "_mixed"
filename = f"data_sl{args.min_sequence_length}-{args.max_sequence_length}_ct{args.min_count}-{args.max_count}_cat{args.min_categories}-{args.max_categories}_mic{args.min_my_items_per_category}-{args.max_my_items_per_category}{language_suffix}_n{args.num_of_data}.jsonl"
output_file = data_dir / filename
# 创建游戏实例
game = ObjectCounting(
min_sequence_length=args.min_sequence_length,
max_sequence_length=args.max_sequence_length,
min_count=args.min_count,
max_count=args.max_count,
min_my_items_per_category=args.min_my_items_per_category,
max_my_items_per_category=args.max_my_items_per_category,
min_categories=args.min_categories,
max_categories=args.max_categories,
language=args.language
)
# 生成游戏数据
game_data_list = game.generate(
num_of_questions=args.num_of_data,
max_attempts=args.max_attempts
)
print(f"成功生成 {len(game_data_list)} 条游戏数据")
# 将数据保存到文件
try:
with open(output_file, "w", encoding="utf-8") as f:
for game_data in game_data_list:
f.write(json.dumps(game_data.to_json(), ensure_ascii=False) + "\n")
print(f"游戏数据已保存到 {output_file}")
except Exception as e:
print(f"保存数据时出错: {e}")