265 lines
11 KiB
Python
265 lines
11 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
英文台词优化 & 回填脚本
|
||
基于 MEMORY.md 的「对话台词优化通用规则」对列 E(编剧台词)进行优化,写入列 F
|
||
知识点:grandmother, grandfather, visit (v.), today (n.)
|
||
句型知识点:... visit+sb, Today is...
|
||
"""
|
||
import json, subprocess, sys
|
||
|
||
# Rules:
|
||
# 0. 知识点词汇/句型必须保留 (grandmother/grandfather/visit/today / Today is... / ...visit+sb)
|
||
# 1. 精简:删除冗余
|
||
# 2. 口语化:自然对话,低龄友好,增语气词
|
||
# 3. 拆分:>8词拆为2-3短句
|
||
# 4. 情绪匹配:匹配角色情绪
|
||
# 5. 场景适配:不重复画面信息
|
||
# 6. 单句≤10词,知识点句≤7词
|
||
|
||
# Knowledge-point words to preserve
|
||
KP_WORDS = {"grandmother", "grandfather", "visit", "today", "today's"}
|
||
|
||
# Mapping: (row_index_0based_sheet) → optimized F value
|
||
# Only rows where D (role) and E (script line) are non-null
|
||
# Row index = sheet row - 1 (0-based from API)
|
||
# Sheet row 1 = header → skip
|
||
# Sheet row 2 = API row index 1
|
||
|
||
optimizations = {}
|
||
|
||
def add(row_sheet, f_value):
|
||
"""row_sheet is 1-indexed sheet row number"""
|
||
optimizations[row_sheet - 1] = f_value # convert to 0-indexed
|
||
|
||
# === SECTION 1: 开场 - 门口 ===
|
||
add(3, "Open up!")
|
||
add(4, "Your letter is here!")
|
||
add(6, "Nobody answers?")
|
||
add(7, "Alright... I'll go in myself.")
|
||
add(9, "Whoa! What a mess!")
|
||
add(11, "What's wrong?")
|
||
add(12, "Vicky? Can you hear me?")
|
||
|
||
# === SECTION 2: 发现家里很乱 ===
|
||
add(14, "Today is a No-Mom-and-Dad day!") # 知识点 Today is
|
||
add(15, "Our parents aren't home!") # 精简 + 口语化
|
||
add(16, "So we can do whatever we want!")
|
||
add(17, "Really?")
|
||
add(19, "Yes!")
|
||
add(20, "Today is a good day!") # 知识点 Today is
|
||
add(21, "Huh?")
|
||
add(22, "Are you sure today is a good day?") # 知识点 today
|
||
|
||
# === SECTION 3: 撞到用户,道歉 ===
|
||
add(23, "So on a good day, nobody says sorry?") # 精简 14→8词
|
||
add(24, "Eva, Peter, say sorry.")
|
||
add(25, "Okay. We're sorry.") # 口语化
|
||
|
||
# === SECTION 4: 继续对话 ===
|
||
add(27, "Ah, kids.")
|
||
add(28, "Come visit us!") # 知识点 visit,修正"Welcome to visit us"不自然表达
|
||
add(29, "Oh, I'm not here to visit.") # 知识点 visit,口语化
|
||
add(30, "I'm here to give you something.") # 口语化
|
||
|
||
# === SECTION 5: 电话 ===
|
||
add(33, "Hello? Grandfather and grandmother, how are you?") # 知识点 grandfather/grandmother
|
||
add(34, "Good, good! We're great!") # 口语化
|
||
add(35, "How are you all, my lovely grandchildren?")
|
||
add(36, "We're great! Today is so much fun!") # 知识点 Today is, 口语化
|
||
add(37, "Great to hear that!")
|
||
add(38, "Are you ready for us?") # 精简
|
||
add(39, "I'm so excited to visit you all!") # 知识点 visit, 口语化
|
||
add(40, "Sure! When will you visit us?") # 知识点 visit
|
||
add(41, "Today is the day, of course!") # 知识点 Today is
|
||
add(42, "What? You're both coming today?") # 口语化修复
|
||
add(43, "Yes! Me and Justin. Your grandmother and grandfather.") # 知识点, 修正 typo gandfather
|
||
add(44, "We sent you a letter. Remember?") # 口语化
|
||
add(45, "See you later!")
|
||
add(46, "I love you! Bye!")
|
||
|
||
# === SECTION 6: 惊慌 ===
|
||
add(48, "Oh no! What did they say on the phone?") # 修正语法 in→on
|
||
add(50, "Your grandfather and grandmother are coming to visit you!") # 知识点, 修正 is→are
|
||
add(51, "On your good day.")
|
||
|
||
# === SECTION 7: 紧急动员 ===
|
||
add(54, "Eva! Peter! Alex! We're in trouble!") # 口语化
|
||
add(56, "What happened?")
|
||
add(57, "Grandfather and grandmother are coming to visit us!") # 知识点, 修正 is→are
|
||
add(58, "So what?")
|
||
add(59, "Today! Right now!") # 精简 On today→Today
|
||
add(62, "No, not today...") # 修正 on today→today
|
||
add(63, "Look at this place!")
|
||
|
||
# === SECTION 8: 用户互动 ===
|
||
add(65, "Yes, today is a total mess.") # 知识点 today
|
||
add(66, "It's not the best day for visitors.") # 知识点 visit→visitors 可接受变体, 口语化
|
||
add(68, "They could be here at any minute!") # 口语化
|
||
|
||
# === SECTION 9: 爷爷奶奶会生气 ===
|
||
add(70, "How will they feel about this?")
|
||
add(72, "Grandfather and grandmother will be so upset!") # 知识点, 精简 mad→upset (正向引导)
|
||
add(74, "What should we do?")
|
||
add(76, "Don't worry! I'll help you clean up!") # 增加具体动作词
|
||
add(77, "Okay, first pick up the toys from the floor.")
|
||
|
||
# === SECTION 10: 收拾 ===
|
||
add(80, "Oh no! No time to put these away!") # 精简
|
||
add(81, "Put them in the cupboard!") # 修正 it→them (玩具是复数)
|
||
add(83, "Your grandfather and grandmother won't see!") # 知识点
|
||
add(85, "Good idea!")
|
||
add(88, "All done!")
|
||
add(89, "We need to clean the floor!")
|
||
add(90, "I'll do it!") # 口语化
|
||
|
||
# === SECTION 11: 扫地机器人 ===
|
||
add(94, "Will Grandfather and Grandmother be happy?") # 知识点, satisfied→happy (低龄词)
|
||
add(95, "Well... this will do for now.") # 口语化
|
||
add(96, "Before your grandfather and grandmother come to visit.") # 知识点
|
||
|
||
# === SECTION 12: 沙发污渍 ===
|
||
add(99, "Alex! The sofa is a mess!") # 精简, 正向化 (不说 you made it dirty)
|
||
add(100, "I'll clean it.") # 口语化
|
||
add(103, "I can't get the chocolate off!")
|
||
add(104, "I'm good at many things. Just not housework!") # 拆分 >8词, 口语化
|
||
|
||
# === SECTION 13: 更乱 ===
|
||
add(106, "Oh no! We can't clean up in time!") # 精简+口语化
|
||
add(107, "I wish we had more time for this!")
|
||
add(108, "Why today, of all days?") # 口语化
|
||
add(109, "I don't want them to see our house like this.") # 口语化修正
|
||
add(110, "Why didn't they tell us earlier?") # 口语化修正
|
||
|
||
# === SECTION 14: 信 ===
|
||
add(113, "I think they did tell you...") # 精简+口语化
|
||
add(114, "In this letter.")
|
||
add(116, "What is in this letter?")
|
||
|
||
# === SECTION 15: 核心互动-听力 (Justin念信) ===
|
||
add(119, "Hi, your grandfather is writing this letter.") # 知识点 grandfather
|
||
add(120, "I will come to visit you guys.") # 知识点 visit
|
||
add(121, "Your grandmother will visit you too!") # 知识点 grandmother, visit
|
||
add(122, "We love you, see you soon!")
|
||
|
||
# === SECTION 16: 反应 ===
|
||
add(124, "They were so happy to visit you!") # 知识点 visit
|
||
add(125, "Yes. We should be happy too.")
|
||
add(127, "We should not be grumpy like this.")
|
||
add(128, "Let's do something to welcome them!") # 口语化
|
||
add(130, "You can make something they like!") # 知识点, 精简
|
||
add(131, "What is their favourite food?")
|
||
|
||
# === SECTION 17: 苹果派 ===
|
||
add(133, "Grandmother likes apples.") # 知识点 grandmother, 修正 apple→apples
|
||
add(134, "Grandfather likes pie.") # 知识点 grandfather
|
||
add(135, "Then you can make apple pie for them!")
|
||
add(136, "I remember the recipe.")
|
||
add(137, "I can fix the cooking robot.")
|
||
add(139, "Okay! Apple pie is today's welcome gift!") # 知识点 today
|
||
|
||
# === SECTION 18: 完成了 ===
|
||
add(142, "You did it!") # 口语化 (替换 You finished)
|
||
add(143, "Now we just wait for them to arrive.") # 精简
|
||
|
||
# === SECTION 19: 爷爷奶奶来了 ===
|
||
add(146, "They're coming!") # 口语化
|
||
add(148, "Who wants a big hug from Grandfather?") # 知识点, 修正语法
|
||
add(149, "Me! Me!")
|
||
add(150, "Who wants Grandmother's homemade candy?") # 知识点, 修正 grandmother→Grandmother's, handmade→homemade(低龄)
|
||
add(151, "Me! Me!")
|
||
add(153, "We made something for you.")
|
||
add(154, "Mmm! What's that smell? Is that a pie?") # 口语化
|
||
add(155, "I smell apples!") # 修正 apple→apples
|
||
add(156, "Whoa! I know that smell! Apple pie!") # 口语化
|
||
add(157, "That is our favourite!")
|
||
add(159, "Oh, you have a friend over!") # 修正 in home→over
|
||
add(161, "Hello! I am here to visit Vicky.") # 知识点 visit
|
||
add(162, "Nice to meet you again!")
|
||
add(163, "I guess you helped out today too.") # 知识点 today, 口语化修正
|
||
|
||
# === SECTION 20: 结尾 ===
|
||
add(165, "Today seems pretty busy.") # 知识点 today
|
||
add(167, "Yes, we made a little mess before you came.") # 知识点 visit, 口语化修正
|
||
add(168, "Today was not easy.") # 知识点 today, 修正时态 is→was
|
||
add(170, "That's okay.") # 口语化
|
||
add(172, "Grandfather and Grandmother can fix anything.") # 知识点, 口语化 everything→anything
|
||
add(173, "That's what family is for!") # 口语化重构
|
||
add(174, "Mess or not, we love seeing you!") # 口语化重构
|
||
|
||
|
||
# Print summary and build write payload
|
||
print(f"Total lines to write: {len(optimizations)}")
|
||
|
||
# Build values payload per row
|
||
# We need to identify continuous ranges for efficiency
|
||
# But since the API supports writing individual ranges, let's batch by nearby rows
|
||
|
||
# Sort by row index
|
||
sorted_rows = sorted(optimizations.items())
|
||
|
||
# Build the complete column F data: for each row, either the optimized value or empty string ("")
|
||
# We need all rows 2-149 (sheet rows)
|
||
all_values = []
|
||
for row_idx in range(1, 150): # 1 = sheet row 2, 149 = sheet row 150
|
||
if row_idx in optimizations:
|
||
all_values.append([optimizations[row_idx]])
|
||
else:
|
||
all_values.append([""])
|
||
|
||
# Write back - use PUT to write the entire column at once
|
||
# We write empty strings for non-dialogue rows to clear previous content
|
||
|
||
import os
|
||
import json as jmod
|
||
|
||
app_id = "cli_a931175d41799cc7"
|
||
config_path = "/root/.openclaw/credentials/xiaoyan/config.json"
|
||
with open(config_path) as f:
|
||
cfg = jmod.load(f)
|
||
app_secret = cfg["apps"][0]["appSecret"]
|
||
|
||
# Get token
|
||
result = subprocess.run([
|
||
"curl", "-s", "-X", "POST",
|
||
"https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal",
|
||
"-H", "Content-Type: application/json",
|
||
"-d", jmod.dumps({"app_id": app_id, "app_secret": app_secret})
|
||
], capture_output=True, text=True)
|
||
token = jmod.loads(result.stdout)["tenant_access_token"]
|
||
|
||
spreadsheet_token = "DA7csROG6hmnQMt59oScOLRfnWc"
|
||
sheet_id = "Nr3Ovs"
|
||
|
||
# Write in batches of 50 rows to avoid too-large payloads
|
||
batch_size = 50
|
||
for batch_start in range(0, len(all_values), batch_size):
|
||
batch = all_values[batch_start:batch_start + batch_size]
|
||
# Sheet rows: batch_start + 2 to batch_start + 1 + len(batch)
|
||
start_row = batch_start + 2
|
||
end_row = batch_start + 1 + len(batch)
|
||
|
||
range_str = f"{sheet_id}!F{start_row}:F{end_row}"
|
||
|
||
payload = {
|
||
"valueRange": {
|
||
"range": range_str,
|
||
"values": batch
|
||
}
|
||
}
|
||
|
||
result = subprocess.run([
|
||
"curl", "-s", "-X", "PUT",
|
||
f"https://open.feishu.cn/open-apis/sheets/v2/spreadsheets/{spreadsheet_token}/values",
|
||
"-H", f"Authorization: Bearer {token}",
|
||
"-H", "Content-Type: application/json",
|
||
"-d", jmod.dumps(payload)
|
||
], capture_output=True, text=True)
|
||
|
||
resp = jmod.loads(result.stdout)
|
||
print(f"Batch F{start_row}:F{end_row} → code={resp.get('code')}, msg={resp.get('msg')}")
|
||
if resp.get("code") != 0:
|
||
print(f" ERROR: {result.stdout[:200]}")
|
||
sys.exit(1)
|
||
|
||
print("All batches written successfully!")
|