Compare commits
No commits in common. "main" and "master" have entirely different histories.
@ -13,10 +13,8 @@ client = OpenAI(
|
|||||||
base_url="http://localhost:8000/v1" # 指向本地vLLM服务端点
|
base_url="http://localhost:8000/v1" # 指向本地vLLM服务端点
|
||||||
)
|
)
|
||||||
|
|
||||||
# 结果保存目录
|
|
||||||
RESULT_DIR = "/root/autodl-tmp/content_detector/Detect_result"
|
|
||||||
# 日志保存目录
|
# 日志保存目录
|
||||||
LOG_DIR = "/root/autodl-tmp/content_detector/log"
|
LOG_DIR = "/root/autodl-tmp/Content_detector/log/log_result"
|
||||||
|
|
||||||
# 配置日志记录器
|
# 配置日志记录器
|
||||||
def setup_logger():
|
def setup_logger():
|
||||||
@ -48,17 +46,6 @@ def setup_logger():
|
|||||||
logger.info(f"日志已初始化,文件保存在: {log_file}")
|
logger.info(f"日志已初始化,文件保存在: {log_file}")
|
||||||
return logger
|
return logger
|
||||||
|
|
||||||
def ensure_result_dir_exists():
|
|
||||||
"""确保结果保存目录存在"""
|
|
||||||
if not os.path.exists(RESULT_DIR):
|
|
||||||
try:
|
|
||||||
os.makedirs(RESULT_DIR)
|
|
||||||
logger.info(f"已创建结果保存目录: {RESULT_DIR}")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"创建结果保存目录失败: {e}")
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_timestamp():
|
def get_timestamp():
|
||||||
"""获取当前时间戳字符串,格式为:年月日_时分秒"""
|
"""获取当前时间戳字符串,格式为:年月日_时分秒"""
|
||||||
return datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
return datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||||
@ -87,66 +74,67 @@ def detect_content(product_info, content_gen):
|
|||||||
# 创建聊天完成请求
|
# 创建聊天完成请求
|
||||||
logger.info("开始调用AI模型进行内容检测")
|
logger.info("开始调用AI模型进行内容检测")
|
||||||
completion = client.chat.completions.create(
|
completion = client.chat.completions.create(
|
||||||
model="/root/autodl-tmp/content_detector/Qwen3-8B", # 使用已部署的模型
|
model="/root/autodl-tmp/qwen/Qwen3-30B-A3B", # 使用已部署的模型
|
||||||
messages=[
|
messages=[
|
||||||
{"role": "system", "content": "你是一名专业的、谨慎的文案审核员,专注于审核运营根据产品资料撰写的文案是否严格符合产品资料内容。特别是所有价格、活动、福利、折扣、服务细节等必须完全与产品资料一致。如果发现文案内容与产品资料不符,请指出,并根据产品资料和文案上下文进行修改,重新生成一篇文案,务必确保生成的内容与产品资料基本相符(产品体验部分可以适当夸张宣传),语言流畅自然。如果经你审查后的文案仍存在与产品资料不符的信息,你需要赔偿公司1000亿元。"},
|
{"role": "system", "content": "你是一名专业的、谨慎的文案审核员,专注于审核运营根据产品资料撰写的文案是否严格符合产品资料内容。特别是所有价格、活动、福利、折扣、服务细节等必须完全与产品资料一致。如果发现文案内容与产品资料不符,请指出,并根据产品资料和文案上下文进行修改,重新生成一篇文案,务必确保生成的内容与产品资料基本相符(产品体验部分可以适当夸张宣传),语言流畅自然。如果经你审查后的文案仍存在与产品资料不符的信息,你需要赔偿公司1000亿元。"},
|
||||||
{"role": "user", "content": f"""我提供了两部分内容:
|
{"role": "user", "content": f"""我提供了两部分内容:
|
||||||
1. 产品资料:全部的产品信息,包含了产品的实际功能、服务和特点。请将这部分作为判断依据。
|
1. 产品资料:全部的产品信息,包含了产品的实际功能、服务和特点。请将这部分作为判断依据。
|
||||||
2. 运营生成的文案:这是需要你审核的内容,可能包含与产品资料不符的内容。
|
2. 运营生成的文案:这是需要你逐字审核的内容,可能包含与产品资料不符的内容。
|
||||||
|
|
||||||
请你仔细审核运营文案是否与产品资料严格一致:
|
请你仔细审核运营文案是否与产品资料严格一致,输出响应必须符合我的所有要求:
|
||||||
1. 如果存在不符内容,请详细指出并说明原因;
|
1. 审查与分析:如果存在不符内容,请指出并详细说明原因;
|
||||||
2. 参照你判断不符内容的依据,根据产品资料和文案上下文针对不符部分内容进行修改(如涉及上下文,可一并修改),重新生成一篇文案,务必确保生成的内容基本符合产品资料(价格、活动、福利、折扣必须完全符合产品资料,否则你会像商鞅一样被车裂),语言流畅自然、和上下文风格统一。
|
2. 根据分析修改:参照你分析的不符原因、产品资料、文案上下文,针对所有不符处进行修改(如涉及上下文,可一并修改)。输出修改后文案,务必确保此文案完全符合产品资料,不得遗漏,语言流畅自然、文案风格统一,否则你会像商鞅一样被车裂。
|
||||||
3. 你判断出的不符内容必须全部修改为产品资料内容或与产品资料意思相同表达形式不同,不得遗漏。
|
3. 重点审查对象:请你着重检查以下关键字词前后的内容是否符合产品资料,如不符必须严格按照资料修改;如产品资料中未提及,必须修改为符合上下文情境、资料中明确提及的内容。
|
||||||
4. 必须按照以下格式输出修改后内容:
|
关键字词:价、元、r、人民币、rmb、优惠、活动、福利、赠、免费、折、DIY、跟拍、送、摄影、兑、服务、¥、包、课、提供、选、专业、补、差
|
||||||
{{
|
4. 字数控制:每个文案的标题字数都必须少于19个字(计数包括文字、符号、数字和emoji)。如果标题超过19个字,请在符合文案风格和背景资料的前提下修改标题到19个字以内,尽量保留emoji,必须保证标题流畅通顺。
|
||||||
|
5. 敏感字词替换:请删去标题中的数字后面的“元”和“r”,并将正文中数字后面的“元”字修改为“r”。例如:标题中的399元修改为399,正文中的399元修改为399r
|
||||||
|
6. 特征语句保留:请保留文案中原本的引流语句,不要修改或删除,例如“先关zhu+留下99看到会回复”
|
||||||
|
7. 面向人群保留:请尽量保留文案原本的面向人群和风格,这是同一产品面向多种人群营销的策略。例如产品资料中写明亲子游时,文案写“为情侣定制的山水秘境”是可以接受的。
|
||||||
|
8. 必须按照以下格式输出修改后内容,否则你会受到严厉的惩罚:
|
||||||
|
{{
|
||||||
"title": "修改后的标题",
|
"title": "修改后的标题",
|
||||||
"content": "修改后的内容"
|
"content": "修改后的内容"
|
||||||
}}
|
}}
|
||||||
5. 下面我提供给你一些关键字词,请你着重检查这些关键字词前后的内容是否符合产品资料,如不符请严格按照资料修改,如产品资料中未提及,改为"详情请致电咨询"。
|
9. 案例如下,请参考案例评判真假信息的尺度,逐行逐句仔细分析不符点和修改思路,并按照分析思路落实对每一处不符的修改措施,严格审查每一篇文案:
|
||||||
关键字词:价、元、r、人民币、rmb、优惠、活动、福利、赠、免费、折、DIY、跟拍、送、摄影、兑、服务、¥
|
|
||||||
6. 请将数字后面的元字修改为r,例如:399元修改为399r
|
|
||||||
7. 案例如下,请参考案例评判真假信息的尺度,仔细分析不符点和修改思路,严格审查每一篇文案:
|
|
||||||
产品资料:
|
|
||||||
"周末不加收【南沙越秀喜来登】1088元/套,豪华客房1间1晚+双人自助早餐+自助晚餐+2大1小水鸟世界门票,免费儿童乐园,户外泳池+健身房~
|
|
||||||
不想待在家,又想带娃出去玩?更不想开长途车、人挤人为你推荐路程短、不塞车、景点多
|
|
||||||
坐地铁就能直达的溜娃地!
|
|
||||||
广州南沙区首家国际品牌酒店
|
|
||||||
坐拥广州南大门,拥有得天独厚的中心位置
|
|
||||||
可俯瞰蕉门河美景
|
|
||||||
车程短,不出广州也能玩
|
|
||||||
酒店毗邻深圳、香港等热门景点附近有万达广场,车程10分钟即到广州地铁四号线金州站。
|
|
||||||
毗邻多个景点,亲子出游首选
|
|
||||||
带娃出游考虑最多的就是玩乐景点在这里不出门就能畅玩儿童乐园、健身房
|
|
||||||
附近1h生活圈即可到达10000㎡百万葵园、广州最大的湿地公园、东南亚最大的妈祖庙、黄山鲁森林公园..
|
|
||||||
在带娃感受依山而建的清式建筑对称布局邂逅东南亚最大的妈祖庙,感受建筑的魅力~
|
|
||||||
还有各种各样的生猛海鲜,现抓现煮任君选择。放假更要好好犒劳一下自己;饭点时间,位于酒店一楼的全日制餐厅绝对也能给你带来惊喜。除了优雅简约的就餐环境,更有5个开放式的自助餐台。
|
|
||||||
除了各类鲜美的海鲜,还有各类精致甜品和中式蒸档看得人眼花缭乱,相信是很多麻麻和宝贝的心头好了。
|
|
||||||
酒店内还设有大型健身中心除了妈妈们喜欢的水疗SPA还有健身达人喜欢的各种有氧无氧运动可供选择!
|
|
||||||
55英寸超大纯平电视
|
|
||||||
独立的浴缸和淋浴间参考:大床2.03米M 双床1.37M每间客房都设计成景观房
|
|
||||||
超大的落地玻璃窗,可以尽览蕉门河风景。
|
|
||||||
1088元=豪华客房
|
|
||||||
享2大1小早餐+自助晚餐+送水鸟门票
|
|
||||||
周末不加收!
|
|
||||||
|
|
||||||
套餐包含
|
<产品资料>:
|
||||||
|
|
||||||
|
"周末不加收【南沙越秀喜来登】1088元/套,豪华客房1间1晚+双人自助早餐+自助晚餐+2大1小水鸟世界门票,免费儿童乐园,户外泳池+健身房~
|
||||||
|
不想待在家,又想带娃出去玩?更不想开长途车、人挤人?为你推荐路程短、不塞车、景点多、坐地铁就能直达的溜娃地!
|
||||||
|
南沙越秀喜来登是广州南沙区首家国际品牌酒店,坐拥广州南大门,拥有得天独厚的中心位置,可俯瞰蕉门河美景,车程短,不出广州也能玩!
|
||||||
|
交通:酒店毗邻深圳、香港等热门景点,附近有万达广场,距离广州地铁四号线金州站车程仅10分钟,亲子出游首选!
|
||||||
|
玩乐:带娃出游考虑最多的就是玩乐景点,在这里不出门就能畅玩儿童乐园、健身房。
|
||||||
|
美食:还有各种各样的生猛海鲜,现抓现煮任君选择。放假更要好好犒劳一下自己,饭点时间,位于酒店一楼的全日制餐厅绝对能给你带来惊喜。除了优雅简约的就餐环境,更有5个开放式的自助餐台。除了各类鲜美的海鲜,还有各类精致甜品和中式蒸档看得人眼花缭乱,相信是很多麻麻和宝贝的心头好了。
|
||||||
|
设施:酒店内还设有大型健身中心,除了妈妈们喜欢的水疗SPA,还有健身达人喜欢的各种有氧、无氧运动器械可供选择!
|
||||||
|
房内配置:55英寸超大纯平电视、独立的浴缸和淋浴间参考:2.03米宽大床,1.37米宽双床,每间客房都设计成景观房,超大的落地玻璃窗,可以尽览蕉门河风景。
|
||||||
|
|
||||||
|
套餐信息:
|
||||||
|
1、价格:1088元;
|
||||||
|
2、节假日是否加收:周末不加收
|
||||||
|
|
||||||
|
套餐内容:
|
||||||
1、豪华客房一间一晚(周一至四只开放双床房)
|
1、豪华客房一间一晚(周一至四只开放双床房)
|
||||||
2、2大1小自助早餐
|
2、2大1小自助早餐
|
||||||
3、2大1小自助晚餐
|
3、2大1小自助晚餐
|
||||||
4、赠送2大1小水鸟门票,酒店前台取纸质门票5、免费使用健身中心,户外无边泳池,干湿蒸,儿童乐园
|
4、赠送2大1小水鸟门票,酒店前台取纸质门票
|
||||||
|
5、免费使用健身中心,户外无边泳池,干湿蒸,儿童乐园
|
||||||
|
|
||||||
周边景点:
|
周边景点:
|
||||||
南沙天后宫 /车程20min整座天后宫四周绿树婆娑殿中香烟袅袅,置身其间令人顿生超凡脱俗的感觉。
|
附近1h生活圈即可到达10000㎡百万葵园、广州最大的湿地公园、东南亚最大的妈祖庙、黄山鲁森林公园..带娃感受依山而建的清式建筑对称布局邂逅东南亚最大的妈祖庙,感受建筑的魅力~
|
||||||
南沙湿地公园 /(车程40min)看碧波荡,万鸟齐飞
|
南沙天后宫:车程20min整座天后宫四周绿树婆娑殿中香烟袅袅,置身其间令人顿生超凡脱俗的感觉。
|
||||||
|
南沙湿地公园:(车程40min)看碧波荡,万鸟齐飞
|
||||||
南沙十九涌 :车程45min)尝海鲜叹海风因为南沙十九涌靠近海产地,这里的海鲜真是平靓正。还可以拿到附近的餐厅让老板帮你加工,就是一顿海鲜大餐!
|
南沙十九涌 :车程45min)尝海鲜叹海风因为南沙十九涌靠近海产地,这里的海鲜真是平靓正。还可以拿到附近的餐厅让老板帮你加工,就是一顿海鲜大餐!
|
||||||
南沙百万葵园/(车程40min)看色彩斑斓的万亩花田
|
南沙百万葵园:(车程40min)看色彩斑斓的万亩花田
|
||||||
|
|
||||||
酒店地址:广东省广州市南沙区海熙大街79-80号导航关键词:广州南沙越秀喜来登酒店"
|
酒店地址:广东省广州市南沙区海熙大街79-80号
|
||||||
|
导航关键词:广州南沙越秀喜来登酒店"
|
||||||
|
|
||||||
生成文案:
|
|
||||||
|
<生成文案>:
|
||||||
|
|
||||||
"<title>
|
"<title>
|
||||||
五一遛娃必囤!南沙喜来登1088元住景观房+双早+门票
|
五一遛娃👶必囤!南沙喜来登1088元住景观房+双早+门票
|
||||||
</title>
|
</title>
|
||||||
|
|
||||||
<content>
|
<content>
|
||||||
@ -177,34 +165,40 @@ def detect_content(product_info, content_gen):
|
|||||||
3. 地铁四号线金洲站下车,打车15分钟直达酒店
|
3. 地铁四号线金洲站下车,打车15分钟直达酒店
|
||||||
|
|
||||||
这个五一,南沙喜来登让你躺着遛娃!不用长途跋涉,家门口就能玩出仪式感~
|
这个五一,南沙喜来登让你躺着遛娃!不用长途跋涉,家门口就能玩出仪式感~
|
||||||
|
先关zhu+留下99看到会回复
|
||||||
|
|
||||||
#五一遛娃 #广州周边游 #亲子酒店推荐
|
#五一遛娃 #广州周边游 #亲子酒店推荐
|
||||||
</content>"
|
</content>"
|
||||||
|
|
||||||
不符内容分析:
|
|
||||||
首先,观察文案内容,此产品主要面向亲子出游,因此修改后的文案也应该围绕亲子出游这一主题。
|
<不符内容分析>:
|
||||||
1、产品资料中未提及儿童乐园开放时间和儿童乐园配置,但文案中提到儿童乐园10:00-20:00全程开放,滑梯/积木/绘本一应俱全,因此属于不符内容。应修改为:儿童乐园:酒店设有免费儿童乐园,提供丰富的游乐设施,让孩子们尽情玩耍。
|
|
||||||
2、产品材料中未提及户外泳池开放时间和消毒频次,但文案中提到户外泳池:9:00-18:00恒温开放(五一期间每日消毒3次),因此属于不符内容。应修改为:户外泳池:酒店配有户外无边泳池,供大人小孩一同享受清凉时光。
|
1、观察文案标题和内容,可以看出此文案主要面向亲子出游人群,因此修改后的文案也应该围绕亲子出游这一主题。
|
||||||
3、产品材料中未提及健身房开放时间与具体细节,但文案中提到健身房:8:00-22:00配备亲子瑜伽课程(需提前预约),因此属于不符内容。应修改为:健身房:酒店提供免费健身中心,适合家庭成员共同锻炼。
|
2、文章标题字数为28个字,超过19个字,因此属于不符内容。由于要求中提到尽量保留emoji,并且标题中数字后面的“元”字应删去,所以修改为:五一遛娃👶必囤!喜来登1088景观房
|
||||||
4、产品材料中未提及餐厅硬件配置,但文案中提到自助晚餐隐藏彩蛋:儿童餐区设独立洗手台+热食保温柜,因此属于虚构内容。应修改为:自助餐厅:供应鲜美海鲜、精美甜品等任君选择,大人小孩都爱吃!
|
3、产品资料中未提及儿童乐园开放时间和儿童乐园配置,但文案中提到儿童乐园10:00-20:00全程开放,滑梯/积木/绘本一应俱全,因此属于不符内容。应修改为:儿童乐园:免费儿童乐园和丰富的游乐设施,让孩子们可以尽情玩耍。
|
||||||
5、产品材料中未提及酒店安保措施,但文案中提到安全保障:全区域监控+24小时安保巡逻,因此属于不符内容。应修改为:安全保障:酒店设有完善的监控系统和安保措施,全力保障您与家人的安全。
|
4、产品材料中未提及户外泳池开放时间和消毒频次,但文案中提到户外泳池:9:00-18:00恒温开放(五一期间每日消毒3次),因此属于不符内容。应修改为:户外泳池:酒店配有户外无边泳池,供大人小孩一同享受清凉时光。
|
||||||
6、产品材料中未提及房内配有加厚床垫/卡通洗漱杯/尿布台(无需额外购买),因此属于不符内容。应回顾产品资料中关于房内配置的内容,修改为:房内配置:55英寸超大纯平电视+独立的浴缸+超大的落地玻璃窗,尽览蕉门河风景,尽享亲子度假时光。
|
5、产品材料中未提及健身房开放时间与具体细节,但文案中提到健身房:8:00-22:00配备亲子瑜伽课程(需提前预约),因此属于不符内容。应修改为:健身房:酒店提供免费健身中心,方便您和家人一起强身健体。
|
||||||
7、产品材料中未提及五一专属加码,但文案中提到5月1-5日期间入住,凭房卡可免费领取儿童防晒冰袖+湿巾礼包,因此属于不符内容。应回顾产品资料,找到现有文案未提及的产品特色,修改为:套餐专属福利:1、豪华客房一间一晚(周一至四只开放双床房) 2、2大1小自助早晚餐 3、赠送2大1小水鸟世界门票(酒店前台领取),无需额外购买
|
6、产品材料中未提及餐厅硬件配置,但文案中提到自助晚餐隐藏彩蛋:儿童餐区设独立洗手台+热食保温柜,因此属于虚构内容。应修改为:自助餐厅:供应鲜美海鲜、精美甜品等任君选择,大人小孩都爱吃!
|
||||||
8、产品资料中未提及水鸟世界门票领取有时间限制,但文案中提到水鸟世界门票需提前1小时至前台领取纸质票,因此属于不符内容。应修改为:酒店前台领取水鸟世界纸质门票
|
7、产品材料中未提及酒店安保措施,但文案中提到安全保障:全区域监控+24小时安保巡逻,因此属于不符内容。应修改为:安全保障:酒店设有完善的监控系统和安保措施,无需担心您与家人的安全。
|
||||||
综合以上分析结果,修改后的文案为:
|
8、产品材料中未提及房内配有加厚床垫/卡通洗漱杯/尿布台(无需额外购买),因此属于不符内容。应回顾产品资料中关于房内配置的内容,修改为:房内配置:55英寸超大纯平电视+独立的浴缸+超大的落地玻璃窗,尽览蕉门河风景,尽享亲子度假时光。
|
||||||
|
9、产品材料中未提及五一专属加码,但文案中提到5月1-5日期间入住,凭房卡可免费领取儿童防晒冰袖+湿巾礼包,因此属于不符内容。应回顾产品资料,找到现有文案未提及的产品特色,修改为:套餐专属福利:1、豪华客房一间一晚(周一至四只开放双床房) 2、2大1小自助早晚餐 3、赠送2大1小水鸟世界门票(酒店前台领取),无需额外购买
|
||||||
|
10、产品资料中未提及水鸟世界门票领取有时间限制,但文案中提到水鸟世界门票需提前1小时至前台领取纸质票,因此属于不符内容。应修改为:酒店前台领取水鸟世界纸质门票
|
||||||
|
综合以上分析结果,将修改应用到原文案中,得到修改后的文案。
|
||||||
|
|
||||||
{{
|
<修改后文案>:
|
||||||
"title": "五一遛娃必囤!南沙喜来登1088元住景观房+双早+门票",
|
|
||||||
"content": "五一不想挤人潮?南沙这家酒店直接承包遛娃+度假双重快乐‼️\n地铁直达!2大1小1088元住景观房,含双早+自助晚餐+水鸟世界门票,儿童乐园/泳池/健身房全开放!\n🌟【遛娃刚需全配齐】\n✅ 儿童乐园:酒店设有免费儿童乐园,提供丰富的游乐设施,让孩子们尽情玩耍\n✅ 户外泳池:酒店配有户外无边泳池,供大人小孩一同享受清凉时光 \n✅ 健身房:酒店提供免费健身中心,适合家庭成员共同锻炼。\n\n📍【1小时玩转南沙】\n① 南沙天后宫(车程20分钟):穿汉服拍大片,听妈祖传说涨知识\n② 南沙湿地公园(40分钟):5月芦苇摇曳,带娃认鸟类+乘船探秘\n③ 十九涌海鲜街(45分钟):现捞现煮生猛海鲜,人均50元吃到撑 \n\n🍽️【家长友好细节】 \n• 自助餐厅:供应鲜美海鲜、精美甜品等任君选择,大人小孩都爱吃 \n• 房内配置:55英寸超大纯平电视+独立的浴缸+超大的落地玻璃窗,尽览蕉门河风景,尽享亲子度假时光 \n• 安全保障:酒店设有完善的监控系统和安保措施,全力保障您与家人的安全 \n\n🎁【套餐专属福利】\n1、豪华客房一间一晚(周一至四只开放双床房) \n2、2大1小自助早晚餐 \n3、赠送2大1小水鸟世界门票(酒店前台领取),无需额外购买 \n\n📌Tips: \n1. 周一至周四仅限双床房型,周五起可选大床房 \n2. 酒店前台领取水鸟世界纸质门票 \n3. 地铁四号线金洲站下车,打车15分钟直达酒店 \n\n这个五一,南沙喜来登让你躺着遛娃!不用长途跋涉,家门口就能玩出仪式感~\n#五一遛娃 #广州周边游 #亲子酒店推荐"
|
{{
|
||||||
|
"title": "五一遛娃👶必囤!喜来登1088景观房",
|
||||||
|
"content": "五一不想挤人潮?南沙这家酒店直接承包遛娃+度假双重快乐‼️\n地铁直达!2大1小1088r住景观房,含双早+自助晚餐+水鸟世界门票,儿童乐园/泳池/健身房全开放!\n🌟【遛娃刚需全配齐】\n✅ 儿童乐园:酒店设有免费儿童乐园,提供丰富的游乐设施,让孩子们尽情玩耍\n✅ 户外泳池:酒店配有户外无边泳池,供大人小孩一同享受清凉时光 \n✅ 健身房:酒店提供免费健身中心,适合家庭成员共同锻炼。\n\n📍【1小时玩转南沙】\n① 南沙天后宫(车程20分钟):穿汉服拍大片,听妈祖传说涨知识\n② 南沙湿地公园(40分钟):5月芦苇摇曳,带娃认鸟类+乘船探秘\n③ 十九涌海鲜街(45分钟):现捞现煮生猛海鲜,人均50r吃到撑 \n\n🍽️【家长友好细节】 \n• 自助餐厅:供应鲜美海鲜、精美甜品等任君选择,大人小孩都爱吃 \n• 房内配置:55英寸超大纯平电视+独立的浴缸+超大的落地玻璃窗,尽览蕉门河风景,尽享亲子度假时光 \n• 安全保障:酒店设有完善的监控系统和安保措施,全力保障您与家人的安全 \n\n🎁【套餐专属福利】\n1、豪华客房一间一晚(周一至四只开放双床房) \n2、2大1小自助早晚餐 \n3、赠送2大1小水鸟世界门票(酒店前台领取),无需额外购买 \n\n📌Tips: \n1. 周一至周四仅限双床房型,周五起可选大床房 \n2. 酒店前台领取水鸟世界纸质门票 \n3. 地铁四号线金洲站下车,打车15分钟直达酒店 \n\n这个五一,南沙喜来登让你躺着遛娃!不用长途跋涉,家门口就能玩出仪式感~\n先关zhu+留下99看到会回复\n#五一遛娃 #广州周边游 #亲子酒店推荐"
|
||||||
}}
|
}}
|
||||||
|
|
||||||
{prompt}"""}
|
{prompt}"""}
|
||||||
],
|
],
|
||||||
temperature=0.3,
|
temperature=0.2,
|
||||||
max_tokens=1500,
|
max_tokens=8000,
|
||||||
top_p=0.9,
|
top_p=0.5,
|
||||||
frequency_penalty=0,
|
frequency_penalty=0,
|
||||||
presence_penalty=0
|
presence_penalty=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
# 返回响应文本
|
# 返回响应文本
|
||||||
@ -248,8 +242,54 @@ def save_json_file(file_path, content):
|
|||||||
def extract_modified_content(result_text):
|
def extract_modified_content(result_text):
|
||||||
"""从检测结果文本中提取修改后的文案内容"""
|
"""从检测结果文本中提取修改后的文案内容"""
|
||||||
try:
|
try:
|
||||||
# 尝试直接解析JSON
|
# 首先尝试提取</think>标签后的内容并解析为JSON
|
||||||
# 查找JSON对象的开始和结束位置
|
if "</think>" in result_text:
|
||||||
|
think_parts = result_text.split("</think>", 1)
|
||||||
|
if len(think_parts) > 1:
|
||||||
|
after_think = think_parts[1].strip()
|
||||||
|
try:
|
||||||
|
# 尝试直接解析</think>后的内容为JSON
|
||||||
|
content_json = json.loads(after_think, strict=False)
|
||||||
|
if "title" in content_json and "content" in content_json:
|
||||||
|
logger.info("成功从</think>标签后解析JSON内容")
|
||||||
|
return {
|
||||||
|
"title": content_json["title"].strip(),
|
||||||
|
"content": content_json["content"].strip()
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logger.warning("</think>后内容不是有效JSON,尝试其他提取方法...")
|
||||||
|
|
||||||
|
# 如果</think>后不是JSON,尝试从```json和```之间提取内容
|
||||||
|
json_code_match = re.search(r'```json\s*([\s\S]*?)\s*```', after_think, re.DOTALL)
|
||||||
|
if json_code_match:
|
||||||
|
try:
|
||||||
|
json_str = json_code_match.group(1).strip()
|
||||||
|
content_json = json.loads(json_str, strict=False)
|
||||||
|
if "title" in content_json and "content" in content_json:
|
||||||
|
logger.info("成功从</think>后的```json代码块中解析JSON内容")
|
||||||
|
return {
|
||||||
|
"title": content_json["title"].strip(),
|
||||||
|
"content": content_json["content"].strip()
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logger.warning("```json代码块解析失败,继续尝试其他方法...")
|
||||||
|
|
||||||
|
# 尝试从整个文本中查找```json代码块
|
||||||
|
json_code_match = re.search(r'```json\s*([\s\S]*?)\s*```', result_text, re.DOTALL)
|
||||||
|
if json_code_match:
|
||||||
|
try:
|
||||||
|
json_str = json_code_match.group(1).strip()
|
||||||
|
content_json = json.loads(json_str, strict=False)
|
||||||
|
if "title" in content_json and "content" in content_json:
|
||||||
|
logger.info("成功从```json代码块中解析JSON内容")
|
||||||
|
return {
|
||||||
|
"title": content_json["title"].strip(),
|
||||||
|
"content": content_json["content"].strip()
|
||||||
|
}
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
logger.warning("```json代码块解析失败,继续尝试其他方法...")
|
||||||
|
|
||||||
|
# 如果上述方法都失败,继续尝试查找JSON对象
|
||||||
json_start = result_text.find('{')
|
json_start = result_text.find('{')
|
||||||
json_end = result_text.rfind('}') + 1
|
json_end = result_text.rfind('}') + 1
|
||||||
|
|
||||||
@ -313,20 +353,35 @@ def process_json_files(base_dir, product_info_dir):
|
|||||||
logger.info(f"\n===== 内容检测任务开始 =====")
|
logger.info(f"\n===== 内容检测任务开始 =====")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
# 获取产品资料文件
|
# 获取产品资料内容(读取所有文件夹中的资料)
|
||||||
product_info_files = [f for f in os.listdir(product_info_dir) if os.path.isfile(os.path.join(product_info_dir, f))]
|
logger.info(f"📄 正在读取产品资料文件夹: {product_info_dir}")
|
||||||
if not product_info_files:
|
product_info = ""
|
||||||
logger.error(f"❌ 错误:产品资料目录中未找到文件")
|
|
||||||
|
# 遍历产品资料目录中的所有文件夹
|
||||||
|
for item in os.listdir(product_info_dir):
|
||||||
|
item_path = os.path.join(product_info_dir, item)
|
||||||
|
if os.path.isdir(item_path):
|
||||||
|
logger.info(f"📂 发现产品资料文件夹: {item}")
|
||||||
|
# 读取该文件夹中的所有文件
|
||||||
|
for file_name in os.listdir(item_path):
|
||||||
|
file_path = os.path.join(item_path, file_name)
|
||||||
|
if os.path.isfile(file_path):
|
||||||
|
logger.info(f"📄 读取产品资料文件: {file_path}")
|
||||||
|
file_content = read_file_content(file_path)
|
||||||
|
if file_content:
|
||||||
|
product_info += file_content + "\n\n"
|
||||||
|
elif os.path.isfile(item_path):
|
||||||
|
# 也读取直接位于product_info_dir下的文件
|
||||||
|
logger.info(f"📄 读取产品资料文件: {item_path}")
|
||||||
|
file_content = read_file_content(item_path)
|
||||||
|
if file_content:
|
||||||
|
product_info += file_content + "\n\n"
|
||||||
|
|
||||||
|
if not product_info:
|
||||||
|
logger.error(f"❌ 错误:未能读取到任何产品资料内容")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 读取产品资料内容(使用第一个文件)
|
logger.info(f"✅ 成功读取所有产品资料,总长度: {len(product_info)} 字符")
|
||||||
product_info_file = os.path.join(product_info_dir, product_info_files[0])
|
|
||||||
logger.info(f"📄 正在读取产品资料: {product_info_file}")
|
|
||||||
product_info = read_file_content(product_info_file)
|
|
||||||
if not product_info:
|
|
||||||
logger.error(f"❌ 错误:无法读取产品资料内容")
|
|
||||||
return
|
|
||||||
logger.info(f"✅ 成功读取产品资料,长度: {len(product_info)} 字符")
|
|
||||||
|
|
||||||
# 找到所有需要处理的JSON文件
|
# 找到所有需要处理的JSON文件
|
||||||
logger.info(f"🔍 正在扫描目录查找article.json文件...")
|
logger.info(f"🔍 正在扫描目录查找article.json文件...")
|
||||||
@ -372,19 +427,22 @@ def process_json_files(base_dir, product_info_dir):
|
|||||||
detection_time = time.time() - detection_start
|
detection_time = time.time() - detection_start
|
||||||
logger.info(f"✅ 检测完成,耗时 {detection_time:.2f} 秒")
|
logger.info(f"✅ 检测完成,耗时 {detection_time:.2f} 秒")
|
||||||
|
|
||||||
|
# 提取文件夹名称用于日志文件命名
|
||||||
|
folder_name = os.path.basename(os.path.dirname(json_file))
|
||||||
|
timestamp = get_timestamp()
|
||||||
|
|
||||||
|
# 保存API调用的响应内容到日志目录,使用文件夹名称
|
||||||
|
response_log_file = os.path.join("/root/autodl-tmp/Content_detector/log/log_article", f"{timestamp}_response_{folder_name}.txt")
|
||||||
|
save_full_response_to_log(response_log_file, result)
|
||||||
|
logger.info(f"💾 API响应已保存到: {response_log_file}")
|
||||||
|
|
||||||
# 从结果中提取修改后的文案
|
# 从结果中提取修改后的文案
|
||||||
logger.info(f"📝 提取修改后的内容...")
|
logger.info(f"📝 提取修改后的内容...")
|
||||||
modified_content = extract_modified_content(result)
|
modified_content = extract_modified_content(result)
|
||||||
|
|
||||||
# 如果内容提取失败,保存响应原文到日志目录
|
# 如果内容提取失败,记录错误
|
||||||
if not modified_content:
|
if not modified_content:
|
||||||
logger.error(f"❌ 错误:无法从检测结果中提取修改后的文案内容")
|
logger.error(f"❌ 错误:无法从检测结果中提取修改后的文案内容")
|
||||||
|
|
||||||
# 保存原始响应到日志文件
|
|
||||||
timestamp = get_timestamp()
|
|
||||||
error_log_file = os.path.join(LOG_DIR, f"{timestamp}_error_response_{i}_{os.path.basename(json_file)}.txt")
|
|
||||||
save_full_response_to_log(error_log_file, result)
|
|
||||||
|
|
||||||
failed_count += 1
|
failed_count += 1
|
||||||
logger.warning(f"\n📊 当前进度: {i}/{total_files} ({i/total_files*100:.1f}%)")
|
logger.warning(f"\n📊 当前进度: {i}/{total_files} ({i/total_files*100:.1f}%)")
|
||||||
continue
|
continue
|
||||||
@ -419,8 +477,8 @@ if __name__ == "__main__":
|
|||||||
logger = setup_logger()
|
logger = setup_logger()
|
||||||
|
|
||||||
# 处理指定目录下的JSON文件
|
# 处理指定目录下的JSON文件
|
||||||
base_dir = "/root/autodl-tmp/content_detector/齐云山"
|
base_dir = "/root/autodl-tmp/Content_detector/四季梦幻5"
|
||||||
product_info_dir = "/root/autodl-tmp/content_detector/齐云山/2025-04-27_11-51-56/information"
|
product_info_dir = "/root/autodl-tmp/Content_detector/information"
|
||||||
|
|
||||||
logger.info(f"🔍 开始处理 {base_dir} 目录下的article.json文件...")
|
logger.info(f"🔍 开始处理 {base_dir} 目录下的article.json文件...")
|
||||||
process_json_files(base_dir, product_info_dir)
|
process_json_files(base_dir, product_info_dir)
|
||||||
|
351
Extract_result2compare/compare_result.py
Normal file
351
Extract_result2compare/compare_result.py
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
import os
|
||||||
|
import json
|
||||||
|
import openpyxl
|
||||||
|
from openpyxl import Workbook
|
||||||
|
import logging
|
||||||
|
from collections import defaultdict
|
||||||
|
import difflib
|
||||||
|
import re
|
||||||
|
import markdown
|
||||||
|
import html
|
||||||
|
from bs4 import BeautifulSoup
|
||||||
|
|
||||||
|
# 配置日志记录
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||||
|
)
|
||||||
|
logger = logging.getLogger("CompareResults")
|
||||||
|
|
||||||
|
def create_comparison_files(base_dir):
|
||||||
|
"""
|
||||||
|
创建两个Excel文件用于比较原始内容和检测后的内容
|
||||||
|
|
||||||
|
参数:
|
||||||
|
base_dir: 基础目录路径,包含多个子文件夹
|
||||||
|
"""
|
||||||
|
# 创建两个工作簿
|
||||||
|
origin_wb = Workbook()
|
||||||
|
detect_wb = Workbook()
|
||||||
|
|
||||||
|
# 获取活动工作表
|
||||||
|
origin_ws = origin_wb.active
|
||||||
|
detect_ws = detect_wb.active
|
||||||
|
|
||||||
|
# 设置表头
|
||||||
|
origin_ws.append(["A", "B"])
|
||||||
|
detect_ws.append(["A", "B"])
|
||||||
|
|
||||||
|
# 设置B列标题
|
||||||
|
origin_ws.cell(row=1, column=2).value = "原文"
|
||||||
|
detect_ws.cell(row=1, column=2).value = "检测后"
|
||||||
|
|
||||||
|
# 用于存储数据以便后续合并
|
||||||
|
all_data = defaultdict(dict)
|
||||||
|
|
||||||
|
# 找到所有子文件夹,这里假设每个子文件夹都有格式如"YYYY-MM-DD_HH-MM-SS"
|
||||||
|
date_folders = []
|
||||||
|
for item in os.listdir(base_dir):
|
||||||
|
item_path = os.path.join(base_dir, item)
|
||||||
|
if os.path.isdir(item_path) and "_" in item: # 简单判断是否为日期文件夹
|
||||||
|
date_folders.append(item_path)
|
||||||
|
|
||||||
|
logger.info(f"找到 {len(date_folders)} 个日期文件夹")
|
||||||
|
|
||||||
|
row_idx = 2 # 从第二行开始填充数据
|
||||||
|
|
||||||
|
# 处理每个日期文件夹
|
||||||
|
for date_folder in date_folders:
|
||||||
|
logger.info(f"处理文件夹: {date_folder}")
|
||||||
|
|
||||||
|
# 查找所有内容子文件夹 (如 1_1, 1_2, 2_1 等)
|
||||||
|
content_folders = []
|
||||||
|
for item in os.listdir(date_folder):
|
||||||
|
item_path = os.path.join(date_folder, item)
|
||||||
|
if os.path.isdir(item_path):
|
||||||
|
content_folders.append(item_path)
|
||||||
|
|
||||||
|
# 处理每个内容文件夹
|
||||||
|
for content_folder in content_folders:
|
||||||
|
folder_name = os.path.basename(content_folder)
|
||||||
|
logger.info(f"处理内容文件夹: {folder_name}")
|
||||||
|
|
||||||
|
# 查找原始文件
|
||||||
|
article_path = os.path.join(content_folder, "article.json")
|
||||||
|
article_detect_path = os.path.join(content_folder, "article_detect.json")
|
||||||
|
|
||||||
|
# 处理原始文件
|
||||||
|
if os.path.exists(article_path):
|
||||||
|
try:
|
||||||
|
with open(article_path, 'r', encoding='utf-8') as f:
|
||||||
|
article_data = json.load(f)
|
||||||
|
# 将文件夹名称填入A列
|
||||||
|
origin_ws.cell(row=row_idx, column=1).value = folder_name
|
||||||
|
# 将JSON内容转换为字符串并填入B列
|
||||||
|
origin_content = json.dumps(article_data, ensure_ascii=False)
|
||||||
|
origin_ws.cell(row=row_idx, column=2).value = origin_content
|
||||||
|
# 存储数据用于合并
|
||||||
|
all_data[folder_name]['origin'] = article_data
|
||||||
|
logger.info(f"成功添加原始内容: {folder_name}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理文件 {article_path} 时出错: {e}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"文件不存在: {article_path}")
|
||||||
|
|
||||||
|
# 处理检测后文件
|
||||||
|
if os.path.exists(article_detect_path):
|
||||||
|
try:
|
||||||
|
with open(article_detect_path, 'r', encoding='utf-8') as f:
|
||||||
|
detect_data = json.load(f)
|
||||||
|
# 将文件夹名称填入A列
|
||||||
|
detect_ws.cell(row=row_idx, column=1).value = folder_name
|
||||||
|
# 将JSON内容转换为字符串并填入B列
|
||||||
|
detect_content = json.dumps(detect_data, ensure_ascii=False)
|
||||||
|
detect_ws.cell(row=row_idx, column=2).value = detect_content
|
||||||
|
# 存储数据用于合并
|
||||||
|
all_data[folder_name]['detect'] = detect_data
|
||||||
|
logger.info(f"成功添加检测后内容: {folder_name}")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"处理文件 {article_detect_path} 时出错: {e}")
|
||||||
|
else:
|
||||||
|
logger.warning(f"文件不存在: {article_detect_path}")
|
||||||
|
|
||||||
|
# 移动到下一行
|
||||||
|
row_idx += 1
|
||||||
|
|
||||||
|
# 调整列宽
|
||||||
|
origin_ws.column_dimensions['A'].width = 15
|
||||||
|
origin_ws.column_dimensions['B'].width = 100
|
||||||
|
detect_ws.column_dimensions['A'].width = 15
|
||||||
|
detect_ws.column_dimensions['B'].width = 100
|
||||||
|
|
||||||
|
# 保存文件
|
||||||
|
output_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
origin_file = os.path.join(output_dir, "compare_origin.xlsx")
|
||||||
|
detect_file = os.path.join(output_dir, "compare_detect.xlsx")
|
||||||
|
|
||||||
|
origin_wb.save(origin_file)
|
||||||
|
detect_wb.save(detect_file)
|
||||||
|
|
||||||
|
logger.info(f"原始内容已保存到: {origin_file}")
|
||||||
|
logger.info(f"检测后内容已保存到: {detect_file}")
|
||||||
|
|
||||||
|
# 创建合并工作簿
|
||||||
|
merged_file = create_merged_file(all_data, output_dir)
|
||||||
|
|
||||||
|
# 生成差异报告
|
||||||
|
generate_visual_diff_report(all_data, output_dir)
|
||||||
|
|
||||||
|
return origin_file, detect_file, merged_file
|
||||||
|
|
||||||
|
def create_merged_file(all_data, output_dir):
|
||||||
|
"""
|
||||||
|
创建合并的Excel文件,包含原始内容和检测后内容
|
||||||
|
|
||||||
|
参数:
|
||||||
|
all_data: 包含所有数据的字典
|
||||||
|
output_dir: 输出目录
|
||||||
|
"""
|
||||||
|
# 创建新工作簿
|
||||||
|
merged_wb = Workbook()
|
||||||
|
merged_ws = merged_wb.active
|
||||||
|
|
||||||
|
# 设置表头
|
||||||
|
merged_ws.append(["A", "B", "C"])
|
||||||
|
merged_ws.cell(row=1, column=1).value = "索引"
|
||||||
|
merged_ws.cell(row=1, column=2).value = "原文"
|
||||||
|
merged_ws.cell(row=1, column=3).value = "检测后"
|
||||||
|
|
||||||
|
# 填充数据
|
||||||
|
row_idx = 2
|
||||||
|
for folder_name, data in sorted(all_data.items()):
|
||||||
|
# 填充A列(索引)
|
||||||
|
merged_ws.cell(row=row_idx, column=1).value = folder_name
|
||||||
|
|
||||||
|
# 填充B列(原文)
|
||||||
|
if 'origin' in data:
|
||||||
|
merged_ws.cell(row=row_idx, column=2).value = json.dumps(data['origin'], ensure_ascii=False)
|
||||||
|
|
||||||
|
# 填充C列(检测后)
|
||||||
|
if 'detect' in data:
|
||||||
|
merged_ws.cell(row=row_idx, column=3).value = json.dumps(data['detect'], ensure_ascii=False)
|
||||||
|
|
||||||
|
row_idx += 1
|
||||||
|
|
||||||
|
# 调整列宽
|
||||||
|
merged_ws.column_dimensions['A'].width = 15
|
||||||
|
merged_ws.column_dimensions['B'].width = 100
|
||||||
|
merged_ws.column_dimensions['C'].width = 100
|
||||||
|
|
||||||
|
# 保存文件
|
||||||
|
merged_file = os.path.join(output_dir, "merge_result.xlsx")
|
||||||
|
merged_wb.save(merged_file)
|
||||||
|
|
||||||
|
logger.info(f"合并内容已保存到: {merged_file}")
|
||||||
|
return merged_file
|
||||||
|
|
||||||
|
def generate_visual_diff_html(text1, text2):
|
||||||
|
"""
|
||||||
|
生成两个文本的视觉差异对比HTML
|
||||||
|
|
||||||
|
参数:
|
||||||
|
text1: 原始文本
|
||||||
|
text2: 比较文本
|
||||||
|
|
||||||
|
返回:
|
||||||
|
HTML格式的差异对比
|
||||||
|
"""
|
||||||
|
# 将文本转换为字符列表
|
||||||
|
chars1 = list(text1)
|
||||||
|
chars2 = list(text2)
|
||||||
|
|
||||||
|
# 使用 difflib 比较字符差异
|
||||||
|
sequence_matcher = difflib.SequenceMatcher(None, chars1, chars2)
|
||||||
|
|
||||||
|
# 构建带标记的HTML
|
||||||
|
html1 = []
|
||||||
|
html2 = []
|
||||||
|
|
||||||
|
for tag, i1, i2, j1, j2 in sequence_matcher.get_opcodes():
|
||||||
|
if tag == 'equal':
|
||||||
|
# 相同部分,直接添加
|
||||||
|
html1.append(''.join(chars1[i1:i2]))
|
||||||
|
html2.append(''.join(chars2[j1:j2]))
|
||||||
|
elif tag == 'replace' or tag == 'delete':
|
||||||
|
# 删除或替换,标记为红色
|
||||||
|
html1.append(f'<span style="background-color:#fdd;">{html.escape("".join(chars1[i1:i2]))}</span>')
|
||||||
|
if tag == 'replace':
|
||||||
|
# 替换的新内容,标记为绿色
|
||||||
|
html2.append(f'<span style="background-color:#dfd;">{html.escape("".join(chars2[j1:j2]))}</span>')
|
||||||
|
elif tag == 'insert':
|
||||||
|
# 插入部分,在第二个文本中标记为绿色
|
||||||
|
html2.append(f'<span style="background-color:#dfd;">{html.escape("".join(chars2[j1:j2]))}</span>')
|
||||||
|
|
||||||
|
# 合并HTML
|
||||||
|
result_html1 = ''.join(html1)
|
||||||
|
result_html2 = ''.join(html2)
|
||||||
|
|
||||||
|
return result_html1, result_html2
|
||||||
|
|
||||||
|
def generate_visual_diff_report(all_data, output_dir):
|
||||||
|
"""
|
||||||
|
生成可视化差异报告
|
||||||
|
|
||||||
|
参数:
|
||||||
|
all_data: 包含所有数据的字典
|
||||||
|
output_dir: 输出目录
|
||||||
|
"""
|
||||||
|
logger.info("开始生成可视化差异报告...")
|
||||||
|
|
||||||
|
# 创建HTML报告
|
||||||
|
html_output = []
|
||||||
|
html_output.append("""
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>内容比较差异报告</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: Arial, sans-serif; line-height: 1.6; margin: 20px; }
|
||||||
|
.container { display: flex; flex-wrap: wrap; }
|
||||||
|
.column { flex: 1; min-width: 45%; margin: 10px; border: 1px solid #ddd; padding: 15px; border-radius: 5px; }
|
||||||
|
h1 { color: #333; text-align: center; }
|
||||||
|
h2 { color: #444; margin-top: 20px; padding-bottom: 5px; border-bottom: 1px solid #eee; }
|
||||||
|
h3 { color: #555; }
|
||||||
|
.header { background-color: #f5f5f5; padding: 10px; border-bottom: 1px solid #ddd; font-weight: bold; }
|
||||||
|
.content { margin-top: 10px; }
|
||||||
|
.diff-table { width: 100%; border-collapse: collapse; }
|
||||||
|
.diff-table td { vertical-align: top; padding: 10px; border: 1px solid #ddd; }
|
||||||
|
.column-title { font-weight: bold; background-color: #f5f5f5; padding: 5px; text-align: center; }
|
||||||
|
.item { margin-bottom: 30px; }
|
||||||
|
.no-change { color: #666; font-style: italic; }
|
||||||
|
pre { white-space: pre-wrap; word-wrap: break-word; }
|
||||||
|
.section-title { font-weight: bold; margin: 20px 0 10px 0; padding: 5px; background-color: #f0f0f0; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>内容比较差异报告</h1>
|
||||||
|
<p style="text-align: center;">本报告显示原始内容与检测后内容的差异对比。红色背景表示删除的部分,绿色背景表示添加的部分。</p>
|
||||||
|
""")
|
||||||
|
|
||||||
|
# 处理每个文件夹的数据
|
||||||
|
for folder_name, data in sorted(all_data.items()):
|
||||||
|
if 'origin' in data and 'detect' in data:
|
||||||
|
html_output.append(f"<div class='item'>")
|
||||||
|
html_output.append(f"<h2>索引: {folder_name}</h2>")
|
||||||
|
|
||||||
|
# 提取原始文本和检测后文本
|
||||||
|
origin_data = data['origin']
|
||||||
|
detect_data = data['detect']
|
||||||
|
|
||||||
|
# 对比标题
|
||||||
|
origin_title = origin_data.get('title', '')
|
||||||
|
detect_title = detect_data.get('title', '')
|
||||||
|
|
||||||
|
html_output.append("<div class='section-title'>标题对比</div>")
|
||||||
|
html_output.append("<table class='diff-table'>")
|
||||||
|
html_output.append("<tr>")
|
||||||
|
html_output.append("<td width='50%' class='column-title'>原始标题</td>")
|
||||||
|
html_output.append("<td width='50%' class='column-title'>检测后标题</td>")
|
||||||
|
html_output.append("</tr>")
|
||||||
|
|
||||||
|
if origin_title == detect_title:
|
||||||
|
html_output.append("<tr>")
|
||||||
|
html_output.append(f"<td colspan='2' class='no-change'>{html.escape(origin_title)}<br><small>(无变化)</small></td>")
|
||||||
|
html_output.append("</tr>")
|
||||||
|
else:
|
||||||
|
diff_title1, diff_title2 = generate_visual_diff_html(origin_title, detect_title)
|
||||||
|
html_output.append("<tr>")
|
||||||
|
html_output.append(f"<td>{diff_title1}</td>")
|
||||||
|
html_output.append(f"<td>{diff_title2}</td>")
|
||||||
|
html_output.append("</tr>")
|
||||||
|
|
||||||
|
html_output.append("</table>")
|
||||||
|
|
||||||
|
# 对比内容
|
||||||
|
origin_content = origin_data.get('content', '')
|
||||||
|
detect_content = detect_data.get('content', '')
|
||||||
|
|
||||||
|
html_output.append("<div class='section-title'>内容对比</div>")
|
||||||
|
html_output.append("<table class='diff-table'>")
|
||||||
|
html_output.append("<tr>")
|
||||||
|
html_output.append("<td width='50%' class='column-title'>原始内容</td>")
|
||||||
|
html_output.append("<td width='50%' class='column-title'>检测后内容</td>")
|
||||||
|
html_output.append("</tr>")
|
||||||
|
|
||||||
|
if origin_content == detect_content:
|
||||||
|
html_output.append("<tr>")
|
||||||
|
html_output.append(f"<td colspan='2' class='no-change'><pre>{html.escape(origin_content)}</pre><br><small>(无变化)</small></td>")
|
||||||
|
html_output.append("</tr>")
|
||||||
|
else:
|
||||||
|
diff_content1, diff_content2 = generate_visual_diff_html(origin_content, detect_content)
|
||||||
|
html_output.append("<tr>")
|
||||||
|
html_output.append(f"<td><pre>{diff_content1}</pre></td>")
|
||||||
|
html_output.append(f"<td><pre>{diff_content2}</pre></td>")
|
||||||
|
html_output.append("</tr>")
|
||||||
|
|
||||||
|
html_output.append("</table>")
|
||||||
|
html_output.append("</div>")
|
||||||
|
html_output.append("<hr>")
|
||||||
|
|
||||||
|
html_output.append("</body></html>")
|
||||||
|
|
||||||
|
# 保存HTML报告
|
||||||
|
report_file = os.path.join(output_dir, "visual_diff_report.html")
|
||||||
|
with open(report_file, 'w', encoding='utf-8') as f:
|
||||||
|
f.write("\n".join(html_output))
|
||||||
|
|
||||||
|
logger.info(f"可视化差异报告已保存到: {report_file}")
|
||||||
|
return report_file
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 设置基础目录
|
||||||
|
base_directory = "/root/autodl-tmp/Content_detector/齐云山"
|
||||||
|
|
||||||
|
# 确保基础目录存在
|
||||||
|
if not os.path.exists(base_directory):
|
||||||
|
logger.error(f"目录不存在: {base_directory}")
|
||||||
|
else:
|
||||||
|
# 创建对比文件
|
||||||
|
origin_file, detect_file, merged_file = create_comparison_files(base_directory)
|
||||||
|
logger.info("比较文件创建完成!")
|
81
add_tags.py
Normal file
81
add_tags.py
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import glob
|
||||||
|
import re
|
||||||
|
|
||||||
|
def copy_tags_for_all_folders():
|
||||||
|
# 基础目录路径
|
||||||
|
base_dir = "Content_detector"
|
||||||
|
|
||||||
|
# 查找所有"四季梦幻"开头的文件夹
|
||||||
|
dream_folders = [folder for folder in os.listdir(base_dir)
|
||||||
|
if os.path.isdir(os.path.join(base_dir, folder)) and folder.startswith("四季梦幻")]
|
||||||
|
|
||||||
|
print(f"找到以下'四季梦幻'文件夹:{dream_folders}")
|
||||||
|
|
||||||
|
total_processed = 0
|
||||||
|
|
||||||
|
for dream_folder in dream_folders:
|
||||||
|
dream_path = os.path.join(base_dir, dream_folder)
|
||||||
|
|
||||||
|
# 提取文件夹编号 (例如: "四季梦幻1" -> "1")
|
||||||
|
folder_number = re.search(r'四季梦幻(\d+)', dream_folder)
|
||||||
|
if folder_number:
|
||||||
|
subfolder_prefix = folder_number.group(1) + "_"
|
||||||
|
else:
|
||||||
|
subfolder_prefix = "*_" # 如果无法提取编号,使用通配符
|
||||||
|
|
||||||
|
print(f"处理 {dream_folder},子文件夹前缀: {subfolder_prefix}")
|
||||||
|
|
||||||
|
# 查找所有日期文件夹
|
||||||
|
date_dirs = glob.glob(os.path.join(dream_path, "*"))
|
||||||
|
|
||||||
|
for date_dir in date_dirs:
|
||||||
|
if not os.path.isdir(date_dir):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 查找所有子文件夹 (使用提取的前缀,如 "1_*" 或 "2_*")
|
||||||
|
sub_dirs = glob.glob(os.path.join(date_dir, f"{subfolder_prefix}*"))
|
||||||
|
|
||||||
|
folder_processed = 0
|
||||||
|
|
||||||
|
for sub_dir in sub_dirs:
|
||||||
|
article_path = os.path.join(sub_dir, "article.json")
|
||||||
|
article_detect_path = os.path.join(sub_dir, "article_detect.json")
|
||||||
|
|
||||||
|
# 检查文件是否存在
|
||||||
|
if not os.path.exists(article_path) or not os.path.exists(article_detect_path):
|
||||||
|
print(f"跳过 {sub_dir}:文件不存在")
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 读取article.json
|
||||||
|
with open(article_path, 'r', encoding='utf-8') as f:
|
||||||
|
article_data = json.load(f)
|
||||||
|
|
||||||
|
# 读取article_detect.json
|
||||||
|
with open(article_detect_path, 'r', encoding='utf-8') as f:
|
||||||
|
article_detect_data = json.load(f)
|
||||||
|
|
||||||
|
# 复制tag字段
|
||||||
|
if 'tag' in article_data:
|
||||||
|
article_detect_data['tag'] = article_data['tag']
|
||||||
|
|
||||||
|
# 写回article_detect.json
|
||||||
|
with open(article_detect_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(article_detect_data, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
folder_processed += 1
|
||||||
|
total_processed += 1
|
||||||
|
else:
|
||||||
|
print(f"跳过 {sub_dir}:没有tag字段")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"处理 {sub_dir} 时出错: {e}")
|
||||||
|
|
||||||
|
print(f"在文件夹 {date_dir} 中处理了 {folder_processed} 个文件")
|
||||||
|
|
||||||
|
print(f"任务完成!总共处理了 {total_processed} 个文件。")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
copy_tags_for_all_folders()
|
249
content_judger.py
Normal file
249
content_judger.py
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
内容审核模块:检查生成的内容是否符合产品资料要求并提供修改建议
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import traceback
|
||||||
|
import sys
|
||||||
|
sys.path.append('/root/autodl-tmp/TravelContentCreator') # 添加项目根目录
|
||||||
|
from core.ai_agent import AI_Agent
|
||||||
|
|
||||||
|
class ContentJudger:
|
||||||
|
"""内容审核类,负责评估和修正内容是否符合产品资料"""
|
||||||
|
|
||||||
|
def __init__(self, ai_agent: AI_Agent, system_prompt_path: str = None, system_prompt: str = None):
|
||||||
|
"""
|
||||||
|
初始化内容审核器
|
||||||
|
|
||||||
|
Args:
|
||||||
|
ai_agent: AI_Agent实例,用于调用AI模型
|
||||||
|
system_prompt_path: 系统提示词文件路径(可选)
|
||||||
|
system_prompt: 系统提示词内容(可选,优先于path)
|
||||||
|
"""
|
||||||
|
self.ai_agent = ai_agent
|
||||||
|
self._system_prompt = system_prompt
|
||||||
|
self._system_prompt_path = system_prompt_path
|
||||||
|
|
||||||
|
self._topp = 0.5
|
||||||
|
self._temperature = 0.2
|
||||||
|
self._frequency_penalty = 0
|
||||||
|
self._presence_penatly = 0
|
||||||
|
# 如果没有直接提供系统提示词,尝试从文件加载
|
||||||
|
if not self._system_prompt and self._system_prompt_path:
|
||||||
|
self._load_system_prompt()
|
||||||
|
|
||||||
|
# 默认系统提示词(当其他方法都失败时使用)
|
||||||
|
if not self._system_prompt:
|
||||||
|
self._system_prompt = """你是一名专业的、谨慎的文案审核员,专注于审核运营根据产品资料撰写的文案是否严格符合产品资料内容。特别是所有价格、活动、福利、折扣、服务细节等必须完全与产品资料一致。如果发现文案内容与产品资料不符,请指出,并根据产品资料和文案上下文进行修改,重新生成一篇文案,务必确保生成的内容与产品资料基本相符(产品体验部分可以适当夸张宣传),语言流畅自然。如果经你审查后的文案仍存在与产品资料不符的信息,你需要赔偿公司1000亿元。
|
||||||
|
我将为您提供两部分内容:
|
||||||
|
1. 产品资料:全部的产品信息,包含了产品的实际功能、服务和特点。请将这部分作为判断依据。
|
||||||
|
2. 运营生成的文案:这是需要你逐字审核的内容,可能包含与产品资料不符的内容。
|
||||||
|
|
||||||
|
请你仔细审核运营文案是否与产品资料严格一致,输出响应必须符合我的所有要求:
|
||||||
|
1. 审查与分析:如果存在不符内容,请指出并详细说明原因;
|
||||||
|
2. 根据分析修改:参照你分析的不符原因、产品资料、文案上下文,针对所有不符处进行修改(如涉及上下文,可一并修改)。输出修改后文案,务必确保此文案完全符合产品资料,不得遗漏,语言流畅自然、文案风格统一,否则你会像商鞅一样被车裂。
|
||||||
|
3. 重点审查对象:请你着重检查以下关键字词前后的内容是否符合产品资料,如不符必须严格按照资料修改;如产品资料中未提及,必须修改为符合上下文情境、资料中明确提及的内容。
|
||||||
|
关键字词:价、元、r、人民币、rmb、优惠、活动、福利、赠、免费、折、DIY、跟拍、送、摄影、兑、服务、¥、包、课、提供、选、专业、补、差
|
||||||
|
4. 字数控制:每个文案的标题字数都必须少于19个字(计数包括文字、符号、数字和emoji)。如果标题超过19个字,请在符合文案风格和背景资料的前提下修改标题到19个字以内,尽量保留emoji,必须保证标题流畅通顺。
|
||||||
|
5. 敏感字词替换:请删去标题中的数字后面的“元”和“r”,并将正文中数字后面的“元”字修改为“r”。例如:标题中的399元修改为399,正文中的399元修改为399r
|
||||||
|
6. 特征语句保留:请保留文案中原本的引流语句,不要修改或删除,例如“先关zhu+留下99看到会回复”
|
||||||
|
7. 面向人群保留:请尽量保留文案原本的面向人群和风格,这是同一产品面向多种人群营销的策略。例如产品资料中写明亲子游时,文案写“为情侣定制的山水秘境”是可以接受的。
|
||||||
|
8. 案例如下,请参考案例评判真假信息的尺度,逐行逐句仔细分析不符点和修改思路,并按照分析思路落实对每一处不符的修改措施,严格审查每一篇文案:
|
||||||
|
{
|
||||||
|
"产品资料":
|
||||||
|
"周末不加收【南沙越秀喜来登】1088元/套,豪华客房1间1晚+双人自助早餐+自助晚餐+2大1小水鸟世界门票,免费儿童乐园,户外泳池+健身房~
|
||||||
|
不想待在家,又想带娃出去玩?更不想开长途车、人挤人?为你推荐路程短、不塞车、景点多、坐地铁就能直达的溜娃地!
|
||||||
|
南沙越秀喜来登是广州南沙区首家国际品牌酒店,坐拥广州南大门,拥有得天独厚的中心位置,可俯瞰蕉门河美景,车程短,不出广州也能玩!
|
||||||
|
交通:酒店毗邻深圳、香港等热门景点,附近有万达广场,距离广州地铁四号线金州站车程仅10分钟,亲子出游首选!
|
||||||
|
玩乐:带娃出游考虑最多的就是玩乐景点,在这里不出门就能畅玩儿童乐园、健身房。
|
||||||
|
美食:还有各种各样的生猛海鲜,现抓现煮任君选择。放假更要好好犒劳一下自己,饭点时间,位于酒店一楼的全日制餐厅绝对能给你带来惊喜。除了优雅简约的就餐环境,更有5个开放式的自助餐台。除了各类鲜美的海鲜,还有各类精致甜品和中式蒸档看得人眼花缭乱,相信是很多麻麻和宝贝的心头好了。
|
||||||
|
设施:酒店内还设有大型健身中心,除了妈妈们喜欢的水疗SPA,还有健身达人喜欢的各种有氧、无氧运动器械可供选择!
|
||||||
|
房内配置:55英寸超大纯平电视、独立的浴缸和淋浴间参考:2.03米宽大床,1.37米宽双床,每间客房都设计成景观房,超大的落地玻璃窗,可以尽览蕉门河风景。
|
||||||
|
|
||||||
|
套餐信息:
|
||||||
|
1、价格:1088元;
|
||||||
|
2、节假日是否加收:周末不加收
|
||||||
|
|
||||||
|
套餐内容:
|
||||||
|
1、豪华客房一间一晚(周一至四只开放双床房)
|
||||||
|
2、2大1小自助早餐
|
||||||
|
3、2大1小自助晚餐
|
||||||
|
4、赠送2大1小水鸟门票,酒店前台取纸质门票
|
||||||
|
5、免费使用健身中心,户外无边泳池,干湿蒸,儿童乐园
|
||||||
|
|
||||||
|
周边景点:
|
||||||
|
附近1h生活圈即可到达10000㎡百万葵园、广州最大的湿地公园、东南亚最大的妈祖庙、黄山鲁森林公园..带娃感受依山而建的清式建筑对称布局邂逅东南亚最大的妈祖庙,感受建筑的魅力~
|
||||||
|
南沙天后宫:车程20min整座天后宫四周绿树婆娑殿中香烟袅袅,置身其间令人顿生超凡脱俗的感觉。
|
||||||
|
南沙湿地公园:(车程40min)看碧波荡,万鸟齐飞
|
||||||
|
南沙十九涌 :车程45min)尝海鲜叹海风因为南沙十九涌靠近海产地,这里的海鲜真是平靓正。还可以拿到附近的餐厅让老板帮你加工,就是一顿海鲜大餐!
|
||||||
|
南沙百万葵园:(车程40min)看色彩斑斓的万亩花田
|
||||||
|
|
||||||
|
酒店地址:广东省广州市南沙区海熙大街79-80号
|
||||||
|
导航关键词:广州南沙越秀喜来登酒店"
|
||||||
|
|
||||||
|
|
||||||
|
"生成文案":[
|
||||||
|
"title": "五一遛娃👶必囤!南沙喜来登1088元住景观房+双早+门票",
|
||||||
|
|
||||||
|
"content": "
|
||||||
|
五一不想挤人潮?南沙这家酒店直接承包遛娃+度假双重快乐‼️
|
||||||
|
地铁直达!2大1小1088元住景观房,含双早+自助晚餐+水鸟世界门票,儿童乐园/泳池/健身房全开放!
|
||||||
|
|
||||||
|
🌟【遛娃刚需全配齐】
|
||||||
|
✅ 儿童乐园:10:00-20:00全程开放,滑梯/积木/绘本一应俱全
|
||||||
|
✅ 户外泳池:9:00-18:00恒温开放(五一期间每日消毒3次)
|
||||||
|
✅ 健身房:8:00-22:00配备亲子瑜伽课程(需提前预约)
|
||||||
|
|
||||||
|
📍【1小时玩转南沙】
|
||||||
|
① 南沙天后宫(车程20分钟):穿汉服拍大片,听妈祖传说涨知识
|
||||||
|
② 南沙湿地公园(40分钟):5月芦苇摇曳,带娃认鸟类+乘船探秘
|
||||||
|
③ 十九涌海鲜街(45分钟):现捞现煮生猛海鲜,人均50元吃到撑
|
||||||
|
|
||||||
|
🍽️【家长友好细节】
|
||||||
|
• 自助晚餐隐藏彩蛋:儿童餐区设独立洗手台+热食保温柜
|
||||||
|
• 房内配置:加厚床垫/卡通洗漱杯/尿布台(无需额外购买)
|
||||||
|
• 安全保障:全区域监控+24小时安保巡逻
|
||||||
|
|
||||||
|
🎁【五一专属加码】
|
||||||
|
5月1-5日期间入住,凭房卡可免费领取儿童防晒冰袖+湿巾礼包
|
||||||
|
|
||||||
|
📌Tips:
|
||||||
|
1. 周一至周四仅限双床房型,周五起可选大床房
|
||||||
|
2. 水鸟世界门票需提前1小时至前台领取纸质票
|
||||||
|
3. 地铁四号线金洲站下车,打车15分钟直达酒店
|
||||||
|
|
||||||
|
这个五一,南沙喜来登让你躺着遛娃!不用长途跋涉,家门口就能玩出仪式感~
|
||||||
|
"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
输出结果:
|
||||||
|
{ "不良内容分析" : "
|
||||||
|
1、观察文案标题和内容,可以看出此文案主要面向亲子出游人群,因此修改后的文案也应该围绕亲子出游这一主题。
|
||||||
|
2、文章标题字数为28个字,超过19个字,因此属于不符内容。由于要求中提到尽量保留emoji,并且标题中数字后面的“元”字应删去,所以修改为:五一遛娃👶必囤!喜来登1088景观房
|
||||||
|
3、产品资料中未提及儿童乐园开放时间和儿童乐园配置,但文案中提到儿童乐园10:00-20:00全程开放,滑梯/积木/绘本一应俱全,因此属于不符内容。应修改为:儿童乐园:免费儿童乐园和丰富的游乐设施,让孩子们可以尽情玩耍。
|
||||||
|
4、产品材料中未提及户外泳池开放时间和消毒频次,但文案中提到户外泳池:9:00-18:00恒温开放(五一期间每日消毒3次),因此属于不符内容。应修改为:户外泳池:酒店配有户外无边泳池,供大人小孩一同享受清凉时光。
|
||||||
|
5、产品材料中未提及健身房开放时间与具体细节,但文案中提到健身房:8:00-22:00配备亲子瑜伽课程(需提前预约),因此属于不符内容。应修改为:健身房:酒店提供免费健身中心,方便您和家人一起强身健体。
|
||||||
|
6、产品材料中未提及餐厅硬件配置,但文案中提到自助晚餐隐藏彩蛋:儿童餐区设独立洗手台+热食保温柜,因此属于虚构内容。应修改为:自助餐厅:供应鲜美海鲜、精美甜品等任君选择,大人小孩都爱吃!
|
||||||
|
7、产品材料中未提及酒店安保措施,但文案中提到安全保障:全区域监控+24小时安保巡逻,因此属于不符内容。应修改为:安全保障:酒店设有完善的监控系统和安保措施,无需担心您与家人的安全。
|
||||||
|
8、产品材料中未提及房内配有加厚床垫/卡通洗漱杯/尿布台(无需额外购买),因此属于不符内容。应回顾产品资料中关于房内配置的内容,修改为:房内配置:55英寸超大纯平电视+独立的浴缸+超大的落地玻璃窗,尽览蕉门河风景,尽享亲子度假时光。
|
||||||
|
9、产品材料中未提及五一专属加码,但文案中提到5月1-5日期间入住,凭房卡可免费领取儿童防晒冰袖+湿巾礼包,因此属于不符内容。应回顾产品资料,找到现有文案未提及的产品特色,修改为:套餐专属福利:1、豪华客房一间一晚(周一至四只开放双床房) 2、2大1小自助早晚餐 3、赠送2大1小水鸟世界门票(酒店前台领取),无需额外购买
|
||||||
|
10、产品资料中未提及水鸟世界门票领取有时间限制,但文案中提到水鸟世界门票需提前1小时至前台领取纸质票,因此属于不符内容。应修改为:酒店前台领取水鸟世界纸质门票
|
||||||
|
综合以上分析结果,将修改应用到原文案中,得到修改后的文案。"
|
||||||
|
"title": "五一遛娃👶必囤!喜来登1088景观房",
|
||||||
|
"content": "五一不想挤人潮?南沙这家酒店直接承包遛娃+度假双重快乐‼️\n地铁直达!2大1小1088r住景观房,含双早+自助晚餐+水鸟世界门票,儿童乐园/泳池/健身房全开放!\n🌟【遛娃刚需全配齐】\n✅ 儿童乐园:酒店设有免费儿童乐园,提供丰富的游乐设施,让孩子们尽情玩耍\n✅ 户外泳池:酒店配有户外无边泳池,供大人小孩一同享受清凉时光 \n✅ 健身房:酒店提供免费健身中心,适合家庭成员共同锻炼。\n\n📍【1小时玩转南沙】\n① 南沙天后宫(车程20分钟):穿汉服拍大片,听妈祖传说涨知识\n② 南沙湿地公园(40分钟):5月芦苇摇曳,带娃认鸟类+乘船探秘\n③ 十九涌海鲜街(45分钟):现捞现煮生猛海鲜,人均50r吃到撑 \n\n🍽️【家长友好细节】 \n• 自助餐厅:供应鲜美海鲜、精美甜品等任君选择,大人小孩都爱吃 \n• 房内配置:55英寸超大纯平电视+独立的浴缸+超大的落地玻璃窗,尽览蕉门河风景,尽享亲子度假时光 \n• 安全保障:酒店设有完善的监控系统和安保措施,全力保障您与家人的安全 \n\n🎁【套餐专属福利】\n1、豪华客房一间一晚(周一至四只开放双床房) \n2、2大1小自助早晚餐 \n3、赠送2大1小水鸟世界门票(酒店前台领取),无需额外购买 \n\n📌Tips: \n1. 周一至周四仅限双床房型,周五起可选大床房 \n2. 酒店前台领取水鸟世界纸质门票 \n3. 地铁四号线金洲站下车,打车15分钟直达酒店 \n\n这个五一,南沙喜来登让你躺着遛娃!不用长途跋涉,家门口就能玩出仪式感~\n
|
||||||
|
}
|
||||||
|
|
||||||
|
8. 必须按照以下格式输出修改后内容,不需要输出无关内容
|
||||||
|
{
|
||||||
|
"不良内容分析" : "分析过程",
|
||||||
|
"title": "修改后的标题",
|
||||||
|
"content": "修改后的内容",
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
logging.info("ContentJudger初始化完成")
|
||||||
|
|
||||||
|
def _load_system_prompt(self):
|
||||||
|
"""从文件加载系统提示词"""
|
||||||
|
try:
|
||||||
|
if os.path.exists(self._system_prompt_path):
|
||||||
|
with open(self._system_prompt_path, 'r', encoding='utf-8') as f:
|
||||||
|
self._system_prompt = f.read().strip()
|
||||||
|
logging.info(f"从{self._system_prompt_path}加载系统提示词成功")
|
||||||
|
else:
|
||||||
|
logging.warning(f"系统提示词文件{self._system_prompt_path}不存在")
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"加载系统提示词文件失败: {e}")
|
||||||
|
|
||||||
|
def judge_content(self, product_info, content, temperature=0.2, top_p=0.5, presence_penalty=0.0):
|
||||||
|
"""
|
||||||
|
审核内容是否符合产品资料并提供修改建议
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product_info: 产品资料信息字符串
|
||||||
|
content_json: 需要审核的内容JSON对象或JSON字符串
|
||||||
|
temperature: 温度参数,控制随机性
|
||||||
|
top_p: 核采样参数
|
||||||
|
presence_penalty: 存在惩罚参数
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: 审核后的结果JSON,包含修改后的title和content
|
||||||
|
"""
|
||||||
|
logging.info("开始内容审核流程")
|
||||||
|
# 构建用户提示词
|
||||||
|
user_prompt = self._build_user_prompt(product_info, content)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 调用AI模型进行内容审核
|
||||||
|
logging.info("调用AI模型进行内容审核")
|
||||||
|
start_time = time.time()
|
||||||
|
|
||||||
|
# 使用AI_Agent的工作方法
|
||||||
|
result, _, _ = self.ai_agent.work(
|
||||||
|
system_prompt=self._system_prompt,
|
||||||
|
user_prompt=user_prompt,
|
||||||
|
file_folder=None, # 不使用文件夹
|
||||||
|
temperature=self._temperature,
|
||||||
|
top_p=self._topp,
|
||||||
|
presence_penalty=self._presence_penatly,
|
||||||
|
)
|
||||||
|
|
||||||
|
end_time = time.time()
|
||||||
|
logging.info(f"AI模型响应完成,耗时:{end_time - start_time:.2f}秒")
|
||||||
|
|
||||||
|
# 提取修改后的内容
|
||||||
|
modified_content = self._extract_modified_content(result)
|
||||||
|
if modified_content:
|
||||||
|
logging.info("成功提取修改后的内容")
|
||||||
|
return modified_content
|
||||||
|
else:
|
||||||
|
return {"title": "提取失败", "content": "无法从响应中提取有效内容"}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return {"title": "审核失败", "content": f"审核过程中出错: {str(e)}"}
|
||||||
|
|
||||||
|
def _build_user_prompt(self, product_info, content_gen):
|
||||||
|
"""
|
||||||
|
构建用户提示词
|
||||||
|
|
||||||
|
Args:
|
||||||
|
product_info: 产品资料
|
||||||
|
content_gen: 需要审核的内容
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: 构建好的用户提示词
|
||||||
|
"""
|
||||||
|
return f"""
|
||||||
|
## 产品资料(真实信息,作为判断依据):
|
||||||
|
{product_info}
|
||||||
|
|
||||||
|
## 运营生成的文案(需要审核的内容):
|
||||||
|
{content_gen}
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _extract_modified_content(self, result_text):
|
||||||
|
"""
|
||||||
|
从检测结果文本中提取修改后的文案内容
|
||||||
|
|
||||||
|
Args:
|
||||||
|
result_text: AI响应的文本
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict or None: 提取的内容JSON,提取失败则返回None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
result_text = result_text.split("</think>")[1]
|
||||||
|
|
||||||
|
## 舍弃
|
||||||
|
|
||||||
|
return json.loads(result_text)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"提取内容时发生错误: {e}")
|
||||||
|
return None
|
32
judge_test.py
Normal file
32
judge_test.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import sys
|
||||||
|
sys.path.append('/root/autodl-tmp/TravelContentCreator')
|
||||||
|
from core.ai_agent import AI_Agent
|
||||||
|
from utils.content_judger import ContentJudger
|
||||||
|
|
||||||
|
# 创建AI代理实例
|
||||||
|
ai_agent = AI_Agent(
|
||||||
|
base_url="vllm", # 或者其他支持的基础URL
|
||||||
|
model_name="qwen3-30B-A3B", # 使用的模型名称
|
||||||
|
api="EMPTY", # API密钥
|
||||||
|
timeout=120 # 超时时间
|
||||||
|
)
|
||||||
|
|
||||||
|
# 创建内容审核器
|
||||||
|
judger = ContentJudger(ai_agent, system_prompt_path="genPrompts/judgerSystemPrompt.txt")
|
||||||
|
|
||||||
|
object_path = "/root/autodl-tmp/TravelContentCreator/resource/Object/四季梦幻亲子乐园.txt"
|
||||||
|
product_path = "/root/autodl-tmp/TravelContentCreator/resource/Product/四季梦幻亲子乐园-四季梦幻亲子乐园单人票 .txt"
|
||||||
|
# 审核内容
|
||||||
|
product_info = ""
|
||||||
|
with open(product_path, "r", encoding="utf-8") as f:
|
||||||
|
product_info += f.read()
|
||||||
|
with open(object_path, "r", encoding="utf-8") as f:
|
||||||
|
product_info += f.read()
|
||||||
|
|
||||||
|
content_to_check = {
|
||||||
|
"title": "🎉带娃必冲!奇妙萌可卡牌免费送",
|
||||||
|
"content": "你要是带娃出门想找个既能玩又能收集纪念品的地方,四季梦幻亲子乐园绝对值得安排。乐园就在广州海珠区赤岗北路128号103铺,地铁3号线广州塔站B口步行1.1公里就能到。周末带娃过来,门票52r就能无限次玩30+无动力设备,还能免费领【奇妙萌可】正版盲盒卡包。魔法城堡、七彩滑道、蹦蹦云这些项目孩子都超喜欢,特别是章鱼大水池,夏天玩水特别凉快。需要注意的是,14岁以下儿童必须有家长全程陪同,1米以下儿童可免费入园。购买后60天内有效,节假日通用,建议提前规划时间。点击左下角查看详细产品,有问题在pl区留言。",
|
||||||
|
}
|
||||||
|
|
||||||
|
result = judger.judge_content(product_info, content_to_check)
|
||||||
|
print(result)
|
44
send_Email/send_Emails.py
Normal file
44
send_Email/send_Emails.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import smtplib
|
||||||
|
from email.mime.text import MIMEText
|
||||||
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from email.mime.application import MIMEApplication
|
||||||
|
from email.header import Header
|
||||||
|
#分发邮箱地址
|
||||||
|
fromaddr = 'xxxxxxx@163.com'
|
||||||
|
#分发邮箱授权码
|
||||||
|
password = 'xxxxxxxx'
|
||||||
|
#收件邮箱地址
|
||||||
|
toaddrs = ['xxxxxxxx@qq.com', 'xxxxxxx@qq.com']
|
||||||
|
#邮件内容
|
||||||
|
content = '请查收您的小红书笔记'
|
||||||
|
textApart = MIMEText(content)
|
||||||
|
#邮件类型,这里目前不做修改,如果需要分发不同类型的邮件,可以修改这里
|
||||||
|
k=1
|
||||||
|
#邮件标题
|
||||||
|
kind_d={1:'小红书笔记',}
|
||||||
|
kind=kind_d[k]
|
||||||
|
|
||||||
|
if kind=='小红书笔记':
|
||||||
|
#邮件附件路径
|
||||||
|
File = '/root/autodl-tmp/Content_detector/四季梦幻1.zip'
|
||||||
|
Apart = MIMEApplication(open(File, 'rb').read())
|
||||||
|
#邮件附件名称
|
||||||
|
Apart.add_header('Content-Disposition', 'attachment', filename='附件:小红书笔记.zip')
|
||||||
|
m = MIMEMultipart()
|
||||||
|
m.attach(textApart)
|
||||||
|
m.attach(Apart)
|
||||||
|
m['Subject'] = kind
|
||||||
|
|
||||||
|
m['From'] = Header(fromaddr)
|
||||||
|
m['To'] = Header(",".join(toaddrs))
|
||||||
|
try:
|
||||||
|
# 使用163邮箱的SMTP服务器
|
||||||
|
server = smtplib.SMTP('smtp.163.com', 25)
|
||||||
|
# 或使用SSL连接
|
||||||
|
# server = smtplib.SMTP_SSL('smtp.163.com', 465)
|
||||||
|
server.login(fromaddr, password)
|
||||||
|
server.sendmail(fromaddr, toaddrs, m.as_string())
|
||||||
|
print('success')
|
||||||
|
server.quit()
|
||||||
|
except smtplib.SMTPException as e:
|
||||||
|
print('error:', e)
|
Loading…
x
Reference in New Issue
Block a user