Cortex 文档已覆盖 Parse、Storage、Knowledge、Evaluation 与 Synthesis。查看 最新变更

TensorZero + Cortex 评估矩阵

理解并运行一个覆盖 Cortex Parse、Storage、Knowledge、TensorZero 和 Evaluation 的金融 RAG 评估矩阵。

examples/tensorzero-cortex 是最适合演示 Cortex 端到端能力的样例。它把一个研究问题拆成可复现的评估矩阵:

  • 同一批来源 URL 会被多个 Cortex Parse engine 解析;
  • 每个解析出的 Markdown artifact 会写入 Cortex Storage;
  • Cortex Knowledge 尝试构建可搜索的图/向量上下文;
  • TensorZero 用一个或多个模型 variant 对每个 context group 作答;
  • Cortex Evaluation 把生成答案作为 RAG 和 custom quality case 继续打分。

当你要演示 Cortex、理解样例代码,或者寻找贡献入口时,可以按这页来讲。

这个矩阵在比较什么

实验有四个独立轴。完整离线矩阵可以理解为:

选中的 URL x parse engines x context groups x TensorZero variants x evaluation metrics

exhaustive 模式下,TensorZero inference 次数大致是:

context_group_count x variant_count

例如参考产物 examples/tensorzero-cortex/artifacts/tzcx_20260509_090446_65440870 产生了 5 个 context group,并只使用一个 openrouter variant,所以一共产生 5 次 TensorZero inference。

配置或代码影响什么
来源集合src/finance_urls.py, --max-urls哪些金融、宏观、政策、PDF、HTML、JSON 或 CSV 来源进入实验。
Parse enginePARSE_ENGINES, --parse-engines同一个 URL 由 autocrawl4aijina_readermarkitdownllama_parsedocling 转成 Markdown。
Context groupingTENSORZERO_CONTEXT_GROUPING, --context-groupingRAG context 是合并、按 parse engine 分组,还是 Knowledge 可用时优先使用 Knowledge。
TensorZero variantTENSORZERO_VARIANTS, tensorzero/tensorzero.toml.tpl哪些模型供应商槽位回答同一个问题。
Evaluation profileCORTEX_EVAL_TYPES, CORTEX_EVAL_METRIC_PROFILECortex Evaluation 使用哪些评测类型和指标。

端到端数据流

这里最重要的设计点是 fallback。即使 Knowledge Search 不可用,pipeline 仍会把已解析的 Markdown excerpt 分组后继续实验,并在报告中标记 context_source=parse_artifact_fallback

代码地图

文件作用
src/cli.pyCLI 入口,支持 render-configrunservelist-urlsvisualize-knowledge
src/main.pyFastAPI 样例服务,提供 /experiments/run/cortex/status/tensorzero/status 和 Swagger examples。
src/pipeline.py编排 Parse、Storage、Knowledge、TensorZero inference、feedback、Evaluation 和报告写入。
src/cortex_client.pyCortex Parse、Storage、Knowledge、Jobs、Evaluation 的轻量 HTTP client。
src/tensorzero_client.pyTensorZero /status/inference/feedback 的轻量 HTTP client。
src/models.pyPydantic 请求、配置、artifact、inference、evaluation case 和 report schema。
src/scoring.py在 Cortex Evaluation 之前先给 TensorZero feedback 用的本地轻量评分。
src/finance_urls.py内置来源目录和 expected keyword hints。
tensorzero/tensorzero.toml.tplTensorZero 模型槽位、variants、JSON 输出 schema、adaptive experiment 和反馈指标。
tensorzero/templates/rag_system.minijinja金融 RAG answer function 的 system prompt。

每个环节的输入输出

