feat: add public digest brief output for openclaw
This commit is contained in:
@@ -115,6 +115,7 @@ python scripts/run_freshrss_pipeline.py ^
|
|||||||
|
|
||||||
- `outputs/freshrss/rerun/<timestamp>/raw/freshrss.raw.json`
|
- `outputs/freshrss/rerun/<timestamp>/raw/freshrss.raw.json`
|
||||||
- `outputs/freshrss/rerun/<timestamp>/candidates/openclaw-delivery-payload.json`
|
- `outputs/freshrss/rerun/<timestamp>/candidates/openclaw-delivery-payload.json`
|
||||||
|
- `outputs/freshrss/rerun/<timestamp>/candidates/digest-brief.json`(给 OpenClaw 生成 public digest 用的轻量输入,仅包含 `keep` 候选)
|
||||||
- `outputs/freshrss/rerun/<timestamp>/run-report.json`
|
- `outputs/freshrss/rerun/<timestamp>/run-report.json`
|
||||||
- `outputs/freshrss/rerun/<timestamp>/extracted/item-XX.extracted.json`(每篇一份)
|
- `outputs/freshrss/rerun/<timestamp>/extracted/item-XX.extracted.json`(每篇一份)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,298 @@
|
|||||||
|
# Digest Optimization Summary
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
reader → OpenClaw 日报链路原先的问题主要有两类:
|
||||||
|
|
||||||
|
1. **OpenClaw public digest 输入过重**
|
||||||
|
- public digest 直接读取完整 `openclaw-delivery-payload.json`
|
||||||
|
- 其中混有大量不直接服务公开日报的字段
|
||||||
|
- public digest 这一步在 OpenClaw 侧消耗了较多 token
|
||||||
|
|
||||||
|
2. **public / internal 生成逻辑没有充分拆分**
|
||||||
|
- public digest 与 internal review digest 都基于完整 payload 推导
|
||||||
|
- 容易造成重复消耗
|
||||||
|
- public digest 还可能被 review / 内部流程语义污染
|
||||||
|
|
||||||
|
本轮优化的目标不是重写 reader 主流程,而是在不破坏现有 delivery payload 的前提下,先把 public digest 的输入和生成方式收敛下来,并验证整体 token 与内容质量的变化。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 本轮改动
|
||||||
|
|
||||||
|
### 1. reader 新增 `digest-brief.json`
|
||||||
|
|
||||||
|
在 FreshRSS pipeline 写出:
|
||||||
|
|
||||||
|
- `outputs/freshrss/rerun/<run-id>/candidates/openclaw-delivery-payload.json`
|
||||||
|
|
||||||
|
之后,额外生成:
|
||||||
|
|
||||||
|
- `outputs/freshrss/rerun/<run-id>/candidates/digest-brief.json`
|
||||||
|
|
||||||
|
用途:
|
||||||
|
|
||||||
|
- 供 OpenClaw 生成 **public digest** 时优先读取
|
||||||
|
- 作为 public-only 的轻量输入视图
|
||||||
|
|
||||||
|
当前约束:
|
||||||
|
|
||||||
|
- 仅保留 `selection_decision == "keep"` 的候选
|
||||||
|
- 默认最多保留前 5 条
|
||||||
|
- 高亮 `highlights` 最多保留 3 条
|
||||||
|
- schema 标识为 `digest-brief.v1`
|
||||||
|
|
||||||
|
保留字段:
|
||||||
|
|
||||||
|
- `title`
|
||||||
|
- `source_name`
|
||||||
|
- `summary`
|
||||||
|
- `highlights`
|
||||||
|
- `category`
|
||||||
|
- `digest_rank`
|
||||||
|
- `selection_decision`
|
||||||
|
- `url`
|
||||||
|
|
||||||
|
附带计数:
|
||||||
|
|
||||||
|
- `source_candidate_count`
|
||||||
|
- `candidate_count`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. public / internal 输入边界拆分
|
||||||
|
|
||||||
|
当前推荐口径:
|
||||||
|
|
||||||
|
- **public digest**
|
||||||
|
- 优先读取 `digest-brief.json`
|
||||||
|
- 仅使用 public-only 输入视图
|
||||||
|
|
||||||
|
- **internal review digest**
|
||||||
|
- 继续读取完整 `openclaw-delivery-payload.json`
|
||||||
|
- 保留 keep / review 的决策上下文
|
||||||
|
|
||||||
|
这样做的原因:
|
||||||
|
|
||||||
|
- public digest 需要更轻、更干净的公开输入
|
||||||
|
- internal review digest 仍然需要完整上下文来支撑判断、待确认与建议沉淀
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. 一次生成两份 digest 的生成模式
|
||||||
|
|
||||||
|
推荐把:
|
||||||
|
|
||||||
|
- `public digest`
|
||||||
|
- `internal review digest`
|
||||||
|
|
||||||
|
改为在 OpenClaw 侧 **一次调用同时生成两份**。
|
||||||
|
|
||||||
|
推荐输入:
|
||||||
|
|
||||||
|
- `PUBLIC_DIGEST_INPUT` → `digest-brief.json`
|
||||||
|
- `INTERNAL_REVIEW_INPUT` → `openclaw-delivery-payload.json`
|
||||||
|
|
||||||
|
推荐输出:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"public_digest_markdown": "...",
|
||||||
|
"internal_review_digest_markdown": "..."
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这样可以减少重复 prompt / 调用开销,同时保留 public / internal 两种视图的边界。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 4. internal review digest 风格收敛
|
||||||
|
|
||||||
|
internal review digest 经过一轮人工验证后,收敛成以下规则:
|
||||||
|
|
||||||
|
固定结构:
|
||||||
|
|
||||||
|
1. `今日候选概况`
|
||||||
|
2. `已入选重点`
|
||||||
|
3. `待你确认`
|
||||||
|
4. `建议沉淀到 IMA`
|
||||||
|
5. `原始候选清单`
|
||||||
|
|
||||||
|
表达规则:
|
||||||
|
|
||||||
|
- 不显示 `rank`
|
||||||
|
- 不显示英文 machine state
|
||||||
|
- 使用中文状态:
|
||||||
|
- `keep` → `已入选`
|
||||||
|
- `review` → `待确认`
|
||||||
|
- `drop` → `暂不纳入`
|
||||||
|
|
||||||
|
内容规则:
|
||||||
|
|
||||||
|
- `已入选重点`
|
||||||
|
- 标题 + 来源
|
||||||
|
- 状态
|
||||||
|
- 较完整的一段摘要
|
||||||
|
- 一段判断(解释为什么值得入选,以及它在今天 digest 中承担什么角色)
|
||||||
|
|
||||||
|
- `待你确认`
|
||||||
|
- 标题 + 来源
|
||||||
|
- 状态
|
||||||
|
- 较完整的一段摘要
|
||||||
|
- 原因
|
||||||
|
- 建议
|
||||||
|
|
||||||
|
- `原始候选清单`
|
||||||
|
- 也用中文状态,而不是 `decision=keep/review`
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
- 保留 internal review digest 作为“给人看的审阅稿”的属性
|
||||||
|
- 避免它沦为 payload 的原样转写或机器中间态展示
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 5. public digest 风格收敛
|
||||||
|
|
||||||
|
public digest 当前推荐结构:
|
||||||
|
|
||||||
|
1. `今日概览`
|
||||||
|
2. `今日重点`
|
||||||
|
3. `趋势观察`
|
||||||
|
4. `延伸阅读`
|
||||||
|
5. `信息来源`
|
||||||
|
|
||||||
|
表达规则:
|
||||||
|
|
||||||
|
- 不暴露 internal workflow 词汇
|
||||||
|
- 不写 `待确认` / `建议沉淀到 IMA` / `keep/review/drop` / `selection_decision`
|
||||||
|
- 保持适合 Hugo 公开浏览的表达方式
|
||||||
|
|
||||||
|
内容规则:
|
||||||
|
|
||||||
|
- 每个 `今日重点` 条目除了摘要和 highlights 外,增加一句编辑性总结
|
||||||
|
- 推荐形式:
|
||||||
|
- `这篇内容更值得关注的原因在于……`
|
||||||
|
|
||||||
|
目标:
|
||||||
|
|
||||||
|
- 保证 public digest 不只是“摘要列表”
|
||||||
|
- 而是一份带有编辑性提炼的公开日报
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 实测结果
|
||||||
|
|
||||||
|
基于真实 run:
|
||||||
|
|
||||||
|
- run 目录:`outputs/freshrss/rerun/20260401-074614`
|
||||||
|
|
||||||
|
### 1. public 输入压缩效果
|
||||||
|
|
||||||
|
- 完整 payload:`8701` 字符
|
||||||
|
- `digest-brief.json`:`3080` 字符
|
||||||
|
|
||||||
|
压缩比例:
|
||||||
|
|
||||||
|
- **减少约 64.6%**
|
||||||
|
|
||||||
|
按中位 token 粗估:
|
||||||
|
|
||||||
|
- 完整 payload:约 `3955 tokens`
|
||||||
|
- public brief:约 `1400 tokens`
|
||||||
|
|
||||||
|
public 输入侧单次大约减少:
|
||||||
|
|
||||||
|
- **约 2500 tokens**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. 一次生成两份的总成本估算
|
||||||
|
|
||||||
|
基于真实输入输出的中位估算:
|
||||||
|
|
||||||
|
- 旧方案(两次生成):约 `10328 tokens`
|
||||||
|
- 新方案(一次生成两份):约 `7734 tokens`
|
||||||
|
|
||||||
|
节省:
|
||||||
|
|
||||||
|
- **约 2594 tokens**
|
||||||
|
- **约 25%**
|
||||||
|
|
||||||
|
说明:
|
||||||
|
|
||||||
|
- 第一步 public 输入瘦身带来的是“输入量级下降”
|
||||||
|
- 第二步一次生成两份带来的是“调用层重复开销下降”
|
||||||
|
- 两者叠加后,已经形成比较明显的成本优化效果
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 当前默认口径
|
||||||
|
|
||||||
|
### public digest
|
||||||
|
|
||||||
|
- 输入:`digest-brief.json`
|
||||||
|
- 风格:公开浏览稿
|
||||||
|
- 每个重点项包含:
|
||||||
|
- 摘要
|
||||||
|
- 关键信号
|
||||||
|
- 一句编辑性总结
|
||||||
|
|
||||||
|
### internal review digest
|
||||||
|
|
||||||
|
- 输入:完整 payload
|
||||||
|
- 风格:内部审阅稿
|
||||||
|
- 每个重点项包含:
|
||||||
|
- 更完整摘要
|
||||||
|
- 判断
|
||||||
|
- 每个待确认项包含:
|
||||||
|
- 更完整摘要
|
||||||
|
- 原因
|
||||||
|
- 建议
|
||||||
|
|
||||||
|
### 生成方式
|
||||||
|
|
||||||
|
- 优先采用 **一次调用同时生成两份**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 当前阶段结论
|
||||||
|
|
||||||
|
本轮优化已经形成一个可用版本:
|
||||||
|
|
||||||
|
- reader 新增 public-only 轻量输入视图
|
||||||
|
- public / internal 边界清楚
|
||||||
|
- internal 风格和 public 风格都收敛到了可接受版本
|
||||||
|
- token 成本下降有明确实测支撑
|
||||||
|
- skill 文档与流程规范已经同步更新
|
||||||
|
|
||||||
|
当前更适合的策略不是继续抽象设计,而是:
|
||||||
|
|
||||||
|
- 按这套新流程再跑几次真实日报
|
||||||
|
- 观察稳定性、质量波动和实际使用感受
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 后续可选方向
|
||||||
|
|
||||||
|
### 1. internal 输入进一步轻量化
|
||||||
|
|
||||||
|
潜在方向:
|
||||||
|
|
||||||
|
- 新增一个 internal 专用的轻量视图
|
||||||
|
- 但需要谨慎,避免削弱 internal review 的判断价值
|
||||||
|
|
||||||
|
### 2. digest 阶段模型分层
|
||||||
|
|
||||||
|
潜在方向:
|
||||||
|
|
||||||
|
- reader 上游继续用便宜模型做抽取和结构化
|
||||||
|
- OpenClaw digest 阶段单独切到更便宜或更合适的模型
|
||||||
|
|
||||||
|
### 3. 自动化执行收口
|
||||||
|
|
||||||
|
潜在方向:
|
||||||
|
|
||||||
|
- 把“一次生成两份”的逻辑进一步标准化
|
||||||
|
- 更顺滑地接 Hugo 发布与聊天回传
|
||||||
|
- 让 reader → OpenClaw → Hugo / chat 的路径更接近真正的稳定生产流程
|
||||||
@@ -26,7 +26,9 @@ from .keyword_index import DailyKeywordIndex, DailyKeywordTerm, KeywordStat, Key
|
|||||||
from .openclaw_delivery import (
|
from .openclaw_delivery import (
|
||||||
OpenClawDeliveryPayload,
|
OpenClawDeliveryPayload,
|
||||||
OpenClawDeliveryStats,
|
OpenClawDeliveryStats,
|
||||||
|
OpenClawDigestBrief,
|
||||||
build_openclaw_delivery_payload,
|
build_openclaw_delivery_payload,
|
||||||
|
build_openclaw_digest_brief,
|
||||||
)
|
)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@@ -50,10 +52,12 @@ __all__ = [
|
|||||||
"OpenClawCandidateInput",
|
"OpenClawCandidateInput",
|
||||||
"OpenClawDeliveryPayload",
|
"OpenClawDeliveryPayload",
|
||||||
"OpenClawDeliveryStats",
|
"OpenClawDeliveryStats",
|
||||||
|
"OpenClawDigestBrief",
|
||||||
"ReviewState",
|
"ReviewState",
|
||||||
"ReviewStatus",
|
"ReviewStatus",
|
||||||
"build_article_candidate_record",
|
"build_article_candidate_record",
|
||||||
"build_openclaw_delivery_payload",
|
"build_openclaw_delivery_payload",
|
||||||
|
"build_openclaw_digest_brief",
|
||||||
"build_openclaw_candidate_input",
|
"build_openclaw_candidate_input",
|
||||||
"candidate_id_for",
|
"candidate_id_for",
|
||||||
"normalize_candidate_url",
|
"normalize_candidate_url",
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ from pydantic import BaseModel, Field
|
|||||||
|
|
||||||
from .article_candidate import OpenClawCandidateInput
|
from .article_candidate import OpenClawCandidateInput
|
||||||
|
|
||||||
|
DIGEST_BRIEF_LIMIT = 5
|
||||||
|
DIGEST_BRIEF_HIGHLIGHT_LIMIT = 3
|
||||||
|
|
||||||
|
|
||||||
class OpenClawDeliveryStats(BaseModel):
|
class OpenClawDeliveryStats(BaseModel):
|
||||||
total: int = Field(default=0, ge=0)
|
total: int = Field(default=0, ge=0)
|
||||||
@@ -23,6 +26,27 @@ class OpenClawDeliveryPayload(BaseModel):
|
|||||||
stats: OpenClawDeliveryStats = Field(default_factory=OpenClawDeliveryStats)
|
stats: OpenClawDeliveryStats = Field(default_factory=OpenClawDeliveryStats)
|
||||||
|
|
||||||
|
|
||||||
|
class DigestBriefCandidate(BaseModel):
|
||||||
|
title: str
|
||||||
|
source_name: str | None = None
|
||||||
|
summary: str
|
||||||
|
highlights: list[str] = Field(default_factory=list)
|
||||||
|
category: str | None = None
|
||||||
|
digest_rank: int = Field(default=0)
|
||||||
|
selection_decision: str
|
||||||
|
url: str
|
||||||
|
|
||||||
|
|
||||||
|
class OpenClawDigestBrief(BaseModel):
|
||||||
|
schema_version: str = "digest-brief.v1"
|
||||||
|
generated_at: datetime
|
||||||
|
run_id: str
|
||||||
|
date: date
|
||||||
|
source_candidate_count: int = Field(default=0, ge=0)
|
||||||
|
candidate_count: int = Field(default=0, ge=0)
|
||||||
|
top_candidates: list[DigestBriefCandidate] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
def build_openclaw_delivery_payload(
|
def build_openclaw_delivery_payload(
|
||||||
candidates: list[OpenClawCandidateInput],
|
candidates: list[OpenClawCandidateInput],
|
||||||
*,
|
*,
|
||||||
@@ -46,4 +70,36 @@ def build_openclaw_delivery_payload(
|
|||||||
date=payload_date,
|
date=payload_date,
|
||||||
candidates=candidates,
|
candidates=candidates,
|
||||||
stats=stats,
|
stats=stats,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_openclaw_digest_brief(
|
||||||
|
payload: OpenClawDeliveryPayload,
|
||||||
|
*,
|
||||||
|
limit: int = DIGEST_BRIEF_LIMIT,
|
||||||
|
highlight_limit: int = DIGEST_BRIEF_HIGHLIGHT_LIMIT,
|
||||||
|
) -> OpenClawDigestBrief:
|
||||||
|
keep_candidates = [candidate for candidate in payload.candidates if candidate.selection_decision == "keep"]
|
||||||
|
sorted_candidates = sorted(keep_candidates, key=lambda candidate: candidate.digest_rank, reverse=True)
|
||||||
|
top_candidates = [
|
||||||
|
DigestBriefCandidate(
|
||||||
|
title=candidate.title,
|
||||||
|
source_name=candidate.source_name,
|
||||||
|
summary=candidate.summary,
|
||||||
|
highlights=list(candidate.highlights[:highlight_limit]),
|
||||||
|
category=candidate.category,
|
||||||
|
digest_rank=candidate.digest_rank,
|
||||||
|
selection_decision=candidate.selection_decision,
|
||||||
|
url=str(candidate.url),
|
||||||
|
)
|
||||||
|
for candidate in sorted_candidates[:limit]
|
||||||
|
]
|
||||||
|
return OpenClawDigestBrief(
|
||||||
|
schema_version="digest-brief.v1",
|
||||||
|
generated_at=payload.generated_at,
|
||||||
|
run_id=payload.run_id,
|
||||||
|
date=payload.date,
|
||||||
|
source_candidate_count=len(payload.candidates),
|
||||||
|
candidate_count=len(top_candidates),
|
||||||
|
top_candidates=top_candidates,
|
||||||
|
)
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ from summary_mcp.models.article_candidate import (
|
|||||||
)
|
)
|
||||||
from summary_mcp.models.filtering import FilterContext, FilterInput
|
from summary_mcp.models.filtering import FilterContext, FilterInput
|
||||||
from summary_mcp.models.llm_result import LlmSummaryResult
|
from summary_mcp.models.llm_result import LlmSummaryResult
|
||||||
from summary_mcp.models.openclaw_delivery import OpenClawDeliveryPayload, build_openclaw_delivery_payload
|
from summary_mcp.models.openclaw_delivery import (
|
||||||
|
OpenClawDeliveryPayload,
|
||||||
|
build_openclaw_delivery_payload,
|
||||||
|
build_openclaw_digest_brief,
|
||||||
|
)
|
||||||
from summary_mcp.models.summary_io import ExtractionInput
|
from summary_mcp.models.summary_io import ExtractionInput
|
||||||
|
|
||||||
|
|
||||||
@@ -197,8 +201,8 @@ def _build_and_persist_delivery(
|
|||||||
resolved_run_id: str,
|
resolved_run_id: str,
|
||||||
resolved_delivery_date: Any,
|
resolved_delivery_date: Any,
|
||||||
delivery_output: Path,
|
delivery_output: Path,
|
||||||
) -> tuple[OpenClawDeliveryPayload, dict[str, Any]]:
|
) -> tuple[OpenClawDeliveryPayload, Path, dict[str, Any]]:
|
||||||
# 按 digest_rank 排序,构建 delivery payload,持久化词元索引
|
# 按 digest_rank 排序,构建 delivery payload;同时派生一个更轻量的 digest-brief.json 供日报生成使用。
|
||||||
delivered_candidates.sort(key=lambda candidate: candidate.digest_rank, reverse=True)
|
delivered_candidates.sort(key=lambda candidate: candidate.digest_rank, reverse=True)
|
||||||
delivery_payload = build_openclaw_delivery_payload(
|
delivery_payload = build_openclaw_delivery_payload(
|
||||||
delivered_candidates,
|
delivered_candidates,
|
||||||
@@ -207,6 +211,10 @@ def _build_and_persist_delivery(
|
|||||||
)
|
)
|
||||||
_save_json(delivery_output, delivery_payload.model_dump(mode="json"))
|
_save_json(delivery_output, delivery_payload.model_dump(mode="json"))
|
||||||
|
|
||||||
|
digest_brief = build_openclaw_digest_brief(delivery_payload)
|
||||||
|
digest_brief_output = delivery_output.with_name("digest-brief.json")
|
||||||
|
_save_json(digest_brief_output, digest_brief.model_dump(mode="json"))
|
||||||
|
|
||||||
keyword_index_result = persist_keyword_indexes(
|
keyword_index_result = persist_keyword_indexes(
|
||||||
delivery_payload.candidates,
|
delivery_payload.candidates,
|
||||||
for_date=delivery_payload.date,
|
for_date=delivery_payload.date,
|
||||||
@@ -217,7 +225,7 @@ def _build_and_persist_delivery(
|
|||||||
aliases_path=DEFAULT_TERM_ALIASES_PATH,
|
aliases_path=DEFAULT_TERM_ALIASES_PATH,
|
||||||
stopwords_path=DEFAULT_TERM_STOPWORDS_PATH,
|
stopwords_path=DEFAULT_TERM_STOPWORDS_PATH,
|
||||||
)
|
)
|
||||||
return delivery_payload, keyword_index_result
|
return delivery_payload, digest_brief_output, keyword_index_result
|
||||||
|
|
||||||
|
|
||||||
def _build_run_report(
|
def _build_run_report(
|
||||||
@@ -232,6 +240,7 @@ def _build_run_report(
|
|||||||
debug_artifacts: bool,
|
debug_artifacts: bool,
|
||||||
raw_output: Path,
|
raw_output: Path,
|
||||||
delivery_output: Path,
|
delivery_output: Path,
|
||||||
|
digest_brief_output: Path,
|
||||||
keyword_index_result: dict[str, Any],
|
keyword_index_result: dict[str, Any],
|
||||||
item_reports: list[dict[str, Any]],
|
item_reports: list[dict[str, Any]],
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
@@ -253,6 +262,7 @@ def _build_run_report(
|
|||||||
"debug_artifacts": debug_artifacts,
|
"debug_artifacts": debug_artifacts,
|
||||||
"raw_output": str(raw_output),
|
"raw_output": str(raw_output),
|
||||||
"delivery_output": str(delivery_output),
|
"delivery_output": str(delivery_output),
|
||||||
|
"digest_brief_output": str(digest_brief_output),
|
||||||
"keyword_index": keyword_index_result,
|
"keyword_index": keyword_index_result,
|
||||||
"status_counts": status_counts,
|
"status_counts": status_counts,
|
||||||
"items": item_reports,
|
"items": item_reports,
|
||||||
@@ -369,7 +379,7 @@ def run_freshrss_pipeline(
|
|||||||
item_reports.append(result)
|
item_reports.append(result)
|
||||||
|
|
||||||
# --- 阶段 4+5:构建 delivery payload 并持久化词元索引 ---
|
# --- 阶段 4+5:构建 delivery payload 并持久化词元索引 ---
|
||||||
delivery_payload, keyword_index_result = _build_and_persist_delivery(
|
delivery_payload, digest_brief_output, keyword_index_result = _build_and_persist_delivery(
|
||||||
delivered_candidates=delivered_candidates,
|
delivered_candidates=delivered_candidates,
|
||||||
resolved_run_id=resolved_run_id,
|
resolved_run_id=resolved_run_id,
|
||||||
resolved_delivery_date=resolved_delivery_date,
|
resolved_delivery_date=resolved_delivery_date,
|
||||||
@@ -394,6 +404,7 @@ def run_freshrss_pipeline(
|
|||||||
debug_artifacts=debug_artifacts,
|
debug_artifacts=debug_artifacts,
|
||||||
raw_output=raw_output,
|
raw_output=raw_output,
|
||||||
delivery_output=delivery_output,
|
delivery_output=delivery_output,
|
||||||
|
digest_brief_output=digest_brief_output,
|
||||||
keyword_index_result=keyword_index_result,
|
keyword_index_result=keyword_index_result,
|
||||||
item_reports=item_reports,
|
item_reports=item_reports,
|
||||||
)
|
)
|
||||||
@@ -404,6 +415,7 @@ def run_freshrss_pipeline(
|
|||||||
"output_dir": str(resolved_output_dir),
|
"output_dir": str(resolved_output_dir),
|
||||||
"raw_output": str(raw_output),
|
"raw_output": str(raw_output),
|
||||||
"delivery_output": str(delivery_output),
|
"delivery_output": str(delivery_output),
|
||||||
|
"digest_brief_output": str(digest_brief_output),
|
||||||
"report_output": str(report_output),
|
"report_output": str(report_output),
|
||||||
"keyword_index": keyword_index_result,
|
"keyword_index": keyword_index_result,
|
||||||
"pulled_count": len(items),
|
"pulled_count": len(items),
|
||||||
|
|||||||
Reference in New Issue
Block a user