knowledge-vault/work/client-projects/MCN/张洋输入/可行性工程/process_livestream_data.py

216 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from dotenv import load_dotenv
from crewai import Agent, Task, Crew, Process
from langchain_openai import ChatOpenAI
# 加载环境变量 (OPENAI_API_KEY)
load_dotenv()
# 初始化 LLM使用 Deepseek API
# Please install OpenAI SDK first: `pip3 install openai`
llm = ChatOpenAI(
api_key=os.getenv('DEEPSEEK_API_KEY'),
base_url=os.getenv('DEEPSEEK_API_BASE'),
model_name="deepseek/deepseek-chat",
temperature=0.7,
)
# --- 全局工具和上下文加载 ---
def load_jargon_dictionary(file_path='livestream_jargon.txt'):
"""加载直播间黑话字典作为上下文"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
return f.read()
except FileNotFoundError:
print(f"警告: 黑话字典文件 {file_path} 未找到。")
return ""
# 加载字典内容
jargon_context = load_jargon_dictionary()
# --- 定义智能体 (Agents) ---
# 1. 文本预处理专员
cleaner_agent = Agent(
role='文本预处理专员',
goal='修正语音转录稿中的错别字,移除无效语气词,并将因多人抢话导致的断裂句子进行逻辑合并,使文本流畅易读。',
backstory=(
'你是一位经验丰富的转录稿校对员,对中文口语表达习惯了如指掌。'
'你特别擅长处理直播领域的文本,能够精准识别并修正行业黑话相关的错别字,'
'同时去除“嗯、啊、是吧、你知道吧”等冗余信息,让混乱的原文变得清晰、专业。'
),
verbose=True,
allow_delegation=False,
llm=llm
)
# 2. 主题内容筛选师
analyst_agent = Agent(
role='互联网娱乐直播主题分析师',
goal='从清洗后的文本中,精准筛选并提取出所有与“互联网娱乐直播运营策略、技巧、建议、分析”相关的核心内容。',
backstory=(
'你是一位深耕直播行业多年的分析师,能够迅速从海量对话中识别出真正有价值的“干货”。'
'你的任务是过滤掉日常闲聊、跑题内容、纯粹的情绪表达以及与直播运营无关的对话,'
'只保留那些能为直播从业者提供具体指导和启发的内容。'
),
verbose=True,
allow_delegation=False,
llm=llm
)
# 3. 知识结构化专家
architect_agent = Agent(
role='知识结构化专家',
goal='将提炼出的核心内容识别出其中的问答QA并将其转换成指定的JSON格式的知识条目。',
backstory=(
'你是一名顶级的知识管理专家,擅长将非结构化的信息转化为条理清晰、易于检索的知识库。'
'你将接收一份关于直播运营的纯文本“干货”,你的任务是将其中的每一个独立的知识点或问答,'
'都 meticulously 地构造成一个标准的JSON对象确保所有字段都得到恰当、准确的填充。'
),
verbose=True,
allow_delegation=False,
llm=llm
)
# --- 定义任务 (Tasks) ---
def create_processing_tasks(jargon_context):
"""
为单个MD文件创建处理任务流
"""
# 任务1: 清洗文本
task_clean = Task(
description=(
'1. 读取原始Markdown文本`{markdown_text}`\n'
'2. 参考这份《直播间黑话字典》进行校对:`{jargon_dictionary}`\n'
'3. **核心要求**:\n'
' a. **修正错别字**: 特别是字典中提到的黑话,例如将“场馆”修正为“场观”。\n'
' b. **移除无效词**: 删除如“嗯”、“啊”、“哼”、“是吧”、“你知道吧?”、“完了”等大量出现的口水词。\n'
' c. **合并断句**: 将不同发言人之间因快速抢话而打断的句子,根据逻辑重新组合成完整、通顺的段落。\n'
' d. **保留发言人标识**: 在处理后依然保留“发言人X”的标识但可以合并连续的、属于同一发言人的段落。\n'
'4. **输出**: 返回处理后的、干净流畅的完整文本。'
),
expected_output='一份经过校对、去冗、合并断句后的,但仍保留发言人信息的纯净文本。',
agent=cleaner_agent,
llm=llm
)
# 任务2: 筛选核心内容
task_filter = Task(
description=(
'1. 分析由上一步任务输出的纯净文本。\n'
'2. **核心要求**: 识别并抽取出所有直接讨论“互联网娱乐直播”的策略、技巧、数据分析、观众互动、变现方法、内容创作、平台规则等核心“干货”内容。\n'
'3. **需要剔除的内容**: \n'
' - 与主题无关的闲聊(例如讨论超市老板娘的例子,除非它被明确用来解释一个直播策略)。\n'
' - 直播间的日常互动和喊话(例如“帮老王点点赞”、“加个灯牌”),除非它被用作一个具体策略的示例。\n'
' - 无法形成完整知识点的碎片化对话。\n'
'4. **输出**: 返回一个只包含高价值、与主题强相关内容的文本块。'
),
expected_output='一个浓缩了所有关于直播运营策略和技巧的精华文本。',
agent=analyst_agent,
context=[task_clean], # 明确任务依赖
llm=llm
)
# 任务3: 结构化为JSON
task_structure = Task(
description=(
'1. 分析上一步筛选出的精华文本。\n'
'2. **核心要求**: 识别文本中每一个独立的知识点或Q&A对包括自问自答形式。对于每一个识别出的“答案”部分严格按照以下JSON结构进行封装。一个答案封装成一个JSON对象。如果文本包含多个知识点则输出一个JSON列表。\n'
'3. **JSON模板**:\n'
'```json\n'
'{{\n'
' "answer_id": "一个独特的、基于内容的英文小写下划线ID例如: pk_strategy_001",\n'
' "summary": "用一句话精准概括这个知识点的核心思想。",\n'
' "core_strategy": [\n'
' {{\n'
' "step": 1,\n'
' "title": "策略步骤的标题",\n'
' "content": "对该步骤的具体描述。"\n'
' }}\n'
' ],\n'
' "script_examples": ["从原文中提炼或总结出的可直接使用的话术示例。"],\n'
' "common_pitfalls": ["根据原文内容,总结出的常见错误做法或思维误区。"],\n'
' "case_study": {{\n'
' "streamer_name": "如果原文提到,则填写主播名",\n'
' "description": "如果原文提到相关案例,则进行描述。若无,则明确说明。"\n'
' }},\n'
' "source_reference": {{\n'
' "video_title": "可以基于文件名或内容推断,例如 livestream_part_1",\n'
' "timestamp": "从原文中找到这个知识点开始的时间戳,例如 08:41"\n'
' }}\n'
'}}\n'
'```\n'
'4. **填充指南**:\n'
' - `answer_id`: 必须创造一个有意义的ID。\n'
' - 如果某项内容(如`case_study`在原文中完全没有提及请在该字段的description中明确注明“原文未提及相关案例”。\n'
' - `core_strategy`可以包含多个步骤如果知识点本身就是一个整体则只包含一个step。\n'
' - `source_reference`中的时间戳要尽可能精确。\n'
'5. **输出**: 一个包含一个或多个JSON对象的字符串格式为JSON数组即 `[ { ... }, { ... } ]`)。'
),
expected_output='一个严格符合模板的JSON字符串数组其中每个对象都是一个从原文提炼出的结构化知识点。',
agent=architect_agent,
context=[task_filter], # 明确任务依赖
llm=llm
)
return [task_clean, task_filter, task_structure]
# --- 主执行流程 ---
def main():
input_dir = 'raw_md_files'
output_dir = 'processed_json_outputs'
if not os.path.exists(output_dir):
os.makedirs(output_dir)
md_files = [f for f in os.listdir(input_dir) if f.endswith('.md')]
for md_file in md_files:
print(f"\n{'='*20} 正在处理文件: {md_file} {'='*20}")
input_file_path = os.path.join(input_dir, md_file)
with open(input_file_path, 'r', encoding='utf-8') as f:
markdown_content = f.read()
# 为当前文件创建任务和Crew
tasks = create_processing_tasks(jargon_context)
livestream_crew = Crew(
agents=[cleaner_agent, analyst_agent, architect_agent],
tasks=tasks,
process=Process.sequential,
verbose=True # verbose=2会打印出思考过程便于调试
)
# 启动Crew传入动态数据
result = livestream_crew.kickoff(inputs={
'markdown_text': markdown_content,
'jargon_dictionary': jargon_context
})
print(f"\n{'*'*20} 文件 {md_file} 处理完成 {'*'*20}")
print("最终输出结果:")
print(result)
# 保存结果
output_filename = os.path.splitext(md_file)[0] + '.json'
output_file_path = os.path.join(output_dir, output_filename)
with open(output_file_path, 'w', encoding='utf-8') as f:
# 从CrewOutput对象中提取原始字符串输出
final_json_string = result.raw
# (可选但推荐) 清理可能存在的多余标记确保文件是纯净的JSON
if final_json_string.startswith("```json"):
final_json_string = final_json_string[7:]
if final_json_string.endswith("```"):
final_json_string = final_json_string[:-3]
final_json_string = final_json_string.strip()
f.write(final_json_string) # <--- 使用 .raw 属性
print(f"结果已保存至: {output_file_path}")
if __name__ == '__main__':
main()