You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

targets流程中嵌套Rmd文件的依赖未被识别,如何处理?

问题描述

我搭建了一个targets流程,用于训练多个模型并最终生成一个flexdashboard(或Rmd文件)汇总模型。汇总用的Rmd文件通过tarchetypes::tar_render()纳入流程,自身依赖管理正常,但问题在于该文件通过knitr::knit_expand()引用了单模型汇总的模板Rmd文件,模板里的额外依赖(比如示例中的varimp1和varimp2)没被targets捕获。想知道能不能手动添加这些依赖,或者有没有更优的方法创建这种按模型生成章节的动态Rmd文件。

最小可复现示例(MWE)

以下流程复现了问题:最终输出output.Rmd,为每个模型调用一次template.Rmd。当前依赖关系中,output目标并未依赖varimp1/2,但模板文件实际用到了这两个目标,导致output可能因varimp1/2不存在或过期而无法生成。

_targets.R

library(targets)
library(tarchetypes)

# 虚拟函数
train_model <- function(id) {
  return(id)
}
get_var_imp <- function(mdl, seed) {
  # seed参数用于轻松更改并使结果失效
  set.seed(seed)
  return(data.frame(x = runif(1), y = runif(1)))
}

list(
  tar_target(model1, train_model(id = "model1")),
  tar_target(model2, train_model(id = "model2")),
  
  tar_target(varimp1, get_var_imp(model1, seed = 1)),
  tar_target(varimp2, get_var_imp(model2, seed = 2)),
  
  tar_target(template_file, "template.Rmd", format = "file"),
  tar_render(output, "output.Rmd")
)

output.Rmd

---
title: "Output"
output: rmarkdown::html_document
---

# 通用章节

```{R}
# 这些依赖可被正常识别
model1 <- tar_read(model1)
model2 <- tar_read(model2)

为每个模型创建新章节

models <- c("model1", "model2")
NAME_MAP <- c(
  model1 = "第一个模型",
  model2 = "第二个模型"
)
txt <- sapply(models, \(target_name) knitr::knit_expand(tar_read(template_file)))

r paste(knitr::knit(text = txt), collapse = '\n')

### `template.Rmd`
```r
```{r, echo=FALSE}
# 该依赖可被识别,因已在output.Rmd中存在
mdl <- tar_read_raw("{{target_name}}")
mdl_name <- NAME_MAP[["{{target_name}}"]]

# 该依赖未被识别!=================================
vi <- tar_read_raw(gsub("model", "varimp", "{{target_name}}"))
模型{{target_name}} - r mdl_name

特征重要性如下:

# 或对mdl执行其他操作
vi
生成的文档会为每个模型生成对应章节,展示特征重要性内容。

---

# 解决方案

### 方法1:手动添加依赖到`tar_render`
`tar_render()`支持通过`deps`参数手动指定额外依赖,这样targets就能识别到varimp1/2是output目标的前置依赖。修改`_targets.R`中的`tar_render`部分:
```r
tar_render(output, "output.Rmd", deps = c(varimp1, varimp2))

这种方法简单直接,适合依赖数量少且固定的场景。

方法2:显式加载依赖让targets自动识别

在output.Rmd的开头显式加载所有需要的varimp目标,即使代码里没直接用到,targets的静态分析也会捕获这些依赖:

```{r, include=FALSE}
# 显式加载依赖,让targets识别
tar_load(varimp1)
tar_load(varimp2)
如果模型数量多,可以用循环动态加载:
```r
```{r, include=FALSE}
models <- c("model1", "model2")
lapply(models, function(m) {
  tar_load_raw(gsub("model", "varimp", m))
})
### 方法3:使用动态分支+独立渲染章节(更优解)
如果模型数量较多或后续可能扩展,推荐用targets的动态分支功能,先为每个模型生成独立的章节片段,再汇总到最终文档。

#### 修改`_targets.R`
```r
library(targets)
library(tarchetypes)

train_model <- function(id) {
  return(id)
}
get_var_imp <- function(mdl, seed) {
  set.seed(seed)
  return(data.frame(x = runif(1), y = runif(1)))
}

# 定义模型列表
tar_target(model_ids, c("model1", "model2"))

# 动态分支训练模型
tar_target(model, train_model(id = model_ids), pattern = map(model_ids))

# 动态分支生成特征重要性
tar_target(varimp, get_var_imp(model, seed = model_ids), pattern = map(model, model_ids))

# 动态分支生成单个模型的章节片段
tar_target(model_section, {
  # 渲染模板生成章节文本
  template <- readLines("template.Rmd")
  txt <- knitr::knit_expand(text = template, target_name = model_ids)
  knitr::knit(text = txt, quiet = TRUE)
}, pattern = map(model_ids, model, varimp), format = "file")

# 汇总所有章节生成最终文档
tar_render(output, "output.Rmd", deps = model_section)

修改output.Rmd

---
title: "Output"
output: rmarkdown::html_document
---

# 通用章节

```{r}
model_ids <- tar_read(model_ids)

为每个模型创建新章节

r paste(sapply(tar_read(model_section), readLines), collapse = '\n')

这种方法的优势是:
- targets能自动追踪每个模型及其依赖的varimp,分支间相互独立,更新单个模型时无需重新渲染所有章节
- 代码结构更清晰,扩展性更强,新增模型只需修改`model_ids`即可

---

内容的提问来源于stack exchange,提问作者David
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 12:55:15