Spaces:
Runtime error
Runtime error
File size: 14,096 Bytes
6713bb5 8092a80 6ff4e0e 6713bb5 1e06d5b |
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
import os
os.system('pip install dashscope')
os.system('pip install sympy')
os.system('pip install "gradio==3.40.1"')
import gradio as gr
import random
from http import HTTPStatus
import dashscope
import sympy
import re
dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')
# 定义关卡信息和验证逻辑
# 辅助函数 - 检查是否为质数
def is_prime(num):
return sympy.isprime(num)
# 辅助函数 - 获取下一个质数
def next_prime(num):
return sympy.nextprime(num)
# 辅助函数 - 检查是否为平方数
def is_square(n):
return sympy.sqrt(n).is_integer
# 辅助函数 - 获取平方根
def get_square_root(n):
return int(sympy.sqrt(n))
def validate_palindrome_invariance(origin_input, response):
"""
验证器函数,检查对于给定的问题,正着问和倒着问的模型回答是否一致。
:param origin_input: 原始问题
:return: True 如果回答一致,否则 False
"""
# 将原始问题倒序并提交
reversed_question = origin_input[::-1]
reversed_response = generate_response(reversed_question)
# 比较两个回答是否一致
return response.strip() == reversed_response.strip()
def validate_palindrome_inverse(origin_input, response):
"""
验证器函数,检查对于给定的问题,正着问和倒着问的模型的回答本身不回文且也是逆序的关系。
:param origin_input: 原始问题
:param response: 模型对原始问题的回答
:param model_fn: 能够返回模型回答的函数
:return: True 如果回答本身不回文且也是逆序关系,否则 False
"""
# 检查原始输入不是回文
if origin_input == origin_input[::-1]:
return False
# 将原始问题倒序并获取模型回答
reversed_question = origin_input[::-1]
reversed_response = generate_response(reversed_question).strip()
# 检查原始回答不是回文
if response == response[::-1]:
return False
# 比较正着问和倒着问的回答是否是逆序关系
return response == reversed_response[::-1]
def validate_reciprocal_question(input, response):
"""
验证器函数,检查给定的问题A和回答B,是否能够通过以B作为新的提问得到原始问题A作为回答。
:param response: 模型对问题A的回答B
:param input: 原始问题A
:param model_fn: 模型调用函数,接收问题并返回回答
:return: True 如果以回答B作为新的提问能得到问题A作为回答,否则 False
"""
# 确保回答B不等于原始问题A
if response == input:
return False
# 以回答B作为新的提问
new_response = generate_response(response)
# 检查新的回答是否与原始问题A相等
return new_response.strip() == input.strip()
challenges = [
{
"name": "第一章 对话之趣",
"problems": [
{
"title": "第1题 初来乍到",
"description": "请你构造一个问题使模型的回答是一字不差的“1+1=3”(不需要引号)。",
"validator": lambda response, input: response.strip() == "1+1=3"
},
{
"title": "第2题 小试牛刀",
"description": "请输入三个字以内的问题,使模型的回答在30个字以上。",
"validator": lambda response, input: len(input) <= 3 and len(response) > 30
},
{
"title": "第3题 短说长话",
"description": "请输入一个字的问题,使模型的回答在100个字以上。",
"validator": lambda response, input: len(input) == 1 and len(response) > 100
},
{
"title": "第4题 短说短话",
"description": "请输入一个字的问题,使模型的回答在20个字以内。",
"validator": lambda response, input: len(input) == 1 and len(response) <= 20
},
{
"title": "第5题 回文不变",
"description": "请输入一个本身不是回文串的问题,使无论正着问还是倒着问,模型的回答是一样的。",
# 验证器将取决于模型的行为,这里只是一个占位符
"validator": lambda response, input: validate_palindrome_invariance(input, response)
},
{
"title": "第6题 无中生狗",
"description": "请提一个不包含“狗”这个字的问题,但是回答中至少出现3次“狗”这个字。",
"validator": lambda response, input: "狗" not in input and response.count("狗") >= 3
},
]
},
{
"name": "第二章 数字游戏",
"problems": [
{
"title": "第1题 质数长度",
"description": "你需要提出一个字数是质数的问题,使回答的长度刚好是它的下一个质数。",
"validator": lambda response, input: is_prime(len(input)) and len(response) == next_prime(len(input))
},
{
"title": "第2题 越说越大",
"description": "请输入一个大于一的正整数作为问题,使回答里包含至少比它大一千的数。",
"validator": lambda response, input: input.isdigit() and int(input) > 1 and any(int(num) > int(input) + 1000 for num in re.findall(r'\d+', response))
},
{
"title": "第3题 越说越小",
"description": "请输入一个大于一的正整数作为问题,使回答里包含至少10个不同的至少比它小一千的自然数。",
"validator": lambda response, input: input.isdigit() and int(input) > 1 and (len({int(num) for num in re.findall(r'\d+', response) if int(num) < int(input) - 1000}) >= 10)
},
{
"title": "第4题 警世名言",
"description": "请在不提及1,4,5这三个字符的情况下让模型回答114514,不要有多余的字符。",
"validator": lambda response, input: response.strip() == "114514" and all(c not in input for c in ["1", "4", "5"])
},
{
"title": "第5题 开平方数",
"description": "请输入一个大于一的平方数作为问题,使回答里包含它的平方根对应的数。",
"validator": lambda response, input: input.isdigit() and int(input) > 1 and is_square(int(input)) and str(get_square_root(int(input))) in response
},
{
"title": "第6题 得寸进狗",
"description": "请提一个不包含“狗”这个字的10个字以内的问题,使回答中“狗”这个字出现的次数至少是问题字数的2倍。",
"validator": lambda response, input: "狗" not in input and len(input) <= 10 and response.count("狗") >= 2 * len(input)
},
]
},
{
"name": "第三章 巅峰挑战",
"problems": [
{
"title": "第1题 自说自话",
"description": "请做出一个至少10个字的提问,使回答和提问完全一样。",
"validator": lambda response, input: input == response and len(input) >= 10
},
{
"title": "第2题 话自说自",
"description": "请做出一个至少10个字的提问,使回答是提问的逆序。",
"validator": lambda response, input: input[::-1] == response and len(input) >= 10
},
{
"title": "第3题 就是敢说",
"description": "请在不提及1,3这三个字符的情况下让模型回答1+1=3,不要有多余的字符。",
"validator": lambda response, input: response.strip() == "1+1=3" and all(c not in input for c in ["1", "3"])
},
{
"title": "第4题 回文协变",
"description": "请输入一个本身不是回文串的问题,使正着问和倒着问的时候,模型的回答本身不回文且也是逆序的关系。",
"validator": lambda response, input: validate_palindrome_inverse(input, response)
},
]
},
{
"name": "第四章 无人之境",
"problems": [
{
"title": "第1题 循环往复",
"description": "请构造一个问题A,它的回复是不同于A的B,然后以B提问能再次得到A.",
"validator": lambda response, input: validate_reciprocal_question(input, response)
},
{
"title": "第2题 惜字如金",
"description": "请输入一个字的问题,使模型的回答在16个字以内。",
"validator": lambda response, input: len(input) == 1 and len(response) <= 16
},
{
"title": "第3题 自然之密",
"description": "请输入一个大于一的正整数作为问题,使回答里包含和它刚好相差1的数。",
"validator": lambda response, input: input.isdigit() and int(input) > 1 and any(abs(int(num) - int(input)) == 1 for num in re.findall(r'\d+', response))
},
]
}
]
def get_problem(challenge_idx, problem_idx):
problems = challenges[challenge_idx]['problems']
return problems[problem_idx]
def update_challenge_info(current_chapter_index, current_challenge_index):
return get_problem(current_chapter_index, current_challenge_index)["description"]
def update_question_info(current_chapter_index, current_challenge_index):
global challenges
current_chapter = challenges[current_chapter_index]
challenge = get_problem(current_chapter_index, current_challenge_index)
question_info = f"""\n<center><font size=4>{current_chapter["name"]}</center>\n\n <center><font size=3>{challenge["title"]}</center>"""
return question_info
def validate_challenge(response, input, state):
print('in validate_challenge')
assert 'current_chapter_index' in state, 'current_chapter_index not found in state'
assert 'current_challenge_index' in state, 'current_challenge_index not found in state'
current_chapter_index = state['current_chapter_index']
current_challenge_index = state['current_challenge_index']
# 获取当前章节
current_chapter = challenges[current_chapter_index]
# 获取当前挑战
challenge = current_chapter["problems"][current_challenge_index]
if challenge["validator"](response, input):
challenge_result = "挑战成功!进入下一关。"
# 检查是否还有更多挑战在当前章节
if current_challenge_index < len(current_chapter["problems"]) - 1:
# 移动到当前章节的下一个挑战
current_challenge_index += 1
else:
# 如果当前章节的挑战已经完成,移动到下一个章节
current_challenge_index = 0
if current_chapter_index < len(challenges) - 1:
current_chapter_index += 1
else:
challenge_result = "所有挑战完成!"
else:
challenge_result = "挑战失败,请再试一次。"
state['current_chapter_index'] = current_chapter_index
state['current_challenge_index'] = current_challenge_index
print('update state: ', state)
return challenge_result, \
update_question_info(current_chapter_index, current_challenge_index), \
update_challenge_info(current_chapter_index, current_challenge_index)
def generate_response(input):
messages = [{'role': 'system', 'content': """You are a helpful assistant."""},
{'role': 'user', 'content': input}]
response = dashscope.Generation.call(
model='qwen-max',
messages=messages,
# set the random seed, optional, default to 1234 if not set
seed=random.randint(1, 10000),
result_format='message', # set the result to be "message" format.
top_p = 0.8
)
if response.status_code == HTTPStatus.OK:
return response.output.choices[0].message.content
else:
gr.Error("网络连接错误,请重试。")
def on_submit(input, state):
response = generate_response(input)
history = [(input,response)]
print(history)
challenge_result, question_info, challenge_info = validate_challenge(response, input, state)
print('validate_challenge done')
return challenge_result, history, question_info, challenge_info
# Gradio界面构建
block = gr.Blocks()
with block as demo:
state = gr.State(dict(current_challenge_index=0,
current_chapter_index=0))
current_chapter_index = 0
current_challenge_index = 0
gr.Markdown("""<center><font size=6>完蛋!我被LLM包围了!</center>""")
gr.Markdown("""<font size=3>欢迎来玩LLM Riddles复刻版:完蛋!我被LLM包围了!
你将通过本游戏对大型语言模型产生更深刻的理解。
在本游戏中,你需要构造一个提给一个大型语言模型的问题,使得它回复的答案符合要求。""")
question_info = gr.Markdown(update_question_info(current_chapter_index, current_challenge_index))
challenge_info = gr.Textbox(value=update_challenge_info(current_chapter_index, current_challenge_index), label="当前挑战", disabled=True)
challenge_result = gr.Textbox(label="挑战结果", disabled=True)
chatbot = gr.Chatbot(lines=8, label='Qwen-max', elem_classes="control-height")
message = gr.Textbox(lines=2, label='输入')
with gr.Row():
submit = gr.Button("🚀 发送")
submit.click(on_submit, inputs=[message, state], outputs=[challenge_result, chatbot, question_info, challenge_info])
demo.queue().launch(height=800, share=False) |