环节输入输出去哪里看
选择来源FINANCE_URLS[:max_urls] 和用户 query包含 nameurlformat_hintexpected_keywords 的 URL records。src/finance_urls.py
Parse一个 URL 加一个 engine_id。Docling 默认通过 engine_modes={"docling": "async"} 强制走异步。标准化 Cortex document,包含 Markdown、metadata、document_id、可选 job_id 和启发式 parse_scoreartifacts/{run_id}/parse/*.json
Storage带 front matter 的 Markdown,front matter 包含来源、engine、document、title 等 metadata。Cortex Storage object,例如 obj_80a8ae6ade3e457e9fb54a27,并打上 tensorzerofinanceparsed-markdown、engine 标签。parse/*.jsonstorage 字段
构建 Knowledge解析文本片段、source label、object ID、document ID 和 parse score。Dataset、Add job、Cognify job、可选 knowledge_graph.html,以及 Knowledge Search 结果。report.jsonraw_search_result.jsonknowledge_graph.html
生成 context groupKnowledge Search 结果或 parse artifact fallback,加上 TENSORZERO_CONTEXT_GROUPINGContextGroup 行,例如 parse_engine:auto,包含 context_scorecontext_chars、object IDs 和 text preview。report.json.context_groups
运行 TensorZero问题、一个 context group、请求的 variant 和 run metadata。符合 rag_answer.schema.json 的严格 JSON answer,以及 inference_idepisode_id、token usage、本地 scores。raw_tensorzero_result.json
写入 feedback本地分数:parse_markdown_qualityrag_context_qualityllm_answer_qualityrag_end_to_end_pass绑定到每个 inference_id 的 TensorZero metric feedback;adaptive 模式用 rag_end_to_end_pass 优化路由。TensorZero UI: http://127.0.0.1:4000
构建评测集TensorZero answer、expected keywords、retrieval context、run metadata、本地 scores。可提交给 Cortex Evaluation 的 JSONL cases。tensorzero_eval_dataset.jsonl
运行 Cortex EvalInline test cases、eval type、metric profile、engine ID。RAG 或 custom Evaluation job result、summary、metric scores 和持久化 report object IDs。cortex_eval_result.json
生成报告上面所有产物。人类可读与结构化 scorecard。report.mdreport.json

准备 Cortex

在仓库根目录启动 Cortex:

cd /path/to/cortex
test -f .env || cp .env.local.example .env

docker compose --env-file .env -p cortex-local -f compose.local.yaml \
  --profile docling \
  --profile eval-runtime \
  --profile synthesis-runtime \
  up -d --build

如果只是修改运行时配置,可以只重启完整示例依赖的服务:

docker compose --env-file .env -p cortex-local -f compose.local.yaml \
  --profile docling \
  --profile eval-runtime \
  --profile synthesis-runtime \
  up -d --no-build --force-recreate \
  cortex-api \
  cortex-parse-worker-docling \
  cortex-knowledge-worker \
  cortex-evaluation-worker-runtime \
  cortex-synthesis-worker-runtime

常用本地入口:

服务地址
Cortex Swaggerhttp://127.0.0.1:8080/docs
TensorZero Gatewayhttp://127.0.0.1:3002
TensorZero UIhttp://127.0.0.1:4000
FastAPI 样例应用http://127.0.0.1:8090/docs

配置样例

cd /path/to/cortex/examples/tensorzero-cortex
test -f .env || cp .env.example .env
uv sync

填写你要测试的模型供应商密钥:

OPENAI_API_KEY=...
GEMINI_API_KEY=...
KIMI_API_KEY=...
OPENROUTER_API_KEY=...

现场演示推荐使用:

PARSE_ENGINES=auto,crawl4ai,jina_reader,markitdown,llama_parse,docling
TENSORZERO_STRATEGY=exhaustive
TENSORZERO_VARIANTS=openai,gemini,kimi
TENSORZERO_CONTEXT_GROUPING=by_parse_engine
SUBMIT_CORTEX_EVAL=true
CORTEX_EVAL_MODE=async
CORTEX_EVAL_TYPES=rag,custom
CORTEX_EVAL_METRIC_PROFILE=deepeval_rag_core
CORTEX_EVAL_MAX_CASES=3
CORTEX_EVAL_MAX_CONTEXT_CHARS_PER_CASE=4000
KNOWLEDGE_GRAPH_VISUALIZATION=true

渲染 TensorZero 配置并启动 TensorZero stack:

uv run tensorzero-cortex render-config
docker compose --env-file .env -f tensorzero/docker-compose.tensorzero.yaml up -d

渲染命令会用 .env 填充 tensorzero/tensorzero.toml。修改 TENSORZERO_VARIANTS、模型 ID、API base URL 或 tensorzero/tensorzero.toml.tpl 后,都要重新渲染并重启 Gateway。

先跑冒烟测试

先走最短链路:

uv run tensorzero-cortex run --max-urls 1 --parse-engines markitdown --skip-knowledge-jobs

这个命令会覆盖 Cortex Parse、Cortex Storage、TensorZero inference、TensorZero feedback 和报告生成。它跳过 Knowledge,并直接用解析出的 Markdown 作为 RAG context。

运行完整矩阵

uv run tensorzero-cortex run \
  --max-urls 5 \
  --parse-engines auto,crawl4ai,jina_reader,markitdown,llama_parse,docling \
  --parse-mode sync \
  --tensorzero-strategy exhaustive \
  --tensorzero-variants openai,gemini,kimi \
  --context-grouping by_parse_engine \
  --submit-cortex-eval \
  --cortex-eval-mode async \
  --cortex-eval-types rag,custom \
  --query "What macroeconomic and financial stability risks are highlighted across these documents?"

Docling 属于重型 worker。即使全局 parse mode 是 sync,样例也会把 docling 覆盖为 async,所以它会提交到 /v1/parse/jobs,再由专用 Docling worker 消费。

通过 Swagger 运行

也可以启动样例应用:

uv run tensorzero-cortex serve --host 127.0.0.1 --port 8090

打开 http://127.0.0.1:8090/docs,使用 POST /experiments/runsrc/main.py 中内置了这些 OpenAPI examples:

Example什么时候用
full_matrix_async想跑接近真实的 parse-engine x model-variant 矩阵,并用异步 Evaluation。
ollama_local_smoke想用本地模型小流量验证,限制 context 和 eval case 数量。
adaptive_smoke想让 TensorZero 自动选择 variant,验证 adaptive feedback loop。
legacy_compatible想使用旧版扁平请求字段快速测试。

读懂参考 run

演示和排障时可以先看这个已生成产物:

examples/tensorzero-cortex/artifacts/tzcx_20260509_090446_65440870

这次 run 用一个来源 Federal Reserve FOMC calendar,对比了六个 parse engines。五个 engine 产生了可用于上下文的文本。Docling 通过异步链路完成并写入 Storage,但这次没有 Markdown 文本,所以它进入 parse scorecard,却没有成为 TensorZero context group。

信号怎么解释
Parse artifacts6一个 URL x 六个 parse engines。
Parse successes6所有 parser 调用都成功返回。
Context groups5autocrawl4aijina_readerllama_parsemarkitdown;Docling 因 Markdown 为空没有上下文。
TensorZero inferences5五个 context groups x 一个 openrouter variant。
TensorZero errors0每次 inference 都返回了结构化 answer。
Evaluation cases3这次 run 把 Cortex Evaluation 输入限制为 3 个 case。
Context sourceparse_artifact_fallbackKnowledge build 成功,但 Knowledge Search 失败,pipeline 回退到 parse artifacts。
Knowledge statusbuiltDataset Add 和 Cognify job 完成,并生成了 graph HTML。
Cortex Eval modeasyncEvaluation 通过 /v1/eval/jobs 提交。

参考 scorecard:

MetricValue如何讲
parse_markdown_quality0.7444所有成功 parse artifact 的平均启发式质量。
rag_context_quality0.9245分组后的 context 覆盖了大多数 FOMC 和 monetary policy 关键词。
llm_answer_quality0.6893答案通常引用了来源,并正确指出该日历页缺少风险讨论。
rag_end_to_end_pass_rate1.0每个 TensorZero inference 都通过了本地 parse/context/answer gate。

这个参考 run 很适合讲 Cortex 的韧性:raw_search_result.json 中记录了 knowledge_search_failed,错误是 Cognee runtime module is unavailable,但实验仍通过 parse artifact fallback 完整跑完。

读懂每个产物

Artifact重点看什么
report.md最快读懂全局:scorecard、parse 表、context 表、TensorZero inference 表、evaluation cases 和产物路径。
report.json完整结构化对象,对应 src/models.py 里的 ExperimentReport
parse/Federal-Reserve-FOMC-calendar-jina_reader.json一个紧凑的 parse + storage 样例。它的 title 是 The Fed - Meeting calendars and information,Markdown 长度 1903,Storage object 是 obj_80a8ae6ade3e457e9fb54a27
raw_search_result.json判断 context 来自 Knowledge Search 还是 fallback。参考 run 里有 5 条 fallback results。
raw_tensorzero_result.json每个 context_idvariant_name、answer JSON、citations、confidence、token usage、本地 scores 和 feedback errors。
tensorzero_eval_dataset.jsonl实际提交给 Cortex Evaluation 的 inline test cases。每行包含 query、actual output、expected keywords、retrieval context、TensorZero IDs 和本地 scores。
cortex_eval_result.json异步 Cortex Evaluation 结果。参考 run 中 RAG composite 是 0.8611,custom quality composite 是 0.2,说明答案具备上下文一致性,但对更宽泛的风险对比问题并不完整。
knowledge_graph.html可选的 Cognee dataset-scoped graph visualization。Knowledge Add/Cognify 成功时,演示现场可以直接用浏览器打开。

TensorZero 输入如何变成 Evaluation 输入

TensorZero 收到的是一个 user message:

Question:
{query}

Cortex Knowledge context:
{context group text}

Metadata:
{run_id, dataset_key, parse_engines, parse_mode, object_ids, context_id, requested_variant}

TensorZero 必须返回符合 tensorzero/schemas/rag_answer.schema.json 的 JSON:

{
  "answer": "Concise answer grounded in the supplied context.",
  "citations": ["source label, URL, or object ID"],
  "confidence": 0.3,
  "missing_evidence": ["what the context could not prove"]
}

Pipeline 会把这个 answer 转成 Cortex Evaluation case:

{
  "query": "What macroeconomic and financial stability risks are highlighted?",
  "actual_output": "The generated TensorZero answer.",
  "expected_keywords": ["fomc", "federal reserve", "monetary policy"],
  "retrieval_contexts": ["Source: Federal Reserve FOMC calendar..."],
  "metadata": {
    "context_id": "parse_engine:jina_reader",
    "tensorzero_variant": "openrouter",
    "tensorzero_inference_id": "019e0bfd-2a70-7780-b31e-3a5a95e8deaa",
    "scores": {
      "parse_markdown_quality": 0.7444,
      "rag_context_quality": 0.6224,
      "llm_answer_quality": 0.82,
      "rag_end_to_end_pass": true
    }
  }
}

这就是 TensorZero observability 和 Cortex Evaluation 的连接点:TensorZero 记录在线风格的 inference 和 feedback,Cortex Evaluation 把同一批记录变成可重复的 judge-based reports。

分数怎么来

本地 feedback 指标在 src/scoring.py

Metric本地评分逻辑为什么先于 Cortex Evaluation 存在
parse_markdown_quality结合 Markdown 长度、结构特征和 expected keyword 覆盖。让 TensorZero 能把模型结果和 parser 质量关联起来。
rag_context_quality评估 keyword 覆盖和 context 密度。便于比较 by_parse_engine 分组后的上下文。
llm_answer_quality评估 keyword 覆盖、引用/来源提及和 confidence。给 TensorZero adaptive routing 提供即时反馈。
rag_end_to_end_pass要求 parse score >= 0.45、context score >= 0.35、answer score >= 0.45。tensorzero.toml.tpl 中的 boolean 优化指标。

Cortex Evaluation 是更深一层的 judge。默认 RAG profile 会提交 rag.answer_relevancerag.faithfulnessrag.contextual_precisionrag.contextual_recallrag.contextual_relevance。Custom quality 会提交 quality.correctnessquality.completenessquality.relevancecustom.g_eval

贡献入口

目标从哪里开始改什么
增加新的来源类型src/finance_urls.py添加 URL、format hint 和 expected keywords;运行时把 --max-urls 调到能覆盖它。
增加或调优 parser 对比src/pipeline.py, .env把 engine 加入 PARSE_ENGINES,调整 engine_modes,或改进 parse artifact scoring。
增加模型供应商tensorzero/tensorzero.toml.tpl, .env.example添加 model slot、provider 和 variant;重新 render config 并重启 Gateway。
改 RAG answer contracttensorzero/schemas/rag_answer.schema.json, tensorzero/templates/rag_system.minijinja同步更新 JSON schema 和 prompt,保证模型输出仍可解析。
增加本地 feedback metricsrc/scoring.py, src/pipeline.py, tensorzero/tensorzero.toml.tpl计算分数,写入 TensorZero /feedback,并声明 metric。
增加 Cortex Evaluation 指标src/pipeline.py扩展 _metrics_for_eval_type,或在请求里传 metrics_by_type
改进 API 演示体验src/main.py增加 OpenAPI examples、health diagnostics 或更小的 demo presets。
改进 Knowledge 可视化src/knowledge_graph_visualization.py调整 dataset-scoped graph export 和 HTML rendering。

在 run 后补充 Synthesis

主样例重点覆盖 Parse、Storage、Knowledge、TensorZero 和 Evaluation。要覆盖第五类 Cortex API,可以基于同一批解析内容提交 Synthesis job:

import osimport requestsBASE_URL = os.getenv("CORTEX_URL", "http://127.0.0.1:8080")TOKEN = os.getenv("CORTEX_TOKEN", "replace_with_token")def auth_headers():    return {"Authorization": f"Bearer {TOKEN}"}payload = {  "name": "tensorzero-rag-goldens",  "synthesis_type": "qa_pairs",  "engine_id": "deepeval",  "source": {    "type": "documents",    "documents": [      "Paste a representative parsed Markdown excerpt from report artifacts."    ]  },  "config": {    "sample_count": 10,    "include_expected_output": True  },  "output": {    "output_format": "jsonl",    "include_preview": True  }}response = requests.post(    f"{BASE_URL}/v1/synthesis/jobs",    headers={**auth_headers(), "Content-Type": "application/json"},    json=payload,)response.raise_for_status()data = response.json()print(data)
const BASE_URL = process.env.CORTEX_URL ?? "http://127.0.0.1:8080";const TOKEN = process.env.CORTEX_TOKEN ?? "replace_with_token";const authHeaders = {  Authorization: `Bearer ${TOKEN}`,};const payload = {  "name": "tensorzero-rag-goldens",  "synthesis_type": "qa_pairs",  "engine_id": "deepeval",  "source": {    "type": "documents",    "documents": [      "Paste a representative parsed Markdown excerpt from report artifacts."    ]  },  "config": {    "sample_count": 10,    "include_expected_output": true  },  "output": {    "output_format": "jsonl",    "include_preview": true  }};const response = await fetch(`${BASE_URL}/v1/synthesis/jobs`, {  method: "POST",  headers: { ...authHeaders, "Content-Type": "application/json" },  body: JSON.stringify(payload),});if (!response.ok) throw new Error(await response.text());const data = await response.json();console.log(data);
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;public class CortexExample {  static final String BASE_URL = System.getenv().getOrDefault("CORTEX_URL", "http://127.0.0.1:8080");  static final String TOKEN = System.getenv().getOrDefault("CORTEX_TOKEN", "replace_with_token");  static final HttpClient HTTP = HttpClient.newHttpClient();  static void print(HttpResponse<String> response) {    System.out.println(response.statusCode());    System.out.println(response.body());  }  public static void main(String[] args) throws Exception {    String json = """      {        \"name\": \"tensorzero-rag-goldens\",        \"synthesis_type\": \"qa_pairs\",        \"engine_id\": \"deepeval\",        \"source\": {          \"type\": \"documents\",          \"documents\": [            \"Paste a representative parsed Markdown excerpt from report artifacts.\"          ]        },        \"config\": {          \"sample_count\": 10,          \"include_expected_output\": true        },        \"output\": {          \"output_format\": \"jsonl\",          \"include_preview\": true        }      }      """;    HttpRequest request = HttpRequest.newBuilder()      .uri(URI.create(BASE_URL + "/v1/synthesis/jobs"))      .header("Authorization", "Bearer " + TOKEN)      .header("Content-Type", "application/json")      .POST(HttpRequest.BodyPublishers.ofString(json))      .build();    print(HTTP.send(request, HttpResponse.BodyHandlers.ofString()));  }}

生成的 QA pairs 可以作为新的 Evaluation cases,也可以持久化成可复用数据集,供后续 TensorZero 实验使用。

本页目录