# What解构业务技术设计文档 v1.0
## 1. PRD目标解析
### 1.1 核心目标
针对小红书多模态内容(图文、视频、音频),从**消费者视角**进行充分必要的What要素逆向解构,通过层级化递归深入分析,识别和提取内容中所有构成成分"what",并将这些要素结构化组织且直接关联原始多媒体素材。
### 1.2 核心价值
通过对大量内容的"What"要素进行聚合分析,提取爆款内容的内容特征与新兴趋势,为创作者提供可参考的、经过验证的成功要素组合,提升内容创作的确定性。
### 1.3 关键特征
- **递归深入**:最多10层的递归解构
- **多模态**:支持图片、视频、音频、文本
- **层级化**:输出树状结构的元素关系
- **知识驱动**:通过外部知识库动态获取解构维度
- **消费者视角**:从内容消费者角度分析亮点和关键点
---
## 2. 功能需求拆解
### 2.1 核心功能清单
| 功能模块 | 功能描述 | 实现方式 |
|---------|---------|---------|
| **帖子初理解** | 理解帖子整体,提取品类、主题、关键词 | Agent组件 |
| **知识检索** | 根据query动态获取解构所需的维度知识和工具知识 | Tool组件 |
| **评论理解** | 分析评论区内容,提取消费者关注的亮点 | Agent组件 |
| **图片元素解构** | 递归解构图片中的视觉元素 | Agent组件 |
| **图片分割** | 将图片分割为多个独立的视觉元素 | Tool组件 |
| **文本元素解构** | 递归解构标题、正文、话题标签 | Agent组件 |
| **文本切分** | 将文本按知识库指导切分为子元素 | Function组件 |
| **帖子整体解构** | 从点线面体维度解构帖子整体 | Agent组件 |
| **解构结果汇总** | 将所有解构结果组织为树状JSON结构 | Function组件 |
### 2.2 输入输出定义
#### 2.2.1 系统输入
```python
{
# 必选
"multimedia_content": {
"images": ["image_path1", "image_path2", ...], # 1-9张图片
"video": "video_path", # 可选
"audio": "audio_path", # 可选
"text": {
"title": "标题原文",
"body": "正文原文",
"hashtags": ["#标签1", "#标签2", ...]
},
"metadata": {
"resolution": "1920x1080",
"format": "jpg",
"duration": 120,
...
}
},
# 必选
"comments": [
{"user": "user1", "content": "评论内容1"},
{"user": "user2", "content": "评论内容2"},
...
],
# 可选
"creator_info": {
"nickname": "创作者昵称",
"avatar": "avatar_url",
"followers": 10000,
"category": "时尚美妆"
},
# 可选
"history_baseline": {
"recent_posts": [...], # 最近20-30个帖子
"style_features": {...}
}
}
```
#### 2.2.2 系统输出
```python
{
"帖子总结": {
"总结维度1": "值1", # 动态维度,由知识库决定
"总结维度2": "值2",
...
},
"帖子包含元素": [
{
"id": "1",
"what": "元素概述",
"描述": {
"描述维度1": "值1", # 动态维度,由知识库决定
"描述维度2": "值2",
...
},
"子节点元素关系": ["关系描述1", "关系描述2", ...],
"元素重要性权重": 0.7,
"子节点元素": [
{
"id": "1_1",
"what": "1_1元素概述",
"描述": {...},
"子节点元素关系": [...],
"元素重要性权重": 0.3,
"子节点元素": [...]
},
...
]
},
...
]
}
```
---
## 3. 架构设计
### 3.1 工作流 vs 组件划分原则
根据CLAUDE.md指导原则:
- **工作流**:负责编排组件执行顺序和流程逻辑
- **组件**:实现具体业务功能
#### 3.1.1 工作流职责
1. **WhatDeconstructionWorkflow**(主工作流)
- 编排整体解构流程
- 控制递归深度(最多10层)
- 管理状态传递
- 协调各Agent/Tool/Function的调用顺序
#### 3.1.2 组件职责
根据任务特征选择组件类型:
- **不确定性任务** → Agent(需要LLM推理、多模态理解、语义分析)
- **确定性任务 + 需要Agent调用** → Tool
- **确定性任务 + 不需要Agent调用** → Function
---
## 4. 组件设计
### 4.1 Agent组件设计(核心业务逻辑)
#### 4.1.1 PostUnderstandingAgent(帖子初理解Agent)
**组件类型**:Agent(BaseLLMAgent)
**选择依据**:
- PRD依据:3.1节 "帖子初理解,输出品类、主题、关键词"
- 需要LLM的语义理解能力
- 需要多模态理解能力(图文混合)
- 任务具有不确定性
**功能定义**:
- 输入:帖子的多模态内容(图片、文本)
- 输出:品类、主题、关键词列表
- 处理逻辑:综合分析图片视觉风格、文本语义、话题标签,推理帖子的核心主题
**关键点**:
1. 多模态融合理解(图文结合)
2. 提取结构化信息(品类、主题、关键词)
3. 为后续知识检索提供query参数
**代码框架**:
```python
class PostUnderstandingAgent(BaseLLMAgent):
"""帖子初理解Agent"""
async def ainvoke(self, state: WhatDeconstructionState) -> dict:
"""
分析帖子多模态内容,提取品类、主题、关键词
"""
# 1. 获取图片和文本内容
images = state.get("images")
text = state.get("text")
# 2. 构建多模态prompt
prompt = self._build_understanding_prompt(images, text)
# 3. 调用LLM进行理解
result = await self.llm.ainvoke(prompt)
# 4. 解析返回的品类、主题、关键词
parsed_result = self._parse_result(result)
return {
"category": parsed_result["category"],
"theme": parsed_result["theme"],
"keywords": parsed_result["keywords"]
}
```
---
#### 4.1.2 CommentAnalysisAgent(评论理解Agent)
**组件类型**:Agent(BaseLLMAgent)
**选择依据**:
- PRD依据:2.1.4节 "评论信息用于提取内容消费者关注的亮点"
- 需要LLM的语义理解和情感分析能力
- 需要识别隐含的消费者关注点
- 任务具有不确定性
**功能定义**:
- 输入:评论区文字内容列表
- 输出:消费者关注的亮点列表(对应帖子的哪些元素)
- 处理逻辑:分析评论中的高频词、情感倾向、提及的具体元素
**关键点**:
1. 情感分析(共鸣点、兴趣点)
2. 关键点提取(评论中提到的具体内容元素)
3. 聚合分析(多条评论的共同关注点)
4. 与帖子内容的映射关系
**代码框架**:
```python
class CommentAnalysisAgent(BaseLLMAgent):
"""评论理解Agent"""
async def ainvoke(self, state: WhatDeconstructionState) -> dict:
"""
分析评论区内容,提取消费者关注的亮点
"""
# 1. 获取评论数据
comments = state.get("comments")
post_content = state.get("text")
# 2. 构建分析prompt
prompt = self._build_comment_analysis_prompt(comments, post_content)
# 3. 调用LLM分析
result = await self.llm.ainvoke(prompt)
# 4. 提取亮点并与帖子内容映射
highlights = self._extract_highlights(result)
return {
"consumer_highlights": highlights
}
```
---
#### 4.1.3 RecursiveImageDeconstructionAgent(图片递归解构Agent)
**组件类型**:Agent(BaseReactAgent)
**选择依据**:
- PRD依据:3.3节 "对单一节点的递归解构"
- 需要LLM的视觉理解能力
- 需要动态调用知识库和图片分割工具(ReAct模式)
- 需要递归判断是否继续分割
- 任务具有高度不确定性
**功能定义**:
- 输入:当前图片节点、父节点信息、递归深度
- 输出:图片的what描述、描述维度、子元素列表
- 处理逻辑:
1. 粗理解图片,生成what字段值
2. 根据what值生成query,调用知识库获取描述维度
3. 根据描述维度细致理解图片,填充描述值
4. 判断是否需要继续分割(调用知识库)
5. 如需分割,调用图片分割工具,递归处理子元素
**关键点**:
1. **ReAct模式**:思考→行动→观察的循环(调用知识库、调用分割工具)
2. **递归控制**:深度限制(10层)、停止条件判断
3. **知识库交互**:动态生成query获取解构维度
4. **图片分割判断**:优先判断是否为多子图拼接
5. **多模态理解**:将视觉信息转化为文字描述
**代码框架**:
```python
class RecursiveImageDeconstructionAgent(BaseReactAgent):
"""图片递归解构Agent"""
def __init__(self, llm, tools: List[BaseTool], max_depth: int = 10):
super().__init__(llm, tools)
self.max_depth = max_depth
self.knowledge_retrieval_tool = None # 知识检索工具
self.image_segment_tool = None # 图片分割工具
async def ainvoke(self, state: WhatDeconstructionState) -> dict:
"""
递归解构图片元素
"""
# 1. 获取当前节点信息
current_image = state.get("current_image")
parent_id = state.get("parent_id", "")
depth = state.get("depth", 0)
# 检查递归深度
if depth >= self.max_depth:
return {"continue_decompose": False}
# 2. 粗理解图片(生成what字段)
what_value = await self._rough_understanding(current_image)
# 3. 生成query,获取描述维度
query = self._generate_description_query(what_value)
description_dimensions = await self.knowledge_retrieval_tool.ainvoke(query)
# 4. 根据描述维度细致理解图片
description_values = await self._detailed_understanding(
current_image, description_dimensions
)
# 5. 判断是否需要继续分割
split_query = self._generate_split_query(what_value, description_values)
should_split = await self.knowledge_retrieval_tool.ainvoke(split_query)
result = {
"what": what_value,
"description": description_values,
"continue_decompose": should_split
}
# 6. 如需分割,执行分割并递归
if should_split:
# 判断是否为多子图拼接
sub_elements = await self._identify_sub_elements(current_image)
if sub_elements:
# 调用图片分割工具
segmented_images = await self.image_segment_tool.ainvoke(
image=current_image,
elements_description=sub_elements
)
# 递归处理子元素
children = []
for idx, sub_img in enumerate(segmented_images):
child_state = {
"current_image": sub_img,
"parent_id": f"{parent_id}_{idx+1}",
"depth": depth + 1
}
child_result = await self.ainvoke(child_state)
children.append(child_result)
result["children"] = children
return result
```
---
#### 4.1.4 RecursiveTextDeconstructionAgent(文本递归解构Agent)
**组件类型**:Agent(BaseReactAgent)
**选择依据**:
- PRD依据:3.3节 "对单一节点的递归解构"
- 需要LLM的文本语义理解能力
- 需要动态调用知识库和文本切分工具
- 需要递归判断是否继续切分
- 任务具有不确定性
**功能定义**:
- 输入:当前文本节点(标题/正文/标签)、父节点信息、递归深度
- 输出:文本的what描述、描述维度、子元素列表
- 处理逻辑:与图片解构类似,但针对文本元素
**关键点**:
1. **文本原文保留**:当节点是文本时,what字段必须是原文,不可改写
2. **语义切分**:根据知识库指导切分文本结构
3. **递归控制**:深度限制(10层)
4. **充分必要原则**:子节点文本必须完整覆盖父节点文本
**代码框架**:
```python
class RecursiveTextDeconstructionAgent(BaseReactAgent):
"""文本递归解构Agent"""
def __init__(self, llm, tools: List[BaseTool], max_depth: int = 10):
super().__init__(llm, tools)
self.max_depth = max_depth
self.knowledge_retrieval_tool = None
self.text_split_tool = None
async def ainvoke(self, state: WhatDeconstructionState) -> dict:
"""
递归解构文本元素
"""
# 1. 获取当前节点信息
current_text = state.get("current_text")
text_type = state.get("text_type") # title/body/hashtags
parent_id = state.get("parent_id", "")
depth = state.get("depth", 0)
if depth >= self.max_depth:
return {"continue_decompose": False}
# 2. what字段直接使用原文
what_value = current_text
# 3. 生成query,获取描述维度
query = self._generate_description_query(what_value, text_type)
description_dimensions = await self.knowledge_retrieval_tool.ainvoke(query)
# 4. 根据描述维度分析文本
description_values = await self._analyze_text(
current_text, description_dimensions
)
# 5. 判断是否需要继续切分
split_query = self._generate_split_query(what_value, description_values)
should_split = await self.knowledge_retrieval_tool.ainvoke(split_query)
result = {
"what": what_value,
"description": description_values,
"continue_decompose": should_split
}
# 6. 如需切分,执行切分并递归
if should_split:
# 根据知识库指导切分文本
split_result = await self.text_split_tool.ainvoke(
text=current_text,
split_guidance=description_dimensions
)
# 递归处理子元素
children = []
for idx, sub_text in enumerate(split_result):
child_state = {
"current_text": sub_text,
"text_type": text_type,
"parent_id": f"{parent_id}_{idx+1}",
"depth": depth + 1
}
child_result = await self.ainvoke(child_state)
children.append(child_result)
result["children"] = children
return result
```
---
#### 4.1.5 PostSummaryDeconstructionAgent(帖子整体解构Agent)
**组件类型**:Agent(BaseLLMAgent)
**选择依据**:
- PRD依据:3.2节 "帖子整体解构环节"
- 需要LLM的综合理解能力
- 需要从点线面体维度抽象总结
- 任务具有不确定性
**功能定义**:
- 输入:帖子的所有元素解构结果、知识库返回的总结维度
- 输出:帖子总结对象(动态维度)
- 处理逻辑:综合所有子元素的解构结果,从宏观维度总结帖子特征
**关键点**:
1. 动态总结维度(由知识库决定)
2. 综合多模态元素的解构结果
3. 从整体视角抽象提炼
4. 包含消费者亮点维度
**代码框架**:
```python
class PostSummaryDeconstructionAgent(BaseLLMAgent):
"""帖子整体解构Agent"""
async def ainvoke(self, state: WhatDeconstructionState) -> dict:
"""
从点线面体维度解构帖子整体
"""
# 1. 获取所有子元素解构结果
image_results = state.get("image_deconstruction_results")
text_results = state.get("text_deconstruction_results")
consumer_highlights = state.get("consumer_highlights")
# 2. 获取总结维度(通过知识库)
category = state.get("category")
theme = state.get("theme")
keywords = state.get("keywords")
query = self._generate_summary_query(category, theme, keywords)
summary_dimensions = await self._call_knowledge_retrieval(query)
# 3. 根据总结维度综合分析
prompt = self._build_summary_prompt(
image_results, text_results, consumer_highlights, summary_dimensions
)
result = await self.llm.ainvoke(prompt)
# 4. 解析总结结果
summary = self._parse_summary(result, summary_dimensions)
return {
"post_summary": summary
}
def _generate_summary_query(self, category, theme, keywords):
"""生成总结维度query"""
return f"""对于一篇主题为"{theme}",品类为"{category}",关键词包含"{', '.join(keywords)}"的多模态社交媒体帖子,从内容创作者视角进行What要素的初步识别和分类,需要使用哪些通用工具?"""
```
---
### 4.2 Tool组件设计(可被Agent调用)
#### 4.2.1 KnowledgeRetrievalTool(知识检索工具)
**组件类型**:Tool(BaseTool)
**选择依据**:
- PRD依据:3.2节、3.3.2节"对单一节点解构如何获取知识"
- 需要被Agent调用(各解构Agent都需要调用)
- 任务确定性(API调用)
**功能定义**:
- 输入:query字符串
- 输出:知识库返回的结果(描述维度、工具推荐、判断结果等)
- 处理逻辑:调用外部知识库API,解析返回结果
**关键点**:
1. 支持多种query类型(描述维度、工具知识、分割判断)
2. 结果格式化(转换为Agent可用的结构化数据)
3. 错误处理和降级(知识库不可用时使用LLM默认知识)
**代码框架**:
```python
from tools.base import BaseTool
from typing import Dict, Any
class KnowledgeRetrievalTool(BaseTool):
"""知识检索工具"""
name: str = "knowledge_retrieval"
description: str = "根据query检索What解构所需的知识(描述维度、工具推荐、分割判断等)"
def __init__(self, knowledge_base_url: str):
super().__init__()
self.knowledge_base_url = knowledge_base_url
async def _arun(self, query: str, query_type: str = "description") -> Dict[str, Any]:
"""
调用知识库检索
Args:
query: 查询语句
query_type: 查询类型(description/tool/split_decision)
"""
# 1. 调用知识库API
response = await self._call_knowledge_base(query)
# 2. 根据query类型解析结果
if query_type == "description":
# 返回描述维度列表
return self._parse_description_dimensions(response)
elif query_type == "tool":
# 返回推荐工具列表
return self._parse_tool_recommendations(response)
elif query_type == "split_decision":
# 返回是否分割的判断
return self._parse_split_decision(response)
return response
def _parse_description_dimensions(self, response) -> Dict[str, Any]:
"""解析描述维度"""
return {
"dimensions": response.get("dimensions", []),
"count": len(response.get("dimensions", []))
}
```
**复用决策**:
- 现有组件:`tools/knowledge_retrieval_tools.py` 已存在知识检索工具
- 决策:**复用并修改**
- 理由:现有工具实现了基本的知识库查询功能,但需要增强支持本PRD中的多种query类型
---
#### 4.2.2 ImageSegmentTool(图片分割工具)
**组件类型**:Tool(BaseTool)
**选择依据**:
- PRD依据:3.3.1节 "判断图片元素是否要继续分割拆解"
- 需要被Agent调用(RecursiveImageDeconstructionAgent调用)
- 任务确定性(调用分割模型)
**功能定义**:
- 输入:图片路径、子元素文字描述列表
- 输出:分割后的子图片路径列表
- 处理逻辑:调用图片分割模型(如SAM、GroundingDINO等),根据文字描述分割图片
**关键点**:
1. 支持多种分割模式(完整子图拼接拆解、视觉元素抠图)
2. 保存分割结果并返回路径
3. 分割质量验证
**代码框架**:
```python
from tools.base import BaseTool
from typing import List
class ImageSegmentTool(BaseTool):
"""图片分割工具"""
name: str = "image_segment"
description: str = "根据文字描述将图片分割为多个独立的视觉元素"
def __init__(self, segment_model, output_dir: str):
super().__init__()
self.segment_model = segment_model
self.output_dir = output_dir
async def _arun(
self,
image_path: str,
elements_description: List[str],
segment_type: str = "object" # object/grid
) -> List[str]:
"""
分割图片
Args:
image_path: 原始图片路径
elements_description: 子元素文字描述列表
segment_type: 分割类型(object: 视觉元素分割, grid: 子图拼接拆解)
Returns:
分割后的子图片路径列表
"""
# 1. 加载图片
image = self._load_image(image_path)
# 2. 根据分割类型选择策略
if segment_type == "grid":
# 拼接图拆解(简单切割)
sub_images = self._grid_split(image, elements_description)
else:
# 视觉元素分割(调用分割模型)
sub_images = await self._segment_objects(image, elements_description)
# 3. 保存子图片
saved_paths = []
for idx, sub_img in enumerate(sub_images):
save_path = f"{self.output_dir}/{self._generate_filename(idx)}"
self._save_image(sub_img, save_path)
saved_paths.append(save_path)
return saved_paths
async def _segment_objects(self, image, descriptions):
"""调用分割模型分割视觉元素"""
# 调用SAM/GroundingDINO等模型
masks = await self.segment_model.segment(image, descriptions)
return self._extract_objects(image, masks)
```
**复用决策**:
- 现有组件:`tools/segment_tools.py` 已存在图片分割工具
- 决策:**直接复用**
- 理由:现有工具已实现"根据对象名称对图像进行分割,抽取指定对象的切片"功能,完全符合本PRD需求
---
### 4.3 Function组件设计(不可被Agent调用)
#### 4.3.1 TextSplitFunction(文本切分函数)
**组件类型**:Function(BaseFunction)
**选择依据**:
- PRD依据:3.5节 "文本切分工具"
- 不需要被Agent直接调用(在工作流中调用)
- 任务确定性(字符串处理)
**功能定义**:
- 输入:文本字符串、切分规则(由知识库返回)
- 输出:切分后的子文本列表
- 处理逻辑:根据切分规则(句子、段落、语义块)切分文本
**关键点**:
1. 多种切分策略(按句、按段、按语义)
2. 保留原文完整性(子文本合并后等于父文本)
3. 不重复不遗漏
**代码框架**:
```python
from functions.base import BaseFunction
from typing import List, Dict
class TextSplitFunction(BaseFunction):
"""文本切分函数"""
def __init__(self):
super().__init__()
def invoke(self, text: str, split_rules: Dict) -> List[str]:
"""
切分文本
Args:
text: 待切分文本
split_rules: 切分规则(由知识库返回)
{
"strategy": "sentence/paragraph/semantic",
"params": {...}
}
Returns:
切分后的子文本列表
"""
strategy = split_rules.get("strategy", "sentence")
if strategy == "sentence":
return self._split_by_sentence(text)
elif strategy == "paragraph":
return self._split_by_paragraph(text)
elif strategy == "semantic":
return self._split_by_semantic(text, split_rules.get("params"))
return [text]
def _split_by_sentence(self, text: str) -> List[str]:
"""按句子切分"""
import re
sentences = re.split(r'[。!?\n]', text)
return [s.strip() for s in sentences if s.strip()]
def _split_by_paragraph(self, text: str) -> List[str]:
"""按段落切分"""
paragraphs = text.split('\n\n')
return [p.strip() for p in paragraphs if p.strip()]
def _split_by_semantic(self, text: str, params: Dict) -> List[str]:
"""按语义块切分(需要语义模型)"""
# TODO: 实现语义切分逻辑
pass
```
**复用决策**:
- 现有组件:无
- 决策:**完全新增**
- 理由:项目中不存在文本切分功能,需要从BaseFunction新建
---
#### 4.3.2 ResultAggregationFunction(结果汇总函数)
**组件类型**:Function(BaseFunction)
**选择依据**:
- 任务确定性(数据结构转换)
- 不需要被Agent调用(工作流最后环节)
**功能定义**:
- 输入:各Agent的解构结果
- 输出:最终的树状JSON结构
- 处理逻辑:将分散的解构结果组装为符合PRD格式的JSON
**关键点**:
1. 递归组装树状结构
2. 字段格式验证
3. ID生成规则
4. 元素重要性权重计算
**代码框架**:
```python
from functions.base import BaseFunction
from typing import Dict, List
class ResultAggregationFunction(BaseFunction):
"""结果汇总函数"""
def invoke(self, state: Dict) -> Dict:
"""
汇总所有解构结果为树状JSON
Args:
state: 工作流状态,包含所有解构结果
Returns:
最终的树状JSON结构
"""
# 1. 提取各部分结果
post_summary = state.get("post_summary")
image_results = state.get("image_deconstruction_results")
text_results = state.get("text_deconstruction_results")
# 2. 构建树状结构
elements = []
# 添加图片元素
for idx, img_result in enumerate(image_results):
element = self._build_element_tree(
id=f"{idx+1}",
result=img_result,
element_type="image"
)
elements.append(element)
# 添加文本元素
text_id_start = len(image_results) + 1
for idx, text_result in enumerate(text_results):
element = self._build_element_tree(
id=f"{text_id_start+idx}",
result=text_result,
element_type="text"
)
elements.append(element)
# 3. 组装最终JSON
final_result = {
"帖子总结": post_summary,
"帖子包含元素": elements
}
# 4. 验证JSON格式
self._validate_result(final_result)
return final_result
def _build_element_tree(self, id: str, result: Dict, element_type: str) -> Dict:
"""递归构建元素树"""
element = {
"id": id,
"what": result["what"],
"描述": result["description"],
"子节点元素关系": result.get("relationships", []),
"元素重要性权重": result.get("importance_weight", 0.5),
"子节点元素": []
}
# 递归处理子节点
if "children" in result:
for idx, child in enumerate(result["children"]):
child_element = self._build_element_tree(
id=f"{id}_{idx+1}",
result=child,
element_type=element_type
)
element["子节点元素"].append(child_element)
return element
```
**复用决策**:
- 现有组件:`functions/json_utils.py` 存在JSON处理函数
- 决策:**复用并修改**
- 理由:可复用JSON格式化和验证功能,但需新增树状结构构建逻辑
---
## 5. 工作流设计
### 5.1 WhatDeconstructionWorkflow(主工作流)
**继承基类**:BaseGraphAgent(LangGraph)
**状态定义**:
```python
from typing import TypedDict, List, Dict, Any
class WhatDeconstructionState(TypedDict):
# 输入数据
images: List[str]
video: str
audio: str
text: Dict[str, Any] # {title, body, hashtags}
comments: List[Dict[str, str]]
creator_info: Dict[str, Any]
# 中间状态
category: str
theme: str
keywords: List[str]
consumer_highlights: List[Dict]
# 解构结果
image_deconstruction_results: List[Dict]
text_deconstruction_results: List[Dict]
post_summary: Dict[str, Any]
# 最终输出
final_result: Dict[str, Any]
# 递归控制
current_depth: int
max_depth: int
```
**节点定义**:
```python
nodes = {
"post_understanding": PostUnderstandingAgent,
"comment_analysis": CommentAnalysisAgent,
"image_deconstruction": RecursiveImageDeconstructionAgent,
"text_deconstruction": RecursiveTextDeconstructionAgent,
"post_summary": PostSummaryDeconstructionAgent,
"result_aggregation": ResultAggregationFunction
}
```
**流程图**:
```mermaid
graph TD
START([开始]) --> A[帖子初理解
PostUnderstandingAgent]
A --> B[评论理解
CommentAnalysisAgent]
B --> C{并行解构}
C --> D[图片递归解构
RecursiveImageDeconstructionAgent]
C --> E[文本递归解构
RecursiveTextDeconstructionAgent]
D --> F[帖子整体解构
PostSummaryDeconstructionAgent]
E --> F
F --> G[结果汇总
ResultAggregationFunction]
G --> END([结束])
```
**核心代码**:
```python
from langgraph.graph import StateGraph
from agents.base import BaseGraphAgent
class WhatDeconstructionWorkflow(BaseGraphAgent):
"""What解构主工作流"""
def __init__(self, llm, tools: List[BaseTool]):
super().__init__()
self.llm = llm
self.tools = tools
# 初始化所有组件
self.post_understanding_agent = PostUnderstandingAgent(llm)
self.comment_analysis_agent = CommentAnalysisAgent(llm)
self.image_deconstruction_agent = RecursiveImageDeconstructionAgent(
llm, tools, max_depth=10
)
self.text_deconstruction_agent = RecursiveTextDeconstructionAgent(
llm, tools, max_depth=10
)
self.post_summary_agent = PostSummaryDeconstructionAgent(llm)
self.result_aggregation_func = ResultAggregationFunction()
# 构建工作流图
self.graph = self._build_graph()
def _build_graph(self) -> StateGraph:
"""构建LangGraph工作流"""
workflow = StateGraph(WhatDeconstructionState)
# 添加节点
workflow.add_node("post_understanding", self._post_understanding_node)
workflow.add_node("comment_analysis", self._comment_analysis_node)
workflow.add_node("image_deconstruction", self._image_deconstruction_node)
workflow.add_node("text_deconstruction", self._text_deconstruction_node)
workflow.add_node("post_summary", self._post_summary_node)
workflow.add_node("result_aggregation", self._result_aggregation_node)
# 定义边(流程顺序)
workflow.set_entry_point("post_understanding")
workflow.add_edge("post_understanding", "comment_analysis")
workflow.add_edge("comment_analysis", "image_deconstruction")
workflow.add_edge("comment_analysis", "text_deconstruction")
workflow.add_edge("image_deconstruction", "post_summary")
workflow.add_edge("text_deconstruction", "post_summary")
workflow.add_edge("post_summary", "result_aggregation")
workflow.set_finish_point("result_aggregation")
return workflow.compile()
async def _post_understanding_node(self, state: WhatDeconstructionState):
"""节点:帖子初理解"""
result = await self.post_understanding_agent.ainvoke(state)
return {
"category": result["category"],
"theme": result["theme"],
"keywords": result["keywords"]
}
async def _comment_analysis_node(self, state: WhatDeconstructionState):
"""节点:评论理解"""
result = await self.comment_analysis_agent.ainvoke(state)
return {
"consumer_highlights": result["consumer_highlights"]
}
async def _image_deconstruction_node(self, state: WhatDeconstructionState):
"""节点:图片递归解构"""
images = state.get("images", [])
results = []
for idx, image_path in enumerate(images):
img_state = {
"current_image": image_path,
"parent_id": f"image_{idx+1}",
"depth": 0,
"max_depth": 10,
"category": state["category"],
"theme": state["theme"]
}
result = await self.image_deconstruction_agent.ainvoke(img_state)
results.append(result)
return {"image_deconstruction_results": results}
async def _text_deconstruction_node(self, state: WhatDeconstructionState):
"""节点:文本递归解构"""
text_data = state.get("text", {})
results = []
# 解构标题
if text_data.get("title"):
title_state = {
"current_text": text_data["title"],
"text_type": "title",
"parent_id": "title",
"depth": 0,
"max_depth": 10
}
title_result = await self.text_deconstruction_agent.ainvoke(title_state)
results.append(title_result)
# 解构正文
if text_data.get("body"):
body_state = {
"current_text": text_data["body"],
"text_type": "body",
"parent_id": "body",
"depth": 0,
"max_depth": 10
}
body_result = await self.text_deconstruction_agent.ainvoke(body_state)
results.append(body_result)
# 解构话题标签
if text_data.get("hashtags"):
hashtags_text = " ".join(text_data["hashtags"])
hashtags_state = {
"current_text": hashtags_text,
"text_type": "hashtags",
"parent_id": "hashtags",
"depth": 0,
"max_depth": 10
}
hashtags_result = await self.text_deconstruction_agent.ainvoke(hashtags_state)
results.append(hashtags_result)
return {"text_deconstruction_results": results}
async def _post_summary_node(self, state: WhatDeconstructionState):
"""节点:帖子整体解构"""
result = await self.post_summary_agent.ainvoke(state)
return {"post_summary": result["post_summary"]}
async def _result_aggregation_node(self, state: WhatDeconstructionState):
"""节点:结果汇总"""
final_result = self.result_aggregation_func.invoke(state)
return {"final_result": final_result}
async def ainvoke(self, input_data: Dict) -> Dict:
"""执行工作流"""
# 初始化状态
initial_state = WhatDeconstructionState(
images=input_data.get("multimedia_content", {}).get("images", []),
video=input_data.get("multimedia_content", {}).get("video", ""),
audio=input_data.get("multimedia_content", {}).get("audio", ""),
text=input_data.get("multimedia_content", {}).get("text", {}),
comments=input_data.get("comments", []),
creator_info=input_data.get("creator_info", {}),
current_depth=0,
max_depth=10
)
# 执行工作流
result = await self.graph.ainvoke(initial_state)
return result["final_result"]
```
---
## 6. 数据结构设计
### 6.1 WhatDeconstructionState(工作流状态)
```python
from typing import TypedDict, List, Dict, Any, Optional
class WhatDeconstructionState(TypedDict):
"""What解构工作流状态"""
# ========== 输入数据 ==========
images: List[str] # 图片路径列表(1-9张)
video: Optional[str] # 视频路径
audio: Optional[str] # 音频路径
text: Dict[str, Any] # {title, body, hashtags}
comments: List[Dict[str, str]] # [{user, content}, ...]
creator_info: Optional[Dict[str, Any]] # 创作者信息(可选)
history_baseline: Optional[Dict[str, Any]] # 历史基准(可选)
# ========== 中间状态 ==========
category: str # 品类
theme: str # 主题
keywords: List[str] # 关键词列表
consumer_highlights: List[Dict] # 消费者关注的亮点
# ========== 解构结果 ==========
image_deconstruction_results: List[Dict] # 图片解构结果
text_deconstruction_results: List[Dict] # 文本解构结果
post_summary: Dict[str, Any] # 帖子总结
# ========== 最终输出 ==========
final_result: Dict[str, Any] # 最终的树状JSON结果
# ========== 递归控制 ==========
current_depth: int # 当前递归深度
max_depth: int # 最大递归深度(默认10)
```
### 6.2 ElementNode(元素节点结构)
```python
class ElementNode(TypedDict):
"""元素节点结构(树状结构的节点)"""
id: str # 节点ID(如 "1", "1_1", "1_1_2")
what: str # 元素概述(文本原文 or 图片描述)
描述: Dict[str, Any] # 动态描述维度(由知识库决定)
子节点元素关系: List[str] # 子节点之间的关系描述
元素重要性权重: float # 0-1之间的权重值
子节点元素: List['ElementNode'] # 递归的子节点列表
图片链接: str # 图片分解后的链接
```
### 6.3 FinalOutput(最终输出结构)
```python
class FinalOutput(TypedDict):
"""最终输出的JSON结构"""
帖子总结: Dict[str, Any] # 动态总结维度(由知识库决定)
帖子包含元素: List[ElementNode] # 元素树的根节点列表
```
---
## 7. 技术决策依据总结
### 7.1 工作流设计决策
| 决策点 | 选择 | PRD依据 | 技术理由 |
|-------|------|---------|---------|
| **工作流框架** | LangGraph | CLAUDE.md要求 | 支持状态管理、节点编排、递归控制 |
| **并行解构** | 图片和文本并行 | 3.1节流程图 | 提升效率,两者无依赖关系 |
| **递归深度** | 最多10层 | 2.2.3节 | 防止无限递归,控制计算成本 |
### 7.2 Agent组件决策
| Agent | 选择原因 | PRD依据 | 关键能力 |
|-------|---------|---------|---------|
| **PostUnderstandingAgent** | 多模态理解+语义推理 | 3.1节 | 提取品类/主题/关键词 |
| **CommentAnalysisAgent** | 情感分析+语义理解 | 2.1.4节 | 识别消费者关注点 |
| **RecursiveImageDeconstructionAgent** | ReAct模式+递归控制 | 3.3节+3.3.1节 | 动态调用工具+递归分割 |
| **RecursiveTextDeconstructionAgent** | ReAct模式+递归控制 | 3.3节 | 动态调用工具+递归切分 |
| **PostSummaryDeconstructionAgent** | 综合分析+抽象提炼 | 3.2节 | 点线面体维度总结 |
### 7.3 Tool组件决策
| Tool | 选择原因 | PRD依据 | 关键能力 |
|------|---------|---------|---------|
| **KnowledgeRetrievalTool** | Agent需调用+确定性任务 | 3.2节+3.3.2节 | 知识库API调用 |
| **ImageSegmentTool** | Agent需调用+确定性任务 | 3.3.1节+3.5节 | 图片分割模型调用 |
### 7.4 Function组件决策
| Function | 选择原因 | PRD依据 | 关键能力 |
|----------|---------|---------|---------|
| **TextSplitFunction** | 不需Agent调用+确定性任务 | 3.5节 | 文本切分逻辑 |
| **ResultAggregationFunction** | 不需Agent调用+确定性任务 | 2.2.2节 | JSON结构组装 |
### 7.5 复用决策
| 组件 | 决策 | 理由 |
|------|------|------|
| **knowledge_retrieval_tools.py** | 复用并修改 | 已有基础查询功能,需增强query类型支持 |
| **segment_tools.py** | 直接复用 | 功能完全匹配PRD需求 |
| **json_utils.py** | 复用并修改 | 可复用JSON处理,需新增树状结构构建 |
| **TextSplitFunction** | 完全新增 | 项目中无此功能 |
| **所有Agent** | 完全新增 | PRD业务逻辑全新 |
---
## 8. 实现优先级
### Phase 1: 基础框架(核心路径)
1. **WhatDeconstructionState** - 定义工作流状态
2. **PostUnderstandingAgent** - 帖子初理解
3. **KnowledgeRetrievalTool**(复用修改)- 知识检索
4. **WhatDeconstructionWorkflow** - 主工作流骨架
### Phase 2: 核心解构能力
5. **RecursiveImageDeconstructionAgent** - 图片递归解构
6. **ImageSegmentTool**(直接复用)- 图片分割
7. **RecursiveTextDeconstructionAgent** - 文本递归解构
8. **TextSplitFunction**(新增)- 文本切分
### Phase 3: 增强功能
9. **CommentAnalysisAgent** - 评论理解
10. **PostSummaryDeconstructionAgent** - 帖子整体解构
11. **ResultAggregationFunction**(复用修改)- 结果汇总
### Phase 4: 完善优化
12. 递归深度控制优化
13. 错误处理和降级策略
14. 性能优化和并行化
15. 单元测试和集成测试
---
## 9. 关键技术挑战
### 9.1 递归控制
**挑战**:如何准确判断是否停止递归?
**方案**:
- 依赖知识库返回的判断结果
- 设置硬性深度限制(10层)
- 最小元素判断(不可再分的最小语义/视觉单元)
### 9.2 知识库Query设计
**挑战**:如何动态生成有效的query?
**方案**:
- 固定句式模板 + 动态内容填充
- 多种query类型(描述维度、工具推荐、分割判断)
- 降级策略(知识库不可用时使用LLM默认知识)
### 9.3 图片分割准确性
**挑战**:如何准确分割视觉元素?
**方案**:
- 优先判断是否为多子图拼接(简单切割)
- 使用成熟的分割模型(SAM、GroundingDINO)
- LLM生成精准的元素描述文本
### 9.4 不重复不遗漏原则
**挑战**:如何保证子节点完整覆盖父节点?
**方案**:
- 文本:子节点文本合并后必须等于父节点文本
- 图片:子元素的掩码合并后必须覆盖父图片区域
- LLM验证:最后由LLM验证是否符合"充分必要"原则
---
## 10. 附录:Query模板汇总
### 10.1 帖子整体解构Query
```
对于一篇主题为"{帖子主题}",品类为"{帖子品类}",关键词包含"{帖子关键词列表}"的多模态社交媒体帖子,从内容创作者视角进行What要素的初步识别和分类,需要使用哪些通用工具?
```
### 10.2 描述维度获取Query
```
刻画描述"{元素的what字段值}"核心特征的角度和维度有哪些?请尽可能不重不漏列举全。
```
### 10.3 分割判断Query
```
该节点"{元素的what字段值}"是否需要继续拆解分割?
```
### 10.4 图片整体分割工具Query
```
对一张描述为"{图片整体内容的简要描述}"的图片,从内容创作者视角进行视觉元素分割,需要使用哪些图片分割/抠图工具?
```
### 10.5 图片亮点提取工具Query
```
从内容创作者视角,对一张描述为"{图片整体内容的简要描述}"的图片,进行亮点或关键点的提取,需要使用什么图片分析工具或大模型视觉理解工具?
```
### 10.6 图片特定元素分割工具Query
```
对一张"{XXX图片整体描述}"的图片中的"{YYY具体视觉元素描述}"的视觉元素,从内容创作者视角进行细致分割拆解,需要使用哪些高精度图片分割/抠图工具或细粒度图像理解大模型?
```
### 10.7 图片特定元素亮点提取Query
```
从内容创作者视角,对一张"{XXX图片整体描述}"的图片中的"{YYY具体视觉元素描述}"的视觉元素,进行亮点或关键点的提取,需要使用什么图像特征提取工具或专业视觉大模型?
```
### 10.8 文本段落分割工具Query
```
对一段描述为"{文本段落内容摘要}"的文本段落,从内容创作者视角进行结构化分割拆解,需要使用什么文本切分工具或文本结构化大模型?
```
### 10.9 文本段落亮点提取Query
```
从内容创作者视角,对一段描述为"{文本段落内容摘要}"的文本段落(包含标题、正文、话题标签),进行亮点或关键点的提取,需要使用什么情感分析工具、语义理解工具或文本摘要大模型?
```
---
## 11. 文件结构规划
```
project/
├── workflows/
│ └── what_deconstruction_workflow.py # 主工作流(新增)
├── agents/
│ ├── post_understanding_agent.py # 帖子初理解Agent(新增)
│ ├── comment_analysis_agent.py # 评论理解Agent(新增)
│ ├── recursive_image_deconstruction_agent.py # 图片递归解构Agent(新增)
│ ├── recursive_text_deconstruction_agent.py # 文本递归解构Agent(新增)
│ └── post_summary_deconstruction_agent.py # 帖子整体解构Agent(新增)
├── tools/
│ ├── knowledge_retrieval_tools.py # 知识检索工具(复用修改)
│ └── segment_tools.py # 图片分割工具(直接复用)
├── functions/
│ ├── text_split_function.py # 文本切分函数(新增)
│ └── result_aggregation_function.py # 结果汇总函数(复用修改)
├── states/
│ └── what_deconstruction_state.py # 工作流状态定义(新增)
└── tests/
├── test_agents/
├── test_tools/
├── test_functions/
└── test_workflow/
```
---
## 12. 总结
本技术设计文档基于PRD v1.2,完整设计了What解构业务的技术实现方案:
### 12.1 核心设计原则
- **组件化**:Agent/Tool/Function清晰分工
- **递归解构**:层级化深入分析(最多10层)
- **知识驱动**:动态从知识库获取解构维度
- **充分必要**:子节点不重不漏覆盖父节点
### 12.2 技术架构
- **1个工作流**:WhatDeconstructionWorkflow(LangGraph)
- **5个Agent**:帖子初理解、评论理解、图片递归解构、文本递归解构、帖子整体解构
- **2个Tool**:知识检索、图片分割
- **2个Function**:文本切分、结果汇总
### 12.3 复用策略
- **直接复用**:segment_tools.py
- **复用修改**:knowledge_retrieval_tools.py、json_utils.py
- **完全新增**:所有Agent、TextSplitFunction、主工作流
### 12.4 实现路径
按Phase 1-4完成全部路径