从文本生成高质量问题:项目实操指南

说明:本文旨在把复杂的技术说明变成面向专科及以上读者、通俗易懂且可操作的博客式指南。若需要直接复制命令或配置片段,请按文中示例执行。


概览:这个工具做什么?

这个项目用于从文本中自动生成多样化、可读性强的问题(question generation),支持多种大语言模型和提供者(OpenAI 兼容、Anthropic、Gemini、OpenRouter、Groq、Together 等)。它的目标是把输入文本(例如数据集或本地 JSONL 文档)作为提示,调用 LLM 为每条文本产生若干问题,并可选地为这些问题生成答案,最终把结果写成 JSONL 文件,便于后续使用(例如教育、问答库、数据增强)。


快速上手(最短可执行步骤)

按顺序执行下列命令可以在本地快速跑通一个示例流程:

# 1) Create a venv (optional)
python3 -m venv .venv && source .venv/bin/activate

# 2) Install dependencies
pip install -r requirements.txt

# 3) Set an API key for your chosen provider (example: OpenRouter)
export OPENROUTER_API_KEY=your_api_key_here

# 4) Run
python3 src/main.py mkurman/hindawi-journals-2007-2023 \
    --provider openrouter \
    --model qwen/qwen3-235b-a22b-2507 \
    --output-dir ./data/questions_openrouter \
    --start-index 0 \
    --end-index 10 \
    --num-questions 5 \
    --text-column text \
    --verbose

解释:上面示例展示了一个完整从环境、依赖、到运行的最小可执行流程。--provider 指定调用哪个后端,--model 指定模型名(由提供者决定),--num-questions 控制每条输入生成的问题个数。


