compare-shows

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Compare two shows

比较两个节目

status
sizes each show,
episodes
gives the latest,
occurrences
with both channel ids ranks what each covers and returns
shared
for what both mention, and
sponsors
of each, joined on entity id, gives shared sponsors.
Run each program with
arcmira_execute_read
;
arcmira_describe
has the method reference.
status
用于获取每个节目的规模,
episodes
用于获取最新一期,
occurrences
传入两个频道 ID 后,会对各自讨论的内容进行排名,并通过
shared
返回双方都提及的内容;分别获取两个节目的
sponsors
后按实体 ID 合并,即可得到共同赞助商。
使用
arcmira_execute_read
运行每个程序;
arcmira_describe
中有方法参考。

When to use

何时使用

  • compare two shows, or a show against a competitor
  • what two podcasts both talk about, or who they both advertise
  • a digest of what one or two shows covered this week or month
  • 比较两个节目,或将一个节目与竞争对手进行比较
  • 了解两个播客共同讨论的内容,或双方共同合作的广告主
  • 汇总一个或两个节目本周或本月报道的内容

Pick the entity the user meant

选择用户所指的实体

Users give names; filters take ids only (ent_..., UC..., 11-character video ids), and a name where an id belongs throws
id_required
.
  1. Resolve the exact name the user said, with their own words about it as
    context
    (a bare "Theo" has none).
  2. best
    and
    suggested
    give the id. A
    suggested
    pick is an assumption: the answer names it, with
    suggested.evidence
    as the reason.
  3. ask
    : several entities fit, and
    ask.options
    goes back to the user. No answer at all: the name is not in the index.
For this task:
  • Resolve each show with
    { type: "channel" }
    and use
    youtube_channel_id
    . Users shorten show names ("All In", "MTS"); resolve suggests a show by its initials or closest spelling, so say when a show was assumed. When nothing comes back, retry the full or hyphenated name before saying the show is not in the index.
  • Pass both UC ids in one
    occurrences
    call and read
    shared
    .
用户提供名称;过滤器只接受 ID(
ent_...
、
UC...
、11 位视频 ID),如果在需要 ID 的位置传入名称,则会抛出
id_required
。
  1. 以用户自己的描述作为
    context
    ,解析用户所说的准确名称(单独提供"Theo"时没有描述)。
  2. best
    和
    suggested
    会给出 ID。选择
    suggested
    结果属于推测:回答中应说明该节目,并提供
    suggested.evidence
    作为理由。
  3. ask
    :有多个实体匹配时,通过
    ask.options
    向用户回传选项。完全没有结果:说明该名称不在索引中。
对于此任务:
  • 使用
    { type: "channel" }
    解析每个节目,并采用
    youtube_channel_id
    。用户通常使用节目简称("All In"、"MTS");resolve 会根据首字母缩写或最接近的拼写推荐节目,因此若采用了推测结果,应在回答中说明。如果没有返回任何结果,应先尝试完整名称或带连字符的名称,再判断该节目不在索引中。
  • 在一次
    occurrences
    调用中传入两个 UC ID,并读取
    shared
    。

Worked program

示例程序

Pass each block to
arcmira_execute_read
as one program (a block marked arcmira_execute_write goes to that tool), with the name swapped for the user's. It opens with the pick: set
CONTEXT
to the user's own words about the name. When several entities fit it returns
ask
and runs nothing else. Show those options to the user, then run it again with
ID
set to the pick. Build date windows from
arcmira.daysAgo(n)
and
arcmira.today()
.
将每个代码块作为单个程序传给
arcmira_execute_read
(标记为 arcmira_execute_write 的代码块则传给该工具),并将名称替换为用户指定的名称。程序首先进行实体选择:将
CONTEXT
设置为用户对名称的原始描述。如果有多个实体匹配,它会返回
ask
,且不执行其他操作。向用户展示这些选项,然后再次运行程序,并将
ID
设置为用户选择的选项。使用
arcmira.daysAgo(n)
和
arcmira.today()
构建日期范围。

Two shows, last 90 days

两个节目,最近 90 天

