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

861 lines
40 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.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
import json
import os
import argparse
from pathlib import Path
import inflect
import uuid
from games.base.game import Game
from games.tasks.object_properties.scripts.object_properties_verifier import ObjectPropertiesVerifier
from games.tasks.object_properties.scripts.object_properties_prompt import *
from base.data import Data
import pathlib
"""
物品属性游戏生成器
生成包含多个属性的物品集合,并通过一系列变换后提出计数问题
"""
class ObjectProperties(Game):
def __init__(self, transformation_range=[2,3], feature_num=7, num_range=[10,15], language_type="mixed"):
super().__init__("object_properties", ObjectPropertiesVerifier)
self.transformation_low = transformation_range[0]
self.transformation_high = transformation_range[1]
self.feature_num = feature_num
self.num_low = num_range[0]
self.num_high = num_range[1]
self.language_type = language_type
# 物品属性
self.total_sizes = ["extra-extra-small", "extra-small", "small", "medium", "large", "extra-large", "extra-extra-large"]
self.total_sizes_cn = ["超超小", "超小", "小", "中", "大", "超大", "超超大"]
self.total_countries = ["Turkish", "German", "French", "Italian", "Japanese", "Chinese", "Russian", "British",
"Polish", "Brazilian", "Mexican", "Canadian", "Afghan", "Iranian", "Portuguese"]
self.total_countries_cn = ["土耳其", "德国", "法国", "意大利", "日本", "中国", "俄罗斯", "英国", "波兰", "巴西", "墨西哥", "加拿大", "阿富汗", "伊朗", "葡萄牙"]
self.items = ["pen", "ball", "ruler", "hammer", "shoe", "bag", "bicycle", "screwdriver", "book",
"umbrella", "key", "scissors", "fork", "speaker", "candle", "vase", "brush", "bird",
"pencil", "drill", "lamp", "bottle", "house", "bowl", "sunglasses", "earring", "clock",
"trash can", "plate", "chair"]
self.items_cn = ["笔", "球", "尺子", "锤子", "鞋", "包", "自行车", "螺丝刀", "书", "伞", "钥匙", "剪刀", "叉子", "扬声器", "蜡烛", "花瓶", "刷子", "鸟", "铅笔", "钻头", "灯", "瓶子", "房子", "碗", "太阳镜", "耳环", "钟", "垃圾桶", "盘子", "椅子"]
self.total_materials = ["plastic", "glass", "steel", "ceramic", "concrete","wood", "metal", "fabric", "leather", "paper", "rubber", "diamond", "gold", "silver", "platinum", "titanium"]
self.total_materials_cn = ["塑料", "玻璃", "钢", "陶瓷", "混凝土", "木头", "金属", "布", "皮革", "纸", "橡胶", "钻石", "金", "银", "铂金", "钛"]
self.total_smells = ["wet dog", "baking bread", "pine needles", "burning wood", "garlic", "vinegar",
"rose", "popcorn", "coconut", "vanilla", "coffee", "chocolate", "gasoline",
"citrus fruits", "lavender", "leather"]
self.total_smells_cn = ["湿狗", "烤面包", "松针", "燃烧的木头", "大蒜", "醋", "玫瑰", "爆米花", "椰子", "香草", "咖啡", "巧克力", "汽油", "柑橘", "薰衣草", "皮革"]
self.total_colors = ["beige", "black", "blue", "brown", "crimson", "cyan", "gold", "gray", "green",
"indigo", "magenta", "maroon", "orange", "purple", "red", "silver", "teal",
"turquoise", "violet", "white", "yellow"]
self.total_colors_cn = ["米色", "黑色", "蓝色", "棕色", "深红色", "青色", "金色", "灰色", "绿色", "靛蓝色", "品红色", "栗色", "橙色", "紫色", "红色", "银色", "青绿色", "绿松石色", "紫罗兰色", "白色", "黄色"]
self.person = ["my aunt", "my brother", "my sister", "my mom", "my fiance", "my cousin", "my neighbor"]
self.person_cn = ["我阿姨", "我哥哥", "我姐姐", "我妈妈", "我未婚夫", "我表亲", "我邻居"]
# 初始化inflect引擎
self.p = inflect.engine()
# 定义变化语料库
self.transformations = [
{
"description": "Then, for each item of size {sizes} in my collection, {person} took it but then gave me another one of the same item made of her favorite material {new_materials} and with a smell of {new_smells} (all other properties the same).",
"description_cn": "然后,对于我收藏中每一个尺寸为{sizes}的物品,{person}拿走了它,但又给了我同样物品的另一个版本,材质是{new_materials},气味是{new_smells}(其他属性相同)。",
"apply": self.aunt_transform
},
{
"description": "Then, {person} replaced any item of size {sizes} in my new collection with an exact copy but with size {new_sizes} and another exact copy but with color {new_colors}.",
"description_cn": "然后,{person}用两个副本替换了我新收藏中所有尺寸为{sizes}的物品,一个副本尺寸变为{new_sizes},另一个副本颜色变为{new_colors}。",
"apply": self.brother_transform
},
{
"description": "Then, for any item made of {materials} in my new collection, {person} changed their color to {new_colors} and changed their smell to {new_smells}.",
"description_cn": "然后,对于我新收藏中所有由{materials}制成的物品,{person}将它们的颜色改为{new_colors},气味改为{new_smells}。",
"apply": self.sister_transform
},
{
"description": "Then, for any item of color {colors} in my new collection, {person} gave me another one of the same item, but with color {new_colors}, {new_countries} origin, {new_sizes} size, {new_smells} smell, and made of {new_materials}.",
"description_cn": "然后,对于我新收藏中所有颜色为{colors}的物品,{person}给了我同样物品的另一个版本,但颜色是{new_colors},产地是{new_countries},尺寸是{new_sizes},气味是{new_smells},材质是{new_materials}。",
"apply": self.mom_transform
},
{
"description": "Then, {person} compared my new collection with my initial collection and if there was an item in my new collection with a (smell, color) pair that was different from all items in my initial collection, she added another copy of that to my new collection.",
"description_cn": "然后,{person}比较了我的新收藏和初始收藏,如果在我的新收藏中有一个物品的(气味,颜色)组合与初始收藏中所有物品都不同,她就在我的新收藏中添加了该物品的另一个副本。",
"apply": self.fiance_transform
},
{
"description": "Then, I lost all of the {sizes} items in my collection.",
"description_cn": "然后,我丢失了收藏中所有尺寸为{sizes}的物品。",
"apply": self.lost_item_transform
},
{
"description": "Then, {person} picked all {colors} item and changed its material to {new_materials}.",
"description_cn": "然后,{person}挑选了所有{colors}颜色的物品,并将它们的材质改为{new_materials}。",
"apply": self.cousin_transform
},
{
"description": "Then, {person} traded me all items of {countries} origin for the same number of items with {new_sizes} size and {new_materials} material.",
"description_cn": "然后,{person}用同等数量的尺寸为{new_sizes}、材质为{new_materials}的物品,交换了我收藏中所有{countries}产地的物品。",
"apply": self.neighbor_transform
},
{
"description": "Then, for every item with {smells} smell, I decided to add a twin item but with {new_colors} color instead.",
"description_cn": "然后,对于每一个气味为{smells}的物品,我决定添加一个副本物品,但颜色改为{new_colors}。",
"apply": self.twin_item_transform
},
{
"description": "Then, I accidentally spilled paint on all my {sizes} items, changing their colors to {new_colors}.",
"description_cn": "然后,我不小心在所有尺寸为{sizes}的物品上洒了颜料,将它们的颜色变成了{new_colors}。",
"apply": self.spill_paint_transform
}
]
def aunt_transform(self, collection, original_collection, params):
"""阿姨替换物品"""
size = params["sizes"]
material = params["new_materials"]
smell = params["new_smells"]
for i, item in enumerate(collection):
if item["sizes"] == size:
collection[i]["materials"] = material
collection[i]["smells"] = smell
return collection
def brother_transform(self, collection, original_collection, params):
"""兄弟替换物品"""
size = params["sizes"]
new_size = params["new_sizes"]
color = params["new_colors"]
# 找出所有指定尺寸的物品
size_items = []
for i, item in enumerate(collection):
if item["sizes"] == size:
size_items.append(item.copy())
item["sizes"] = new_size
# 添加新颜色的副本
for item in size_items:
color_copy = item.copy()
color_copy["colors"] = color
collection.append(color_copy)
return collection
def sister_transform(self, collection, original_collection, params):
"""姐姐改变特定材质物品"""
material = params["materials"]
color = params["new_colors"]
smell = params["new_smells"]
for item in collection:
if item["materials"] == material:
item["colors"] = color
item["smells"] = smell
return collection
def mom_transform(self, collection, original_collection, params):
"""妈妈添加特定物品"""
color = params["colors"]
new_color = params["new_colors"]
origin = params["new_countries"]
size = params["new_sizes"]
smell = params["new_smells"]
material = params["new_materials"]
items_to_copy = []
for item in collection:
if item["colors"] == color:
items_to_copy.append(item)
for item in items_to_copy:
new_item = item.copy()
new_item["colors"] = new_color
new_item["countries"] = origin
new_item["sizes"] = size
new_item["smells"] = smell
new_item["materials"] = material
collection.append(new_item)
return collection
def fiance_transform(self, collection, original_collection, params):
"""未婚夫比较添加"""
# 获取原始集合中所有的(smell, color)对
original_smell_color_pairs = set()
for item in original_collection:
original_smell_color_pairs.add((item["smells"], item["colors"]))
# 检查新集合中的(smell, color)对,如果是新的,添加副本
items_to_add = []
for item in collection:
if (item["smells"], item["colors"]) not in original_smell_color_pairs:
items_to_add.append(item.copy())
collection.extend(items_to_add)
return collection
def lost_item_transform(self, collection, original_collection, params):
"""丢失所有特定尺寸物品"""
size = params["sizes"]
new_collections = [item for item in collection if item["sizes"] != size]
return new_collections
def cousin_transform(self, collection, original_collection, params):
"""表亲改变特定颜色物品的材质"""
color = params["colors"]
material = params["new_materials"]
for item in collection:
if item["colors"] == color:
item["materials"] = material
return collection
def neighbor_transform(self, collection, original_collection, params):
"""邻居交换物品"""
origin = params["countries"]
size = params["new_sizes"]
material = params["new_materials"]
# 找出所有具有特定原产地的物品
origin_items = [i for i, item in enumerate(collection) if item["countries"] == origin]
num_to_replace = len(origin_items)
# 移除这些物品
origin_items.sort(reverse=True) # 从后往前删除,避免索引问题
for idx in origin_items:
collection.pop(idx)
# 添加新物品
for _ in range(num_to_replace):
new_item = {
"sizes": size,
"countries": random.choice(self.countries),
"name": random.choice(self.items),
"materials": material,
"smells": random.choice(self.smells),
"colors": random.choice(self.colors)
}
collection.append(new_item)
return collection
def twin_item_transform(self, collection, original_collection, params):
"""为特定气味的物品添加双胞胎"""
smell = params["smells"]
color = params["new_colors"]
items_to_twin = []
for item in collection:
if item["smells"] == smell:
items_to_twin.append(item)
for item in items_to_twin:
twin = item.copy()
twin["colors"] = color
collection.append(twin)
return collection
def spill_paint_transform(self, collection, original_collection, params):
"""颜料洒落事件"""
size = params["sizes"]
color = params["new_colors"]
for item in collection:
if item["sizes"] == size:
item["colors"] = color
return collection
def generate_initial_collection(self, num_items=42):
"""生成初始物品集合"""
collection = []
# 随机选择一个要单独分配的属性
attributes = ["sizes", "colors", "countries", "materials", "smells"]
special_attribute = random.choice(attributes)
# 为每个物品随机分配非特殊属性
for _ in range(num_items):
item = {}
for attr in attributes:
if attr != special_attribute:
attr_list = getattr(self, attr)
item[attr] = random.choice(attr_list)
else:
item[attr] = None
# 单独分配名称属性
item["name"] = random.choice(self.items)
collection.append(item)
# 获取特殊属性的可用值列表
attr_values = getattr(self, special_attribute)
# 随机决定要分配的不同值的数量(3-7个不同的值)
num_distinct_values = random.randint(3, min(self.feature_num, len(attr_values)))
# 随机选择要使用的值
selected_values = random.sample(attr_values, num_distinct_values)
# 生成分割点
total_items = len(collection)
# 生成(值数量-1)个分割点
split_points = sorted(random.sample(range(1, total_items), num_distinct_values - 1))
split_points = [0] + split_points + [total_items]
# 为每段分配相同的值
for i in range(num_distinct_values):
start = split_points[i]
end = split_points[i+1]
current_value = selected_values[i]
for j in range(start, end):
collection[j][special_attribute] = current_value
return collection, special_attribute
def count2str(self, count):
count_dic = {
1:"one",
2:"two",
3:"three",
4:"four",
5:"five",
6:"six",
7:"seven",
8:"eight",
9:"nine",
10:"ten",
11:"eleven",
12:"twelve",
13:"thirteen",
14:"fourteen",
15:"fifteen",
16:"sixteen",
17:"seventeen",
18:"eighteen",
19:"nineteen",
20:"twenty",
21:"twenty-one",
22:"twenty-two",
23:"twenty-three",
24:"twenty-four",
25:"twenty-five",
26:"twenty-six",
27:"twenty-seven",
28:"twenty-eight",
29:"twenty-nine",
30:"thirty",
31:"thirty-one",
32:"thirty-two",
33:"thirty-three",
34:"thirty-four",
35:"thirty-five",
36:"thirty-six",
37:"thirty-seven",
38:"thirty-eight",
39:"thirty-nine",
40:"forty",
}
return count_dic[count]
def count2str_cn(self, count):
count_dic = {
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:"四十",
}
return count_dic[count]
def describe_collection_changes(self, original_collection, special_attribute,language):
"""描述集合的变化过程,并返回最终集合和问题"""
# 复制原始集合以进行修改
collection = [item.copy() for item in original_collection]
# 记录变化过程的描述
story = []
if language == "english":
story.append(f"I had a collection of {len(collection)} weird items that went through a few changes. Initially, I had ")
else: # 中文
story.append(f"我有一个包含{len(collection)}个奇怪物品的收藏,经历了几次变化。最初,我有")
# 描述初始集合
items_desc = []
for item in collection:
if language == "english":
desc = ""
for key, value in item.items():
if key != special_attribute and key != "name":
if key == "materials":
desc += f"made of {value} "
elif key == "smells":
sub_desc = [f'with a smell of {value} ', f'smelled like {value} ']
desc += random.choice(sub_desc)
elif key == "countries":
desc += f"from {value} "
else:
desc += f"{value} "
desc += item["name"]
desc = self.p.a(desc)
items_desc.append(desc)
else: # 中文
desc = ""
for key, value in item.items():
if key != special_attribute and key != "name":
if key == "materials":
desc += f"由{value}制成的"
elif key == "smells":
desc += f"散发{value}气味的"
elif key == "countries":
desc += f"{value}产的"
elif key == "colors":
desc += f"{value}的"
elif key == "sizes":
desc += f"{value}尺寸的"
desc += item["name"]
items_desc.append(f"一个{desc}")
if language == "english":
story.append(", ".join(items_desc) + ".")
else: # 中文
story.append(",".join(items_desc) + "。")
# 描述特殊属性分布
attribute_count = {}
for item in collection:
attr_value = item[special_attribute]
if attr_value in attribute_count:
attribute_count[attr_value] += 1
else:
attribute_count[attr_value] = 1
# 描述特殊属性的分布
if language == "english":
special_attr_descriptors = {
"sizes": "The size of the items was respectively as follows: ",
"countries": "The origin of the items was respectively as follows: ",
"materials": "The material of the items was respectively as follows: ",
"smells": "The smell of the items was respectively as follows: ",
"colors": "The color of the items was respectively as follows: "
}
story.append(special_attr_descriptors[special_attribute])
else: # 中文
special_attr_descriptors = {
"sizes": "这些物品的尺寸依次如下:",
"countries": "这些物品的产地依次如下:",
"materials": "这些物品的材质依次如下:",
"smells": "这些物品的气味依次如下:",
"colors": "这些物品的颜色依次如下:"
}
story.append(special_attr_descriptors[special_attribute])
# 构建每个值的描述
attribute_desc = []
current_count = 0
for value, count in attribute_count.items():
if language == "english":
if special_attribute == "materials":
value_text = f"made of {value}"
elif special_attribute == "smells":
value_text = f"smelled like {value}"
elif special_attribute == "countries":
value_text = f"from {value}"
else:
value_text = value
count_str = self.count2str(count)
if current_count == 0:
if count == 1:
attribute_desc.append(f"the first {count_str} was {value_text}")
else:
attribute_desc.append(f"the first {count_str} were {value_text}")
else:
if count == 1:
attribute_desc.append(f"the next {count_str} was {value_text}")
else:
attribute_desc.append(f"the next {count_str} were {value_text}")
else: # 中文
if special_attribute == "materials":
value_text = f"由{value}制成"
elif special_attribute == "smells":
value_text = f"散发{value}气味"
elif special_attribute == "countries":
value_text = f"来自{value}"
else:
value_text = value
count_str = self.count2str_cn(count)
if current_count == 0:
attribute_desc.append(f"前{count_str}个是{value_text}")
else:
attribute_desc.append(f"接下来的{count_str}个是{value_text}")
current_count += count
if language == "english":
story.append(", ".join(attribute_desc) + ".")
else: # 中文
story.append(",".join(attribute_desc) + "。")
# 随机选择2-5个变化
num_transformations = random.randint(self.transformation_low, self.transformation_high)
selected_transformations = random.sample(self.transformations, num_transformations)
# 应用每个变化并添加到故事中
for transformation in selected_transformations:
# 为变化准备参数
now_sizes = random.choice(list(set([item["sizes"] for item in collection])))
now_colors = random.choice(list(set([item["colors"] for item in collection])))
now_materials = random.choice(list(set([item["materials"] for item in collection])))
now_smells = random.choice(list(set([item["smells"] for item in collection])))
now_countries = random.choice(list(set([item["countries"] for item in collection])))
new_sizes = random.choice([s for s in self.sizes if s != now_sizes])
new_materials = random.choice([m for m in self.materials if m != now_materials])
new_colors = random.choice([c for c in self.colors if c != now_colors])
new_smells = random.choice([s for s in self.smells if s != now_smells])
new_countries = random.choice([c for c in self.countries if c != now_countries])
if language == "english":
person = random.choice(self.person)
desc_key = "description"
else: # 中文
person = random.choice(self.person_cn)
desc_key = "description_cn"
params = {
"sizes": now_sizes,
"colors": now_colors,
"materials": now_materials,
"smells": now_smells,
"countries": now_countries,
"person": person,
"new_sizes": new_sizes,
"new_materials": new_materials,
"new_colors": new_colors,
"new_smells": new_smells,
"new_countries": new_countries,
}
# 格式化描述并添加到故事
description = transformation[desc_key].format(**params)
story.append(description + " ")
# 应用变化到集合
collection = transformation["apply"](collection, original_collection, params)
# 选择性添加状态描述
if random.random() < 0.3: # 30%的概率添加状态描述
if language == "english":
if "materials" in params:
# 统计材料分布
material_count = {}
for item in collection:
material = item["materials"]
if material in material_count:
material_count[material] += 1
else:
material_count[material] = 1
material_desc = []
for material, count in material_count.items():
material_desc.append(f"{count} item(s) made of {material}")
story.append("After this, my collection had: " + ", ".join(material_desc) + ". ")
elif "sizes" in params:
# 统计尺寸分布
size_count = {}
for item in collection:
size = item["sizes"]
if size in size_count:
size_count[size] += 1
else:
size_count[size] = 1
size_desc = []
for size, count in size_count.items():
size_desc.append(f"{count} {size} item(s)")
story.append("After this, my collection had: " + ", ".join(size_desc) + ". ")
elif "colors" in params:
# 统计颜色分布
color_count = {}
for item in collection:
color = item["colors"]
if color in color_count:
color_count[color] += 1
else:
color_count[color] = 1
color_desc = []
for color, count in color_count.items():
color_desc.append(f"{count} {color} item(s)")
story.append("After this, my collection had: " + ", ".join(color_desc) + ". ")
else: # 中文
if "materials" in params:
# 统计材料分布
material_count = {}
for item in collection:
material = item["materials"]
if material in material_count:
material_count[material] += 1
else:
material_count[material] = 1
material_desc = []
for material, count in material_count.items():
material_desc.append(f"{count}个由{material}制成的物品")
story.append("在此之后,我的收藏有:" + ",".join(material_desc) + "。")
elif "sizes" in params:
# 统计尺寸分布
size_count = {}
for item in collection:
size = item["sizes"]
if size in size_count:
size_count[size] += 1
else:
size_count[size] = 1
size_desc = []
for size, count in size_count.items():
size_desc.append(f"{count}个{size}尺寸的物品")
story.append("在此之后,我的收藏有:" + ",".join(size_desc) + "。")
elif "colors" in params:
# 统计颜色分布
color_count = {}
for item in collection:
color = item["colors"]
if color in color_count:
color_count[color] += 1
else:
color_count[color] = 1
color_desc = []
for color, count in color_count.items():
color_desc.append(f"{count}个{color}色物品")
story.append("在此之后,我的收藏有:" + ",".join(color_desc) + "。")
# 生成问题
now_sizes = random.choice(list(set([item["sizes"] for item in collection])))
now_colors = random.choice(list(set([item["colors"] for item in collection])))
now_materials = random.choice(list(set([item["materials"] for item in collection])))
now_smells = random.choice(list(set([item["smells"] for item in collection])))
now_countries = random.choice(list(set([item["countries"] for item in collection])))
attribute_num = random.randint(2, 5)
# 抽取特征
attributes = ["sizes", "colors", "materials", "smells", "countries"]
random.shuffle(attributes)
question_attribute = attributes[:attribute_num]
selected_attributes = []
if language == "english":
for attr in question_attribute:
if attr == "sizes":
selected_attributes.append(f"size is {now_sizes}")
elif attr == "colors":
selected_attributes.append(f"color is {now_colors}")
elif attr == "materials":
selected_attributes.append(f"material is {now_materials}")
elif attr == "smells":
selected_attributes.append(f"smell is {now_smells}")
elif attr == "countries":
selected_attributes.append(f"origin is {now_countries}")
question = f"In my current collection, how many items have the following attributes: either {' or '.join(selected_attributes)}? If the exact number cannot be computed, the answer must be \"unknown\"."
else: # 中文
for attr in question_attribute:
if attr == "sizes":
selected_attributes.append(f"尺寸是{now_sizes}")
elif attr == "colors":
selected_attributes.append(f"颜色是{now_colors}")
elif attr == "materials":
selected_attributes.append(f"材质是{now_materials}")
elif attr == "smells":
selected_attributes.append(f"气味是{now_smells}")
elif attr == "countries":
selected_attributes.append(f"产地是{now_countries}")
question = f"在我当前的收藏中,有多少物品具有以下属性:{'或'.join(selected_attributes)}?"
# 计算答案
answer = 0
for item in collection:
matches = False
for attr in question_attribute:
if attr == "sizes" and item["sizes"] == now_sizes:
matches = True
break
elif attr == "colors" and item["colors"] == now_colors:
matches = True
break
elif attr == "materials" and item["materials"] == now_materials:
matches = True
break
elif attr == "smells" and item["smells"] == now_smells:
matches = True
break
elif attr == "countries" and item["countries"] == now_countries:
matches = True
break
if matches:
answer += 1
# 合并故事
full_story = "".join(story)
return {
"story": full_story,
"question": question,
"answer": str(answer),
"initial_collection": original_collection,
"final_collection": collection
}
def generate(self, num_of_questions: int = 100, max_attempts: int = 100):
"""生成示例问题和答案"""
outputs = []
for i in range(num_of_questions):
if self.language_type == "mixed":
language = random.choice(["english", "chinese"])
else:
language = self.language_type
if language == "english":
self.colors = random.sample(self.total_colors, min(self.feature_num, len(self.total_colors)))
self.sizes = random.sample(self.total_sizes, min(self.feature_num, len(self.total_sizes)))
self.materials = random.sample(self.total_materials, min(self.feature_num, len(self.total_materials)))
self.smells = random.sample(self.total_smells, min(self.feature_num, len(self.total_smells)))
self.countries = random.sample(self.total_countries, min(self.feature_num, len(self.total_countries)))
else:
self.colors = random.sample(self.total_colors_cn, min(self.feature_num, len(self.total_colors_cn)))
self.sizes = random.sample(self.total_sizes_cn, min(self.feature_num, len(self.total_sizes_cn)))
self.materials = random.sample(self.total_materials_cn, min(self.feature_num, len(self.total_materials_cn)))
self.smells = random.sample(self.total_smells_cn, min(self.feature_num, len(self.total_smells_cn)))
self.countries = random.sample(self.total_countries_cn, min(self.feature_num, len(self.total_countries_cn)))
self.items = random.sample(self.items_cn, min(self.feature_num, len(self.items_cn)))
num_items = random.randint(self.num_low, self.num_high)
initial_collection, special_attribute = self.generate_initial_collection(num_items)
result = self.describe_collection_changes(initial_collection, special_attribute,language)
if language == "english":
prompt = random.choice(en_prompts).format(context=result["story"], problem=result["question"])
else:
prompt = random.choice(cn_prompts).format(context=result["story"], problem=result["question"])
outputs.append(Data(
question=prompt,
answer=result["answer"],
difficulty=1,
metadata={
"story": result["story"],
"question": result["question"],
"answer": result["answer"],
"initial_collection": result["initial_collection"],
"final_collection": result["final_collection"],
"language": language
}
))
return outputs
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_range", type=int, nargs=2, default=[10, 15], help="初始物品数量范围")
parser.add_argument("--feature_num", type=int, default=7, help="特征数量")
parser.add_argument("--transformation_range", type=int, nargs=2, default=[2, 3], help="变换数量范围")
parser.add_argument("--language", type=str, default="mixed", choices=["english", "chinese", "mixed"], help="语言")
parser.add_argument("--num_of_data", type=int, default=1000, help="生成数据数量")
parser.add_argument("--max_attempts", type=int, default=100, help="最大尝试次数")
parser.add_argument("--output", type=str, default="test", help="输出文件路径")
args = parser.parse_args()
# 创建游戏实例
game = ObjectProperties(
feature_num=args.feature_num,
transformation_range=args.transformation_range,
num_range=args.num_range,
language_type=args.language
)
# 生成游戏数据
game_data_list = game.generate(
num_of_questions=args.num_of_data,
max_attempts=args.max_attempts
)
# 创建数据目录
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_fp{args.feature_num}_nr{args.num_range[0]}-{args.num_range[1]}_nt{args.transformation_range[0]}-{args.transformation_range[1]}{language_suffix}_n{args.num_of_data}.jsonl"
output_file = data_dir / filename
print(f"成功生成 {len(game_data_list)} 条游戏数据")
# 将数据保存到文件
with open(output_file, 'w', encoding='utf-8') as f:
for data in game_data_list:
f.write(json.dumps(data.__dict__, ensure_ascii=False) + '\n')
print(f"数据已保存到 {output_file}")