بنقرة واحدة
generating-dataflow-pipeline
Reasoning-guided pipeline planner that generates standard DataFlow pipeline code
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Reasoning-guided pipeline planner that generates standard DataFlow pipeline code
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Reasoning-guided pipeline planner that generates standard DataFlow pipeline code. Use when the user asks to generate, create, or build a DataFlow pipeline, wants to process JSONL data with LLM operators, mentions PromptedGenerator / PromptedFilter / Text2MultiHopQAGenerator, or asks about DataFlow operator chains. Also use when user provides a .jsonl file and asks what pipeline to write.
DataFlow 开发专家上下文加载器。当用户在 DataFlow 仓库中进行开发时触发, 涵盖:新建算子/Pipeline/Prompt、诊断报错、规范审查、 以及感知仓库变更并建议更新知识库。 Trigger: user is developing in DataFlow repo, asks to create operator/pipeline/prompt, encounters errors, wants code review, or asks about operators.
Build production-grade DataFlow operator scaffolds (generate/filter/refine/eval) for Codex and coding agents. Trigger when users ask to create/new/scaffold operators, add OPERATOR_REGISTRY registration, generate DataFlowStorage-based CLI wrappers, or generate operator unit/registry/smoke tests.
Build reusable DataFlow prompt_template classes for existing operators with two-round AskUserQuestion intake, two-stage auditable outputs, and static acceptance checks. Trigger when users ask to generate/rewrite/optimize prompt_template or reuse operator logic with new prompt requirements.
DataFlow development expert context loader. Use when developing in the DataFlow repo: creating operators/pipelines/prompts, diagnosing errors, code review, or detecting repo changes to update the knowledge base. Trigger: user is developing in DataFlow repo, asks to create operator/pipeline/prompt, encounters errors, wants code review, or asks about operators.
Build production-grade DataFlow operator scaffolds (generate/filter/refine/eval). Use when users ask to create/new/scaffold operators, add OPERATOR_REGISTRY registration, generate DataFlowStorage-based CLI wrappers, or generate operator unit/registry/smoke tests.
| name | generating-dataflow-pipeline |
| description | Reasoning-guided pipeline planner that generates standard DataFlow pipeline code |
| version | 1.0.0 |
This skill is used when users provide:
The skill must:
first_entry_file_name set to the user-provided file pathUsers provide:
Target: [Clear task description]
Sample file: [Path to JSONL file, e.g., ./data/input.jsonl]
Expected outputs: [Optional field list]
Important: The sample file is a JSONL file (one JSON object per line), not a JSON array.
Six Core Primitives (high-coverage operators for most data science tasks):
PromptedGenerator - Single-field LLM generationFormatStrPromptedGenerator - Multi-field template generationText2MultiHopQAGenerator - Multi-hop QA pair constructionPromptedFilter - LLM-based quality filteringGeneralFilter - Rule-based filteringFileOrURLToMarkdownConverterFlash → KBCChunkGenerator → KBCTextCleanerThese are preferred primitives, not fixed workflows. They can be used repeatedly and combined flexibly.
When a specialized operator exists for the task, it MUST be used over generic operators. Do NOT use PromptedGenerator to replicate functionality that a dedicated operator already provides.
Decision table (check in order, use the first match):
| Task / Scenario | Required Operator | Do NOT use |
|---|---|---|
| Generate QA pairs from text | Text2MultiHopQAGenerator | PromptedGenerator with QA prompt |
| Convert file path / URL to text | KBC trio (FileOrURLToMarkdownConverterFlash → KBCChunkGenerator → KBCTextCleaner) | PromptedGenerator to summarize files |
| Score / evaluate using multiple fields | FormatStrPromptedGenerator + GeneralFilter | PromptedFilter (single input_key only) |
| Filter by deterministic rule on existing fields | GeneralFilter | PromptedFilter |
| Generate new content from a single field | PromptedGenerator | — |
| Generate new content from multiple fields | FormatStrPromptedGenerator | Multiple PromptedGenerator steps |
Key principle: PromptedGenerator is the fallback for generic single-field generation. If the target mentions "QA", "question-answer", "问答" — always reach for Text2MultiHopQAGenerator first. In MCP/WebUI mode, browse top-level category core_text; do not hallucinate query categories like core_text/generate.
If both core_text and another top-level category seem plausible, call recommend_operator_categories with the task description plus dataset columns before spending more MCP context. Treat its result as a hard budget: inspect at most the top 1-2 suggested categories, then switch to get_operator_detail_by_name instead of further category scans.
When this skill is used through the WebUI agent rather than raw local codegen, first call get_dataset_columns for the registered dataset id and treat those returned column names as the ground-truth initial field set.
PromptedGenerator or FormatStrPromptedGenerator to create missing semantic fieldsvalidate_pipeline_config before create/update; field-flow errors should be fixed before commitvalidate_pipeline_config returns missing_input_field, treat its suggested_fields and repair_hint as the first repair path. Fix the binding and re-validate; do not broaden MCP browsing or switch categories just because a field name was wrong.✗ WRONG: Filter by "quality_score" before generating it
✓ CORRECT: Generate "quality_score" first, then filter by it
The KBC trio must always be used in this exact order:
FileOrURLToMarkdownConverterFlash — converts file path / URL → Markdown text (field: text_path)KBCChunkGenerator — splits Markdown into chunks (field: raw_chunk)KBCTextCleaner — LLM-cleans each chunk (field: cleaned_chunk)Rules:
output_key becomes the next step's input_key.text_path, raw_chunk, cleaned_chunk) unless explicitly requested otherwise.GeneralFilter lambda rules must ONLY reference fields that exist in sample data or are produced by upstream steps.
PromptedFilter only accepts a single input_key. For multi-field evaluation (e.g., scoring QA pairs), use FormatStrPromptedGenerator to score + GeneralFilter to filter.
Important caveat for Text2MultiHopQAGenerator output: The QA_pairs column is a nested list of dicts, not separate question/answer columns. You cannot directly pass question or answer as kwargs to FormatStrPromptedGenerator after Text2MultiHopQAGenerator. To score or filter individual QA pairs, use post-processing (explode the list into rows, then optionally score/filter in a second pipeline or in Python code).
Two-stage output required:
Output this first:
{
"ops": ["OperatorA", "OperatorB", "OperatorC"],
"field_flow": "field_a -> field_b -> field_c",
"reason": "Why this ordered operator chain satisfies the target, how field dependencies are satisfied, and why prompted operators are or are not used."
}
Before generating pipeline code, the agent MUST confirm the user's LLM serving configuration. If any LLM-dependent operator is used (e.g., PromptedGenerator, FormatStrPromptedGenerator, PromptedFilter, Text2MultiHopQAGenerator, KBCTextCleaner), the following information is required:
Required information (ask the user if not provided):
api_url: The LLM API endpoint (e.g., https://api.openai.com/v1/chat/completions or a self-hosted/proxy URL)model_name: The model to use (e.g., gpt-4o, gpt-4o-mini, deepseek-chat)OPENAI_API_KEY, DF_API_KEY, etc.), or ask the user to provide itWhen to ask:
api_url or model_name in their request, ask before generating codePipeline 中使用了 LLM 算子,请确认以下配置:
1. API 端点 (api_url):例如 https://api.openai.com/v1/chat/completions
2. 模型名称 (model_name):例如 gpt-4o
3. API Key 环境变量名:例如 OPENAI_API_KEY(默认为 DF_API_KEY)
echo $OPENAI_API_KEY or equivalentWhen NOT to ask (skip the pre-check):
GeneralFilter, KBCChunkGenerator, FileOrURLToMarkdownConverterFlash)WebUI deployment context:
When the pipeline is intended for WebUI execution (not local python pipeline.py), the serving must also be registered in the WebUI Serving Manager. After generating code, remind the user:
api_url, model_name, and api_keyFailed to process parameter: llm_serving errors at execution timelist_servings; the backend now provides both list_serving and a backward-compatible alias, but prefer list_serving in new prompts/skillscreate_pipeline config structure (MANDATORY — WebUI/MCP mode)When building a pipeline via the MCP create_pipeline / update_pipeline tools (NOT
local codegen), the operator params JSON has two buckets — init and run — and
where each value goes is determined by the operator's real signature, which you
MUST fetch first with get_operator_detail_by_name. Getting this wrong makes the
pipeline crash at execution time, not at create time.
Hard rules:
LLM serving goes in init.llm_serving, as the serving id (not the name).
Call list_serving, find the serving the user named, and use its id
(e.g. "0510fc816d385c6f"). NEVER put serving in a run param such as
serving_name — the operator's run() does not accept it and
run(**run_params) will raise "unexpected keyword argument".
system_prompt / user_prompt / json_schema / prompt_template are init
params, not run params for generator operators (e.g. PromptedGenerator,
ReasoningAnswerGenerator). Only put a value in run if it appears in the
operator's run() signature returned by get_operator_detail_by_name.
Never send None (or empty string) for an optional text param that has a
non-empty default. If you don't have a real user_prompt, OMIT the param
entirely so the operator uses its own default (e.g. user_prompt=""). Sending
None can cause None + str TypeErrors inside the operator.
prompt_template must be a plain allowed class name string (e.g.
"MathAnswerGeneratorPrompt"), taken from the operator detail's
allowed_prompts. Do NOT send the <class '...'> repr — the validator rejects it.
Always call validate_pipeline_config before create_pipeline and fix any
reported error (not just warnings) before creating.
Minimal correct example (PromptedGenerator, one LLM op):
operators: [{
name: "PromptedGenerator",
params: {
init: [
{ name: "llm_serving", value: "<serving_id_from_list_serving>" },
{ name: "system_prompt", value: "You are a helpful assistant." }
// user_prompt omitted -> operator default "" is used
],
run: [
{ name: "input_key", value: "instruction" },
{ name: "output_key", value: "generated_answer" }
]
}
}]
All generated Python code must follow the standard pipeline organization shown in the examples/ folder of this skill package.
Input Data Format:
first_entry_file_name MUST be set to the user-provided file path (the JSONL sample file).jsonl (one JSON object per line, NOT an array)Required structure: __init__ (storage + llm_serving + operators) → forward (sequential operator.run(storage=self.storage.step(), ...)) → if __name__ == "__main__" entry point.
DO NOT: generate custom runtime executors, forward(plan) style frameworks, or dynamic dispatch engines.
Use repository-valid constructor/run signatures only. Never invent parameter names.
FileStorage
FileStorage(
first_entry_file_name="...jsonl",
cache_path="./cache",
file_name_prefix="dataflow_cache_step",
cache_type="jsonl"
)
APILLMServing_request
APILLMServing_request(
api_url="...", # user's LLM API endpoint
key_name_of_api_key="OPENAI_API_KEY", # env var name holding the API key (reads os.environ at runtime)
model_name="gpt-4o",
max_workers=10
)
Note: key_name_of_api_key is the name of the environment variable (not the key itself).
The class default is "DF_API_KEY", but most deployments use "OPENAI_API_KEY".
Always match the env var the user has set. The api_url should be the user's actual
API endpoint, not a placeholder.
API Key handling in different contexts:
pipeline.py: Set os.environ["DF_API_KEY"] = "sk-xxx" before running, or use
key_name_of_api_key to match an existing env var. Never hardcode the key in source code.api_key field when creating/editing a serving. The WebUI backend injects it into the
environment at execution time. Do NOT include api_key or key_name_of_api_key in
operators.json — the engine handles this via the serving config.1) PromptedGenerator
PromptedGenerator(llm_serving, system_prompt="You are a helpful agent.", user_prompt="", json_schema=None)json_schema rule: If using json_schema, every "type": "object" in the schema MUST include "additionalProperties": False. Omitting it causes API 500 errors and infinite retries.run(storage=self.storage.step(), input_key="raw_content", output_key="generated_content")input_key column must exist. Generated rows written to output_key.2) FormatStrPromptedGenerator
FormatStrPromptedGenerator(llm_serving, system_prompt="You are a helpful agent.", prompt_template=FormatStrPrompt(...), json_schema=None)json_schema rule: If using json_schema, every "type": "object" in the schema MUST include "additionalProperties": False. Omitting it causes API 500 errors and infinite retries.run(storage=self.storage.step(), output_key="generated_content", **input_keys)**input_keys: each kwarg maps a template variable name (key) to a dataframe column name (value). Internally does row[input_keys[key]] per row, then prompt_template.build_prompt(need_fields, **key_dict).{placeholder} names in FormatStrPrompt.f_str_template. Kwarg values must be existing dataframe columns.prompt_template cannot be None (raises ValueError). Must pass an instantiated FormatStrPrompt(f_str_template="...").from dataflow.prompts.core_text import FormatStrPrompt3) Text2MultiHopQAGenerator
Text2MultiHopQAGenerator(llm_serving=self.llm_serving, seed=0, lang="en", prompt_template=None, num_q=5)
llm_serving — LLM serving instance (required)seed (int, default 0) — random seed for reproducibilitylang (str, default "en") — language for generation prompt; controls sentence splitting ("." for "en", "。" for "zh")prompt_template — custom DIYPromptABC instance; pass None to use default Text2MultiHopQAGeneratorPromptnum_q (int, default 5) — maximum number of QA pairs to keep per input row (truncates the generated list; actual generation count depends on sentence triples in the text)run(storage, input_key="cleaned_chunk", output_key="QA_pairs", output_meta_key="QA_metadata")
input_key must exist (cleaned text chunk column)output_key — column containing a nested list of QA dicts per row. Each dict has keys: question (str), reasoning_steps (list of {step: str}), answer (str), supporting_facts (list of str), type (str)output_meta_key — column containing metadata dict per row with keys: source, timestamp, complexityoutput_key / output_meta_key must NOT pre-exist.output_key column. The list items are dicts — question, answer, etc. are NOT separate dataframe columns. Downstream operators like FormatStrPromptedGenerator cannot directly reference question or answer as column names. To use individual QA pairs downstream, you must post-process (explode the list into separate rows) outside the operator chain.qa_pairs: []):
. or 2+ 。)4) PromptedFilter
PromptedFilter(llm_serving, system_prompt="...", min_score=1, max_score=5)run(storage=self.storage.step(), input_key="raw_content", output_key="eval")input_key must exist. output_key is numeric score column; rows outside [min_score, max_score] are filtered out.input_key is empty, null, or falsy are silently dropped before scoring — they will not appear in the output at all. Ensure the upstream operator produces non-empty values for every row, or expect row count to decrease.system_prompt controls the evaluation rubric. Default: "Please evaluate the quality of this data on a scale from 1 to 5.". Set a custom prompt for better scoring accuracy (e.g., specify evaluation criteria).5) GeneralFilter
GeneralFilter([lambda df: df["score"] >= 4, ...])run(storage=self.storage.step())pd.Series. Referenced fields must already exist.6) KBC Trio (always used in this order)
Step 1 — FileOrURLToMarkdownConverterFlash
FileOrURLToMarkdownConverterFlash(intermediate_dir="../example_data/KBCleaningPipeline/flash/", mineru_model_path="opendatalab/MinerU2.5-2509-1.2B", batch_size=4, replicas=1, num_gpus_per_replica=1.0, engine_gpu_util_rate_to_ray_cap=0.9)llm_serving — this operator has no LLM dependency.mineru_model_path is required — passing None raises ValueError. Use a HuggingFace model ID or local path.run(storage=self.storage.step(), input_key="source", output_key="text_path").pdf, .png, .jpg, .jpeg, .webp, .gif, .html, .xml, .txt, .md).Step 2 — KBCChunkGenerator
KBCChunkGenerator(chunk_size=512, chunk_overlap=50, split_method="token", min_tokens_per_chunk=100, tokenizer_name="bert-base-uncased")run(storage=self.storage.step(), input_key="text_path", output_key="raw_chunk")split_method options: "token", "sentence", "semantic", "recursive".Step 3 — KBCTextCleaner
KBCTextCleaner(llm_serving, lang="en")run(storage=self.storage.step(), input_key="raw_chunk", output_key="cleaned_chunk")# Base components
from dataflow.utils.storage import FileStorage
from dataflow.serving import APILLMServing_request
# Operators
from dataflow.operators.core_text import PromptedGenerator, FormatStrPromptedGenerator, Text2MultiHopQAGenerator, PromptedFilter, GeneralFilter
from dataflow.operators.knowledge_cleaning import FileOrURLToMarkdownConverterFlash, KBCChunkGenerator, KBCTextCleaner
The sibling skill core_text (located at ../core_text/) provides detailed per-operator API documentation that supplements the summary signatures above.
Each operator directory contains:
SKILL.md — Full English reference: constructor signature, run() signature, execution logic, mandatory rules, return value semanticsSKILL_zh.md — Chinese translation of the referenceexamples/good.md — Best-practice pipeline exampleexamples/bad.md — Common mistakes and failure casesWhen to consult core_text:
BenchAnswerGenerator, ChunkedPromptedGenerator, EmbeddingGenerator, RetrievalGenerator, RandomDomainKnowledgeRowGenerator)bad.md examples document the most frequent mistakesNote: The 6 core primitives documented above in "Operator Parameter Signature Rule" remain the primary reference for standard pipeline generation. The core_text skill provides deeper detail and covers additional operators not in the core set.
Path: ../core_text/generate/
Available operator references (8 operators):
| Operator | Subdirectory | Description |
|---|---|---|
PromptedGenerator | prompted-generator/ | Single-field LLM generation — full execution logic, skip-falsy rules |
FormatStrPromptedGenerator | format-str-prompted-generator/ | Multi-field template generation — placeholder-to-column mapping details,@prompt_restrict validation |
Text2MultiHopQAGenerator | text2multihopqa-generator/ | Multi-hop QA pair construction — text filtering thresholds (100–200k chars), output structure, row-count behavior |
BenchAnswerGenerator | bench-answer-generator/ | Benchmark answer generation —eval_type variants, conditional field requirements |
ChunkedPromptedGenerator | chunked-prompted-generator/ | Long document chunk-by-chunk processing — token-based splitting, file I/O conventions |
EmbeddingGenerator | embedding-generator/ | Text vectorization — supported serving backends,/v1/embeddings endpoint usage |
RandomDomainKnowledgeRowGenerator | random-domain-knowledge-row-generator/ | Domain-specific row generation — seed dataframe requirements,generation_num constraints |
RetrievalGenerator | retrieval-generator/ | Async RAG generation —LightRAGServing.create() async initialization, await run() requirement |
Path: ../core_text/eval/
Available operator references (5 operators):
| Operator | Subdirectory | Description |
|---|---|---|
BenchDatasetEvaluator | bench-dataset-evaluator/ | Benchmark answer comparison —match (math verification) and semantic (LLM-based) modes |
BenchDatasetEvaluatorQuestion | bench-dataset-evaluator-question/ | Extended benchmark evaluator — adds question context and subquestion support over BenchDatasetEvaluator |
PromptedEvaluator | prompted-evaluator/ | LLM-based row scoring — writes score into new column without removing rows |
Text2QASampleEvaluator | text2qa-sample-evaluator/ | QA pair quality evaluation — 4 dimensions, 8 output columns (grades + feedbacks per dimension) |
UnifiedBenchDatasetEvaluator | unified-bench-dataset-evaluator/ | Unified benchmark evaluation — 6 eval_type variants, writes 4 output columns |
Path: ../core_text/filter/
Available operator references (3 operators):
| Operator | Subdirectory | Description |
|---|---|---|
GeneralFilter | general-filter/ | Rule-based row filtering — lambda conditions combined with AND, removes rows only, adds no new columns |
KCenterGreedyFilter | kcentergreedy-filter/ | Diversity-based downsampling — K-Center Greedy algorithm, requires pre-computed embedding vectors |
PromptedFilter | prompted-filter/ | LLM semantic filtering — internally uses PromptedEvaluator, retains rows with scores in [min_score, max_score] |
Path: ../core_text/refine/
Available operator references (2 operators):
| Operator | Subdirectory | Description |
|---|---|---|
PandasOperator | pandas-operator/ | Custom DataFrame transformation — applies a sequential list of functions, no LLM calls |
PromptedRefiner | prompted-refiner/ | LLM text refinement — rewrites text in-place, overwrites original column with refined results |
Analyze sample data content to determine task nature:
File path fields (e.g., pdf_path, image_path, doc_path):
FileOrURLToMarkdownConverterFlash → KBCChunkGenerator → KBCTextCleaner (supports .pdf, .png, .jpg, .jpeg, .webp, .gif, .html, .xml, .txt, .md)Plain text fields (e.g., text, content, review_text):
PromptedGenerator, PromptedFilter, Text2MultiHopQAGenerator, FormatStrPromptedGenerator, GeneralFilterMultiple semantic fields (e.g., instruction, output, question, answer):
FormatStrPromptedGenerator for combining fieldsGeneralFilter for field-based rulesSee examples/ folder for complete workflows:
examples/basic_generate_and_filter.md — PromptedGenerator + PromptedFilter (simplest pattern)examples/multifield_scoring.md — FormatStrPromptedGenerator with multi-field scoringexamples/multi_stage_pipeline.md — Multiple PromptedGenerator stages + GeneralFilterexamples/kbc_pdf_to_qa.md — KBC trio (FileOrURLToMarkdownConverterFlash + KBCChunkGenerator + KBCTextCleaner) + Text2MultiHopQAGenerator + PromptedFilter (scores nested QA_pairs column per chunk)These are strategy guidance, not templates to copy blindly. Generated code must follow standard pipeline structure.