系统要求(Environment)

  • Python 3.9+(README 明确要求 Python 3.9 以上,以支持现代类型提示如 list[str]

  • 依赖项通过 pip install -r requirements.txt 安装,当前 requirements.txt 包含:

    • aiohttp
    • datasets
    • tqdm

支持的输入类型

工具接受两类主要输入来源:

  1. Hugging Face 数据集名称(格式:org/dataset,内部用 datasets.load_dataset 读取)

  2. 本地文件

    • .jsonl.json(每行一条 JSON)
    • .parquet

默认文本字段名为 text,可通过 --text-column 指定其它字段。


命令行用法总览与常用选项

基本用法:

python3 src/main.py <dataset_or_jsonl_path> \
  --provider <provider> \
  --model <model_name> \
  --output-dir <dir>

关键命令行选项与含义(简表):

选项 含义
--text-column TEXT 指定包含文本的列,默认 text
--num-questions INT 每条文本生成的问题数,默认 3
--max-tokens INT 每次请求的最大 tokens,默认 4096
--provider-url URL --provider other 时需提供自定义 API 基础 URL
--num-workers INT 并发工作数,默认 1
--shuffle 对数据项打乱顺序
--max-items INT 限制处理条数
--start-index/--end-index INT 对大数据集进行切片(0-based,end-exclusive)
--dataset-split SPLIT 远程 HF 数据集的 split,默认 train
--sleep-between-requests S 请求间休眠(秒)
--sleep-between-items S 条目间休眠(秒)
--style STYLE 指定风格(单个或逗号分隔),每条随机选择一个
--no-style 不使用风格指令(中性风格)
--styles-file FILE 从文件加载风格(每行一个)
--with-answer 为每个问题生成答案
--answer-provider PROVIDER 指定用于生成答案的 API 提供者(如果未设置,则与 --provider 相同)
--answer-model MODEL 答案使用的模型(若未设置,使用与问题相同模型)
--answer-single-request 将所有问题在一次请求中生成答案(性能与错误处理上的权衡)
--verbose / --debug 日志级别控制

Provider(提供者)支持情况

README 中列举的 --provider 支持值包括但不限于:

  • featherless
  • openai
  • anthropic
  • qwen
  • qwen-deepinfra
  • kimi
  • z.ai
  • openrouter
  • cerebras
  • together
  • groq
  • gemini
  • ollama
  • chutes
  • huggingface
  • other

说明:other 表示任何兼容 OpenAI API 的自定义端点,需要同时配合 --provider-url 使用。


风格(Styles)控制

默认行为会从内置的 35+ 风格(参见 default_styles.txt)中随机选一个:例如学术(formal and academic)、创意(creative and imaginative)、轻松会话(casual and conversational)等。

可选项:

  • 通过 --style 指定单个或逗号分隔的风格集合(程序会为每个条目随机挑选一个风格)
  • --no-style 禁用风格指示,生成中性问题
  • --styles-file 从文件加载风格(每行一个,# 可注释)

回答生成(Answer Generation)机制与选项

如果你想在生成问题的同时得到答案,可以使用 --with-answer

主要行为与配置:

  • --with-answer:为每个问题请求生成答案,输出 JSONL 中会包含 output 字段。
  • --answer-provider--answer-model:可用于将问题的生成与答案的生成委托给不同提供者或不同模型(例如问题用 OpenRouter,答案用 Anthropic)。
  • --answer-single-request:把所有问题在一次请求中询问模型以节省请求次数(但可能降低故障隔离能力)。
  • 错误处理:如果某个问题的答案生成失败,output 字段会被设置为字符串 "error",并包含 answer_error 字段说明失败原因(README 描述的行为)。

示例(从 README):

# Generate questions with answers using the same model
python3 src/main.py <dataset> \
  --provider openrouter \
  --model qwen/qwen3-235b-a22b-2507 \
  --output-dir ./data/qa_openrouter \
  --start-index 0 \
  --end-index 10 \
  --num-questions 3 \
  --with-answer

以及跨提供者示例:

# Multi-Provider Q&A Generation (Questions from OpenRouter, Answers from Anthropic):
export OPENROUTER_API_KEY=your_openrouter_key
export ANTHROPIC_API_KEY=your_anthropic_key
python3 src/main.py mkurman/hindawi-journals-2007-2023 \
  --provider openrouter \
  --model qwen/qwen3-235b-a22b-2507 \
  --answer-provider anthropic \
  --answer-model claude-3-haiku-20240307 \
  --output-dir ./data/qa_multi_provider \
  --start-index 0 \
  --end-index 5 \
  --num-questions 2 \
  --with-answer \
  --verbose

认证(API Keys)规则与命名约定

README 说明了环境变量命名的通用规则:以提供者的大写形式作为前缀并附加 _API_KEY。例如:

提供者 环境变量名
openai OPENAI_API_KEY
anthropic ANTHROPIC_API_KEY
openrouter OPENROUTER_API_KEY
groq GROQ_API_KEY
together TOGETHER_API_KEY
cerebras CEREBRAS_API_KEY
qwen QWEN_API_KEY
qwen-deepinfra QWEN_DEEPINFRA_API_KEY
kimi (Moonshot) KIMI_API_KEY
z.ai Z_AI_API_KEY
gemini GEMINI_API_KEY
other OTHER_API_KEY

备注:Ollama 则通常假设本地运行(http://localhost:11434),不强制环境变量。


自定义提供者(other)使用说明

当你需要对接自建的 OpenAI 兼容接口或第三方不在内置列表中的服务时,使用 --provider other 并同时设置 --provider-urlOTHER_API_KEY。示例(来自 README):

export OTHER_API_KEY=your_custom_api_key
python3 src/main.py dataset.jsonl \
  --provider other \
  --provider-url https://your-custom-api.com/v1 \
  --model your-custom-model \
  --output-dir ./output \
  --num-questions 3

输出格式(JSONL)详解

输出会写到 <output-dir>/questions_{YYYY-MM-DD_HH-MM-SS}_{dataset}_{provider}_{model}[optional_range].jsonl,每行是一个 JSON 记录。成功生成时的标准记录示例(取自 README):

{
  "input": "What practical applications benefit most from question generation using LLMs?",
  "source_text": "...original text...",
  "question_index": 1,
  "total_questions": 5,
  "metadata": { "original_item_index": 0, "text_column": "text" },
  "generation_settings": {
    "provider": "openrouter",
    "model": "qwen/qwen3-235b-a22b-2507",
    "style": "formal and academic",
    "num_questions_requested": 5,
    "num_questions_generated": 5,
    "max_tokens": 4096
  },
  "timestamp": "2025-08-17T12:34:56.789012"
}

如果使用 --with-answer,记录会包含 output 字段(即模型生成的答案):

{
  "input": "What practical applications benefit most from question generation using LLMs?",
  "output": "Question generation using LLMs has several practical applications including educational content creation, chatbot training data, assessment generation for online courses, and synthetic dataset augmentation for machine learning models...",
  ...
}

错误记录说明:

  • 如果某个问题的答案生成失败:output 字段取值为 "error",并额外包含 answer_error 字段来描述错误详情。
  • 如果整个条目的生成失败,会输出一个以 error 字段为主的错误记录。

并发与限速(性能提示)

README 提示了两类限速控制:

  • --sleep-between-requests:请求级别的 sleep(用于 API 限流)
  • --sleep-between-items:条目级别的 sleep(处理大批数据时降低突发并发)

此外,--num-workers 控制并发工作数。建议在实际部署时根据目标提供者的速率限制与并发能力调整这些值。


运行示例集合(便于复制)

  1. 基础示例(单一提供者)
export OPENROUTER_API_KEY=your_api_key_here
python3 src/main.py mkurman/hindawi-journals-2007-2023 \
    --provider openrouter \
    --model qwen/qwen3-235b-a22b-2507 \
    --output-dir ./data/questions_openrouter \
    --start-index 0 \
    --end-index 10 \
    --num-questions 5 \
    --text-column text \
    --verbose
  1. 带 Answer 生成的示例
export OPENROUTER_API_KEY=your_api_key_here
python3 src/main.py mkurman/hindawi-journals-2007-2023 \
    --provider openrouter \
    --model qwen/qwen3-235b-a22b-2507 \
    --output-dir ./data/qa_openrouter \
    --start-index 0 \
    --end-index 10 \
    --num-questions 3 \
    --with-answer
  1. 多提供者混合(问题与答案分配给不同 provider)

参考前文 Multi-Provider 示例。


实践建议

  • 并发与速率控制:通过 --num-workers 提升并发,但同时使用 --sleep-between-requests 来避免触发 API 限流。
  • 数据切片:对于大型数据集,使用 --start-index/--end-index 逐段处理,避免一次性加载全部数据。
  • 样式管理:如果希望风格多样化,使用 --style--styles-file;若要统一风格,可明确指定单一风格或使用 --no-style
  • 输出管理:输出文件按时间戳命名,便于批次管理与审计。
  • 错误处理:检查 JSONL 中 outputanswer_error 字段以定位失败项,必要时单独重试失败条目。

常见问题(FAQ)与快速解答

下面这组 FAQ 基于 README 中可能引发的用户疑问编写,并直接回答实现/运行相关的常见问题。

问:我必须使用 Python 3.9 吗?
答:README 指定 Python 3.9+,因为代码使用了现代类型提示(如 list[str])。建议使用 3.9 或更高版本。

问:如何为本地 JSONL 数据生成问题?
答:直接把本地文件路径作为第一个参数传给 src/main.py(文件需为 .jsonl.json,并包含指定的文本列,默认 text)。示例:python3 src/main.py ./data/mydata.jsonl --provider openrouter ...

问:我可以把问题的生成和答案的生成交给不同的 API 吗?
答:可以。使用 --answer-provider--answer-model 将答案任务交给另一提供者或模型。README 中给出了 OpenRouter+Anthropic 的示例。

问:输出文件是什么格式?如何查看?
答:输出为 JSONL(每行一个 JSON 对象),按时间戳与参数命名。使用常规工具(jq、Python、文本编辑器)均可解析。

问:当答案生成出错,如何定位问题?
答:输出中会把失败的 output 字段置为 "error",同时 answer_error 会包含错误说明,按该字段排查并重试相关条目。


HowTo:最小示例步骤

下面是一个简洁的操作步骤(同 README 中的 Quick start,但以 HowTo 形式呈现,便于新手快速执行)。

步骤清单:

  1. 创建并激活虚拟环境:python3 -m venv .venv && source .venv/bin/activate

  2. 安装依赖:pip install -r requirements.txt

  3. 设置 API key:export OPENROUTER_API_KEY=your_api_key_here

  4. 运行脚本生成问题(示例):

    python3 src/main.py mkurman/hindawi-journals-2007-2023 \
        --provider openrouter \
        --model qwen/qwen3-235b-a22b-2507 \
        --output-dir ./data/questions_openrouter \
        --start-index 0 \
        --end-index 10 \
        --num-questions 5 \
        --text-column text \
        --verbose
    
  5. 检查输出:打开 ./data/questions_openrouter 下的 JSONL 文件,逐行解析验证。


Schema 标记(可直接复制到页面以便结构化数据被识别)

注:下面的 JSON-LD 字段内容严格基于 README 文件提供的信息与本文 FAQ / HowTo 的内容。你可以把这些块嵌入博客页面 <head> 或合适位置以暴露结构化内容(如果发布平台允许)。

FAQ Page(JSON-LD)

{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "我必须使用 Python 3.9 吗?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "README 指定 Python 3.9+,建议使用 3.9 或更高版本。"
      }
    },
    {
      "@type": "Question",
      "name": "如何为本地 JSONL 数据生成问题?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "将本地 JSONL 文件路径作为第一个参数传给 src/main.py,确保文件包含文本列(默认 text),并设置 provider 与 model。"
      }
    },
    {
      "@type": "Question",
      "name": "可以把问题生成和答案生成交给不同的 API 吗?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "可以。使用 --answer-provider 与 --answer-model 指定答案方,示例在 README 中给出。"
      }
    }
  ]
}