javascript
const SHOWS = ["TBPN", "All-In Podcast"], IDS = [null, null];   // after an ask, put the picked option's channel_id in IDS and run again
const ids = [], names = [], assumed = [];
for (const [i, n] of SHOWS.entries()) {
  if (IDS[i]) { ids.push(IDS[i]); names.push(n); assumed.push(null); continue; }
  const r = await arcmira.resolve(n, { type: "channel" });
  const e = r.best ?? r.suggested;
  if (!e) return { unresolved: n, ask: r.ask && { question: r.ask.question, options: r.ask.options.map(o => ({ ...o, channel_id: r.candidates.find(c => c.id === o.id)?.youtube_channel_id ?? null })) } };
  ids.push(e.youtube_channel_id);
  names.push(e.name);
  assumed.push(r.suggested ? r.suggested.evidence : null);
}
const after = arcmira.daysAgo(90);
const [s0, s1, e0, e1, occ, sp0, sp1] = await Promise.all([
  arcmira.status({ channelId: ids[0] }), arcmira.status({ channelId: ids[1] }),
  arcmira.episodes(ids[0], { limit: 1 }), arcmira.episodes(ids[1], { limit: 1 }),
  arcmira.occurrences({ channelIds: ids, types: ["organization", "product"], after, limit: 40 }),
  arcmira.sponsors(ids[0]), arcmira.sponsors(ids[1]),
]);
const inOther = new Map(sp1.sponsors.map(x => [x.entity.id, x.ad_reads]));
return {
  window: occ.window,
  shows: ids.map((id, i) => ({ name: names[i], channel_id: id, assumed: Boolean(assumed[i]), why: assumed[i], videos_indexed: [s0, s1][i].channel.searchable_videos, indexed_through: [s0, s1][i].channel.indexed_through, latest: [e0, e1][i].episodes[0]?.title ?? null,
    top: occ.rows.filter(x => x.channel_id === id).slice(0, 5).map(x => [x.name, x.count]) })),
  both_discussed: occ.shared.slice(0, 5).map(x => ({ name: x.name, id: x.entity_id, episodes_by_show: x.by_channel.map(c => [c.channel_name, c.count]) })),
  shared_sponsors: sp0.sponsors.filter(x => inOther.has(x.entity.id)).map(x => ({ name: x.entity.name, id: x.entity.id, ad_reads: [x.ad_reads, inOther.get(x.entity.id)] })),
};
javascript
const SHOWS = ["TBPN", "All-In Podcast"], IDS = [null, null];   // after an ask, put the picked option's channel_id in IDS and run again
const ids = [], names = [], assumed = [];
for (const [i, n] of SHOWS.entries()) {
  if (IDS[i]) { ids.push(IDS[i]); names.push(n); assumed.push(null); continue; }
  const r = await arcmira.resolve(n, { type: "channel" });
  const e = r.best ?? r.suggested;
  if (!e) return { unresolved: n, ask: r.ask && { question: r.ask.question, options: r.ask.options.map(o => ({ ...o, channel_id: r.candidates.find(c => c.id === o.id)?.youtube_channel_id ?? null })) } };
  ids.push(e.youtube_channel_id);
  names.push(e.name);
  assumed.push(r.suggested ? r.suggested.evidence : null);
}
const after = arcmira.daysAgo(90);
const [s0, s1, e0, e1, occ, sp0, sp1] = await Promise.all([
  arcmira.status({ channelId: ids[0] }), arcmira.status({ channelId: ids[1] }),
  arcmira.episodes(ids[0], { limit: 1 }), arcmira.episodes(ids[1], { limit: 1 }),
  arcmira.occurrences({ channelIds: ids, types: ["organization", "product"], after, limit: 40 }),
  arcmira.sponsors(ids[0]), arcmira.sponsors(ids[1]),
]);
const inOther = new Map(sp1.sponsors.map(x => [x.entity.id, x.ad_reads]));
return {
  window: occ.window,
  shows: ids.map((id, i) => ({ name: names[i], channel_id: id, assumed: Boolean(assumed[i]), why: assumed[i], videos_indexed: [s0, s1][i].channel.searchable_videos, indexed_through: [s0, s1][i].channel.indexed_through, latest: [e0, e1][i].episodes[0]?.title ?? null,
    top: occ.rows.filter(x => x.channel_id === id).slice(0, 5).map(x => [x.name, x.count]) })),
  both_discussed: occ.shared.slice(0, 5).map(x => ({ name: x.name, id: x.entity_id, episodes_by_show: x.by_channel.map(c => [c.channel_name, c.count]) })),
  shared_sponsors: sp0.sponsors.filter(x => inOther.has(x.entity.id)).map(x => ({ name: x.entity.name, id: x.entity.id, ad_reads: [x.ad_reads, inOther.get(x.entity.id)] })),
};

A good answer

高质量回答

  • Names both shows as resolved, with their channel ids.
  • A side-by-side: videos indexed and
    indexed_through
    for each, the latest episode, and each show's top subjects with episode counts.
  • What both covered, from
    shared
    , with episodes per show, and the shared sponsors with ad reads per show, for a stated window.
  • 列出解析后的两个节目及其频道 ID。
  • 以并排形式展示:每个节目已索引的视频数量和
    indexed_through
    、最新一期节目,以及每个节目的热门主题及其对应单集数。
  • 基于
    shared
    展示双方共同涉及的内容及每个节目对应的单集数,同时展示共同赞助商、双方各自的广告口播次数以及明确的统计时间范围。

Traps

易错点

  • With two or more
    channelIds
    ,
    occurrences
    puts the overlap in
    shared
    ;
    rows
    alone never shows it.
  • Never count
    episodes
    to size a show;
    status({ channelId }).channel.searchable_videos
    is the count.
  • An empty
    shared
    in a short window is an answer (no overlap in the window), not an error; widen the window only if the user asked for a longer one.
  • 当传入两个或更多
    channelIds
    时,
    occurrences
    会将重叠内容放在
    shared
    中;仅查看
    rows
    永远不会显示重叠项。
  • 不要使用
    episodes
    的数量衡量节目规模;应使用
    status({ channelId }).channel.searchable_videos
    作为数量。
  • 在较短时间范围内,
    shared
    为空本身就是有效结论(该范围内没有重叠内容),并非错误;只有当用户要求更长范围时才扩大时间窗口。

After the answer

回答之后

Monitors can follow what a research turn found, and each alert uses 25 credits from the account's plan, then its on-demand budget. The
company-watch
skill sets one up.
If anything was wrong, slow, or missing for the user, send one arcmira_feedback.
监控项可以持续跟踪某一轮研究检索发现的内容;每条提醒会先从账户套餐中消耗 25 个 credits,然后从按需预算中扣除。
company-watch
skill 可以完成设置。
如果结果存在错误、响应缓慢或对用户而言有缺失,则发送一条 arcmira_feedback。