| 模块 | 现状 | 评价 |
|---|---|---|
| 节目类型定义 | 11 种(talk, interview, news, drama, entertainment, story, history, science, mystery, nighttalk, music) | 丰富但利用不足 |
| 角色系统 | 动态选角 + 30 种音色 | 优秀 |
| 时长配置 | MAIN_DURATION = 480s(8分钟) | 合理但可扩展 |
| 音乐多样性 | ReAct 工具链 + 多样性检查 | 成熟 |
问题 1:节目类型未被充分使用
// cast-system.ts:455-458
// 实际 regularPool 排除了 news 和 drama
const regularPool: ShowType[] = [
'talk', 'interview', 'story', 'history',
'science', 'mystery', 'entertainment', 'music'
];问题 2:Prompt 对内容深度引导不足
// writer-agent.ts:734
// 只要求 3-5 句台词,内容自然偏浅
"每个 talk 块至少 3-5 句台词"问题 3:缺乏节目环节结构
- 当前只有 Block 概念(talk/music/control)
- 没有"开场 → 主体环节 → 互动 → 结尾"的节目流程设计
问题 4:生成的"脱口秀"本质是"鸡汤文+音乐"
- AI 缺乏具体的对话模式指导
- 没有冲突、互动、观点碰撞的引导
概念设计:在 Block 之上增加 Segment 层级,定义节目的结构化流程。
// 新增类型定义
interface ShowSegment {
type: SegmentType;
name: string;
durationHint: [number, number]; // [最短, 最长] 秒
blocks: TimelineBlock[];
}
type SegmentType =
| 'opening' // 开场白
| 'main_topic' // 主话题讨论
| 'sub_topic' // 子话题/延伸
| 'interaction' // 互动环节(问答/来信/猜谜)
| 'music_break' // 音乐间歇
| 'story_time' // 故事时间
| 'news_flash' // 新闻快讯
| 'closing'; // 结尾
// 节目模板示例
const TALK_SHOW_STRUCTURE: SegmentType[] = [
'opening', // 30-60s 开场
'main_topic', // 180-300s 主话题深入讨论
'music_break', // 180-240s 音乐
'sub_topic', // 120-180s 延伸话题
'interaction', // 60-120s 听众互动
'music_break', // 180-240s 音乐
'closing' // 30-60s 结尾
];实现路径:
- 在
radio-core.ts增加 Segment 类型定义 - 修改
writer-agent.ts的 Prompt,按 Segment 引导生成 - 可选:增加
segment-templates.ts预设不同节目类型的环节结构
问题:当前 AI 生成的对话趋于单一,缺乏真实对话的多样性。
解决方案:在 Prompt 中注入对话模式示例。
const DIALOGUE_PATTERNS = {
// 辩论模式
debate: `
A: 提出观点
B: 提出反对意见
A: 用例子反驳
B: 承认部分道理,但补充新角度
A+B: 达成某种共识或保留分歧
`,
// 叙事接力
storytelling: `
A: 开始讲一个故事/经历
B: 插入提问或惊叹
A: 继续故事
B: 联想到自己的类似经历
A: 回应B的经历,引出感悟
`,
// 知识问答
teacherStudent: `
A: 提出一个问题/好奇
B: 解释原理
A: 追问"为什么"
B: 深入解释
A: 用生活例子确认理解
B: 补充有趣的延伸知识
`,
// 吐槽模式
roast: `
A: 描述一个现象/事件
B: 犀利吐槽
A: 补充更多槽点
B: 升华吐槽(从个例到普遍)
A: 反转/自嘲
`,
// 深夜倾诉
confession: `
A: 抛出一个深夜话题
B: 共情回应
A: 分享个人故事
B: 温柔点评
A+B: 一起感慨
`
};实现位置:writer-agent.ts 的 buildReActSystemPrompt() 方法,根据节目类型注入对应模式。
当前限制:
// cast-system.ts:455-456
// 排除 news(低频)和 drama(复杂度高)解除限制步骤:
依赖:已有 NEWS_SERVICE 配置 (constants.ts:122-128)
实现方案:
- 创建
news-agent.ts,调用新闻 API 获取实时新闻 - 增加
NewsBlock类型,或在 TalkBlock 中标记isNews: true - 在
writer-agent.ts中增加新闻获取工具
// 新工具定义
{
name: 'fetch_news',
description: '获取最新新闻摘要',
args: { count: number, category?: string }
}挑战:多角色、剧本结构复杂、需要音效
渐进实现:
-
Phase 1:微型广播剧(2-3 分钟片段)
- 限制 2-3 个角色
- 简单的场景描述
- 无需复杂音效
-
Phase 2:系列广播剧
- 引入"剧集"概念,跨多期播出
- 增加
previousContext存储剧情进展
-
Phase 3:完整广播剧
- 音效支持(脚步声、门声等)
- 多声道混音
需求:脱口秀、吐槽大会、新闻播报等以对话/独白为主的节目形式。
实现方案:引入"节目风格"配置。
interface ShowStyle {
type: ShowType;
musicRatio: number; // 音乐占比 0-1
talkDepth: 'shallow' | 'medium' | 'deep';
interactionLevel: 'none' | 'low' | 'high';
pacing: 'fast' | 'medium' | 'slow';
}
const SHOW_STYLES: Record<ShowType, ShowStyle> = {
talk: { musicRatio: 0.3, talkDepth: 'medium', interactionLevel: 'low', pacing: 'medium' },
entertainment: { musicRatio: 0.2, talkDepth: 'shallow', interactionLevel: 'high', pacing: 'fast' },
news: { musicRatio: 0.1, talkDepth: 'shallow', interactionLevel: 'none', pacing: 'fast' },
nighttalk: { musicRatio: 0.4, talkDepth: 'deep', interactionLevel: 'medium', pacing: 'slow' },
history: { musicRatio: 0.2, talkDepth: 'deep', interactionLevel: 'none', pacing: 'medium' },
mystery: { musicRatio: 0.3, talkDepth: 'deep', interactionLevel: 'none', pacing: 'slow' },
// ...
};Prompt 调整:根据 talkDepth 调整对话要求。
const DEPTH_REQUIREMENTS = {
shallow: '每个话题点到为止,保持节奏明快',
medium: '每个话题展开 2-3 个层面,有一定深度',
deep: '深入探讨话题的多个维度,包括背景、原因、影响、个人感受等'
};当前配置:
SHOW.MAIN_DURATION: 480 // 8分钟优化建议:
// 根据节目类型自动调整时长
const SHOW_DURATIONS: Record<ShowType, [number, number]> = {
talk: [360, 600], // 6-10分钟
news: [180, 300], // 3-5分钟
history: [480, 720], // 8-12分钟
drama: [300, 600], // 5-10分钟
mystery: [480, 720], // 8-12分钟
// ...
};// 根据节目类型调整台词要求
const SCRIPT_DENSITY = {
talk: { minLinesPerBlock: 5, minWordsPerLine: 20 },
history: { minLinesPerBlock: 8, minWordsPerLine: 30 },
news: { minLinesPerBlock: 3, minWordsPerLine: 40 },
entertainment: { minLinesPerBlock: 6, minWordsPerLine: 15 },
};问题:节目缺乏真实电台的"呼吸感"。
解决方案:
// 新增过渡类型
interface TransitionElement {
type: 'jingle' | 'station_id' | 'time_check' | 'weather' | 'ad_break';
duration: number;
content?: string;
}当前 time-announcement 服务已实现,可扩展为:
- 增加天气播报
- 增加"下期预告"
- 增加"听众互动提示"
在 TTS 前对文本进行口语化处理:
const oralizeText = (text: string): string => {
return text
.replace(/。/g, '。…') // 添加自然停顿
.replace(/,/g, ',')
.replace(/!/g, '!…')
// 添加语气词
.replace(/^/gm, (match) => Math.random() > 0.7 ? '嗯,' : match)
// ...
};现有基础:mailQueue 收集用户消息
扩展方向:
type InteractionType =
| 'letter_reading' // 读信
| 'song_request' // 点歌
| 'question' // 问答
| 'story_share' // 故事分享
| 'topic_vote'; // 话题投票AI 生成虚拟听众互动:
// 在 Prompt 中引导生成虚拟互动
`偶尔可以模拟听众互动,如:
- "刚才有听众发来消息说..."
- "有朋友问到..."
- "看到弹幕里有人提到..."
这样可以增加节目的真实感和互动感。`| 优化项 | 改动范围 | 预期效果 |
|---|---|---|
| 启用更多节目类型 | cast-system.ts | 节目多样性 +50% |
| 丰富对话模式模板 | writer-agent.ts | 对话质量 +30% |
| 调整内容深度要求 | writer-agent.ts | 内容密度 +40% |
| 优化项 | 改动范围 | 预期效果 |
|---|---|---|
| Segment 环节系统 | radio-core.ts, writer-agent.ts | 节目结构专业度 +60% |
| 节目风格配置 | 新文件 + writer-agent.ts | 节目特色差异化 |
| 可变时长支持 | constants.ts, director-agent.ts | 节目节奏自然度 +30% |
| 优化项 | 改动范围 | 预期效果 |
|---|---|---|
| News 新闻播报 | 新增 news-agent.ts | 新节目类型 |
| Drama 广播剧 | 多文件改动 | 新节目类型 |
| 听众互动增强 | mail-queue 扩展 | 互动感 +50% |
文件:src/features/content/lib/cast-system.ts
// 修改 randomShowType() 方法
randomShowType(): ShowType {
// 移除类型限制,让所有类型都有机会出现
const allTypes: ShowType[] = [
'talk', 'interview', 'news', 'drama', 'entertainment',
'story', 'history', 'science', 'mystery', 'nighttalk', 'music'
];
// 权重配置(可调)
const weights: Record<ShowType, number> = {
talk: 15,
interview: 10,
news: 5, // 较低频率
drama: 5, // 较低频率
entertainment: 12,
story: 10,
history: 10,
science: 10,
mystery: 10,
nighttalk: 8,
music: 5
};
// 加权随机选择
const totalWeight = Object.values(weights).reduce((a, b) => a + b, 0);
let random = Math.random() * totalWeight;
for (const [type, weight] of Object.entries(weights)) {
random -= weight;
if (random <= 0) return type as ShowType;
}
return 'talk';
}文件:src/features/content/lib/writer-agent.ts
在 buildReActSystemPrompt() 中增加:
private getDialogueGuidance(showType: ShowType): string {
const patterns: Record<string, string> = {
talk: `
## 对话模式指南
请使用以下对话模式之一(随机选择或混合使用):
**辩论式**:A提观点 → B反驳 → A举例 → B让步但补充 → 达成共识
**叙事接力**:A讲故事 → B插话 → A继续 → B分享类似经历 → 共同感慨
**吐槽式**:A描述现象 → B吐槽 → A补充槽点 → B升华 → A自嘲
每个对话回合至少 8-10 句,要有来有往,不要一人独白太久。
`,
history: `
## 叙事指南
- 使用生动的细节描述历史场景
- 穿插历史人物的"独白"或"对话"演绎
- 用现代视角点评历史事件
- 每个历史故事至少讲 3-5 分钟
`,
entertainment: `
## 娱乐节目指南
- 节奏快,互动多
- 多用"接梗"、"反转"、"夸张"的表达
- 可以设计小游戏或问答环节
- 保持轻松搞笑的氛围
`,
mystery: `
## 悬疑叙事指南
- 营造神秘氛围(语速放慢,用词考究)
- 设置悬念,分阶段揭示
- 可以有"当事人"第一人称叙述
- 结尾可以保留开放性
`,
// ... 其他类型
};
return patterns[showType] || patterns.talk;
}文件:src/features/content/lib/writer-agent.ts
修改 getOutputFormatExample() 中的示例和要求:
## 内容密度要求
### Talk Block 要求
- **最少台词数**:8-12 句(不是 3-5 句!)
- **单句长度**:15-50 字
- **对话节奏**:不超过 3 句连续由同一人说
### 内容深度要求
- 每个话题展开至少 2-3 个层面
- 包含具体的例子或故事
- 有个人观点和感受的表达
- 避免空洞的鸡汤式表达
### 禁止的表达模式
❌ "生活就是这样"
❌ "我们要积极向上"
❌ 没有具体内容的抒情
❌ 一个人说超过 5 句
### 期望的表达模式
✅ 具体的故事或经历
✅ 有观点碰撞的对话
✅ 幽默或机智的表达
✅ 意料之外的转折RadioNowhere 已具备良好的技术基础,主要问题在于内容生成策略过于保守和Prompt 引导不够具体。通过以上优化方向,可以显著提升节目的丰富度和真实感,让它真正像一个有趣的网络电台,而不是"AI 读鸡汤配音乐"。
核心改进思路:
- 放开节目类型限制 → 多样性
- 注入对话模式模板 → 对话质量
- 提高内容密度要求 → 信息量
- 引入环节结构 → 专业感
- 增加过渡元素 → 真实感