wow agent day11 Zigent实现出题智能体

Reference：Datawhale wow agent day11

实现内容

本节课我们将通过 Zigent 框架实现一个出题智能体，其主要功能是根据指定的 Markdown 文件内容自动生成考卷。该智能体支持单选题、多选题和填空题三种题型，并能将生成的考卷保存为 Markdown 文件。

设计思路

出题智能体的核心功能包括：

从指定目录加载 Markdown 文件作为知识来源

根据用户指定的受众群体和考察目的生成考卷

支持多种题型（单选题、多选题、填空题）

自动保存生成的考卷并返回结果路径

代码实现

定义出题 Action

定义 QuizGenerationAction 类，负责生成考卷题目：

Copy
class QuizGenerationAction(BaseAction):
"""Generate quiz questions from markdown content"""
def __init__(self, llm: LLM) -> None:
action_name = "GenerateQuiz"
action_desc = "Generate quiz questions from markdown content"
params_doc = {
"content": "(Type: string): The markdown content to generate questions from",
"question_types": "(Type: list): List of question types to generate",
"audience": "(Type: string): Target audience for the quiz",
"purpose": "(Type: string): Purpose of the quiz"
}
super().__init__(action_name, action_desc, params_doc)
self.llm = llm

def __call__(self, **kwargs):
content = kwargs.get("content", "")
question_types = kwargs.get("question_types", [])
audience = kwargs.get("audience", "")
purpose = kwargs.get("purpose", "")

prompt = f"""
你是一个辅助设计考卷的机器人,全程使用中文。
你的任务是帮助用户快速创建、设计考卷，考卷以markdown格式给出。

要求：
1. 受众群体：{audience}
2. 考察目的：{purpose}
3. 需要包含以下题型：{", ".join(question_types)}
4. 考卷格式要求：
"""
prompt += """
# 问卷标题
---
1. 这是判断题的题干?
- (x) True
- ( ) False
# (x)为正确答案

2. 这是单选题的题干
- (x) 这是正确选项
- ( ) 这是错误选项
# (x)为正确答案

3. 这是多选题的题干?
- [x] 这是正确选项1
- [x] 这是正确选项2
- [ ] 这是错误选项1
- [ ] 这是错误选项2
# [x]为正确答案

4. 这是填空题的题干?
- R:= 填空题答案
#填空题正确答案格式
"""

prompt += f"\n请根据以下内容生成考卷：\n{content}"

quiz_content = self.llm.run(prompt)
return {
"quiz_content": quiz_content,
"audience": audience,
"purpose": purpose,
"question_types": question_types
}

定义保存 Action

定义 SaveQuizAction 类，负责保存生成的考卷：

Copy
class SaveQuizAction(BaseAction):
"""Save quiz to file and return URL"""
def __init__(self) -> None:
action_name = "SaveQuiz"
action_desc = "Save quiz content to file and return URL"
params_doc = {
"quiz_content": "(Type: string): The quiz content to save",
"quiz_title": "(Type: string): Title of the quiz"
}
super().__init__(action_name, action_desc, params_doc)

def __call__(self, **kwargs):
quiz_content = kwargs.get("quiz_content", "")
quiz_title = kwargs.get("quiz_title", "quiz")

output_dir = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
os.makedirs(output_dir, exist_ok=True)

output_file = os.path.join(output_dir, f"{quiz_title}.md")
with open(output_file, 'w', encoding='utf-8') as f:
f.write(quiz_content)

return {
"file_path": output_file,
"quiz_url": f"/{output_file}"
}

定义出题智能体

定义 QuizGeneratorAgent 类，管理整个出题流程：

Copy
class QuizGeneratorAgent(BaseAgent):
"""Quiz generation agent that manages quiz creation process"""
def __init__(
self,
llm: LLM,
markdown_dir: str
):
name = "QuizGeneratorAgent"
role = """你是一个专业的考卷生成助手。你可以根据提供的Markdown内容生成结构良好、
内容全面的考卷。你擅长根据受众群体和考察目的设计合适的题目。"""

super().__init__(
name=name,
role=role,
llm=llm,
)

self.markdown_dir = markdown_dir
self.quiz_action = QuizGenerationAction(llm)
self.save_action = SaveQuizAction()

self._add_quiz_example()

def _load_markdown_content(self) -> str:
"""Load all markdown files from directory"""
content = []
for root, _, files in os.walk(self.markdown_dir):
for file in files:
if file.endswith(".md"):
with open(os.path.join(root, file), 'r', encoding='utf-8') as f:
content.append(f.read())
return "\n".join(content)

def __call__(self, task: TaskPackage):
"""Process the quiz generation task"""
# Parse task parameters
params = json.loads(task.instruction)
audience = params.get("audience", "")
purpose = params.get("purpose", "")
question_types = params.get("question_types", [])

# Load markdown content
content = self._load_markdown_content()

# Generate quiz
quiz_result = self.quiz_action(
content=content,
question_types=question_types,
audience=audience,
purpose=purpose
)

# Save quiz
save_result = self.save_action(
quiz_content=quiz_result["quiz_content"],
quiz_title="generated_quiz"
)

task.answer = {
"quiz_content": quiz_result["quiz_content"],
"quiz_url": save_result["quiz_url"]
}
task.completion = "completed"

return task

使用

Copy
from dotenv import load_dotenv
load_dotenv()

api_key = os.getenv('ZISHU_API_KEY')
base_url = "http://43.200.7.56:8008/v1"
chat_model = "deepseek-chat"

llm = LLM(api_key=api_key, base_url=base_url, model_name=chat_model)

# 创建出题智能体
markdown_dir = "docs" # 指定包含Markdown文件的目录
agent = QuizGeneratorAgent(llm=llm, markdown_dir=markdown_dir)

# 定义考卷参数
quiz_params = {
"audience": "高水平", # 受众群体
"purpose": "测试知识掌握情况", # 考察目的
"question_types": ["单选题"] # 需要包含的题型
}

# 生成考卷
task = TaskPackage(instruction=json.dumps(quiz_params))
result = agent(task)

print("生成的考卷内容：")
print(result.answer["quiz_content"])
print(f"考卷路径: {result.answer['quiz_url']}")

结果：
高水平知识掌握情况测试

量子力学中，普朗克常数 (h) 的单位是什么？

(x) 焦耳・秒 (J・s)

() 牛顿・米 (N・m)

() 瓦特・秒 (W・s)

() 库仑・秒 (C・s)

在生物化学中，DNA 的双螺旋结构是由哪两位科学家在 1953 年提出的？

(x) 詹姆斯・沃森和弗朗西斯・克里克

( ) 鲁道夫・维尔茨和阿尔伯特・萨克斯

( ) 罗伯特・胡克尔和弗朗西斯・克里克

( ) 乔治・比德尔和爱德华・塔特姆

请列举出以下元素中，属于碱金属元素的是哪一个？

(x) 钠 (Na)

() 氯 (Cl)

() 氧 (O)

() 硅 (Si)

在经典力学中，描述物体在空间中运动状态的基本方程是：

(x) 牛顿第二定律 ( F = ma )
...

() 氧 (O)

() 氢 (H)

() 氯 (Cl)