HowTo(JSON-LD:最小上手流程)

{
  "@context": "https://schema.org",
  "@type": "HowTo",
  "name": "从文本快速生成问题(最小可执行流程)",
  "step": [
    {
      "@type": "HowToStep",
      "name": "创建虚拟环境并激活",
      "text": "python3 -m venv .venv && source .venv/bin/activate"
    },
    {
      "@type": "HowToStep",
      "name": "安装依赖",
      "text": "pip install -r requirements.txt"
    },
    {
      "@type": "HowToStep",
      "name": "设置 API Key",
      "text": "export OPENROUTER_API_KEY=your_api_key_here"
    },
    {
      "@type": "HowToStep",
      "name": "运行生成命令",
      "text": "python3 src/main.py <dataset_or_jsonl_path> --provider openrouter --model <model> --output-dir ./data/out --num-questions 5"
    }
  ]
}

错误排查清单(快速诊断)

  • 依赖未安装:确认 pip install -r requirements.txt 已成功执行。
  • Python 版本不符:使用 python3 --version 检查是否为 3.9+。
  • API Key 未设置或错误:确认对应的 *_API_KEY 环境变量正确导出。
  • 模型或 provider 名称拼写错误:仔细检查 --provider / --model 参数。
  • 输出目录权限:确保 --output-dir 可写。
  • 速率受限(429/限流):调低并发、增加 --sleep-between-requests

—— 完 ——