@rookiestar/eng-lang-tutor 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +22 -0
- package/.gitignore +32 -0
- package/CHANGELOG.md +37 -0
- package/CLAUDE.md +275 -0
- package/README.md +369 -0
- package/SKILL.md +613 -0
- package/bin/eng-lang-tutor.js +177 -0
- package/docs/OPENCLAW_DEPLOYMENT.md +241 -0
- package/examples/sample_keypoint_a1.json +112 -0
- package/examples/sample_keypoint_a2.json +124 -0
- package/examples/sample_keypoint_b1.json +135 -0
- package/examples/sample_keypoint_b2.json +137 -0
- package/examples/sample_keypoint_c1.json +134 -0
- package/examples/sample_keypoint_c2.json +141 -0
- package/examples/sample_quiz_a1.json +94 -0
- package/examples/sample_quiz_a2.json +94 -0
- package/examples/sample_quiz_b1.json +92 -0
- package/examples/sample_quiz_b2.json +94 -0
- package/examples/sample_quiz_c1.json +94 -0
- package/examples/sample_quiz_c2.json +104 -0
- package/package.json +41 -0
- package/references/resources.md +292 -0
- package/requirements.txt +16 -0
- package/scripts/__init__.py +28 -0
- package/scripts/audio/__init__.py +23 -0
- package/scripts/audio/composer.py +367 -0
- package/scripts/audio/converter.py +331 -0
- package/scripts/audio/feishu_voice.py +404 -0
- package/scripts/audio/tts/__init__.py +30 -0
- package/scripts/audio/tts/base.py +166 -0
- package/scripts/audio/tts/manager.py +306 -0
- package/scripts/audio/tts/providers/__init__.py +12 -0
- package/scripts/audio/tts/providers/edge.py +111 -0
- package/scripts/audio/tts/providers/xunfei.py +205 -0
- package/scripts/audio/utils.py +63 -0
- package/scripts/cli/__init__.py +7 -0
- package/scripts/cli/cli.py +229 -0
- package/scripts/cli/command_parser.py +336 -0
- package/scripts/core/__init__.py +30 -0
- package/scripts/core/constants.py +125 -0
- package/scripts/core/error_notebook.py +308 -0
- package/scripts/core/gamification.py +405 -0
- package/scripts/core/scorer.py +295 -0
- package/scripts/core/state_manager.py +814 -0
- package/scripts/eng-lang-tutor +16 -0
- package/scripts/scheduling/__init__.py +6 -0
- package/scripts/scheduling/cron_push.py +229 -0
- package/scripts/utils/__init__.py +12 -0
- package/scripts/utils/dedup.py +331 -0
- package/scripts/utils/helpers.py +82 -0
- package/templates/keypoint_schema.json +420 -0
- package/templates/prompt_templates.md +73 -0
- package/templates/prompts/display_guide.md +106 -0
- package/templates/prompts/initialization.md +350 -0
- package/templates/prompts/keypoint_generation.md +272 -0
- package/templates/prompts/output_rules.md +106 -0
- package/templates/prompts/quiz_generation.md +190 -0
- package/templates/prompts/responses.md +339 -0
- package/templates/prompts/shared_enums.md +252 -0
- package/templates/quiz_schema.json +214 -0
- package/templates/state_schema.json +277 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* eng-lang-tutor CLI
|
|
5
|
+
*
|
|
6
|
+
* Commands:
|
|
7
|
+
* install - Install the skill to ~/.openclaw/skills/eng-lang-tutor/
|
|
8
|
+
* uninstall - Remove the skill from ~/.openclaw/skills/eng-lang-tutor/
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const path = require('path');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const os = require('os');
|
|
14
|
+
|
|
15
|
+
const SKILL_NAME = 'eng-lang-tutor';
|
|
16
|
+
const SKILLS_DIR = path.join(os.homedir(), '.openclaw', 'skills');
|
|
17
|
+
const SKILL_TARGET = path.join(SKILLS_DIR, SKILL_NAME);
|
|
18
|
+
|
|
19
|
+
// Get the package root directory (where package.json is)
|
|
20
|
+
const PACKAGE_ROOT = path.resolve(__dirname, '..');
|
|
21
|
+
|
|
22
|
+
function getSkillSourceDir() {
|
|
23
|
+
return PACKAGE_ROOT;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function install() {
|
|
27
|
+
console.log(`Installing ${SKILL_NAME} skill...`);
|
|
28
|
+
|
|
29
|
+
const sourceDir = getSkillSourceDir();
|
|
30
|
+
|
|
31
|
+
// Check if source directory exists
|
|
32
|
+
if (!fs.existsSync(sourceDir)) {
|
|
33
|
+
console.error(`Error: Source directory not found: ${sourceDir}`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Create skills directory if it doesn't exist
|
|
38
|
+
if (!fs.existsSync(SKILLS_DIR)) {
|
|
39
|
+
fs.mkdirSync(SKILLS_DIR, { recursive: true });
|
|
40
|
+
console.log(`Created skills directory: ${SKILLS_DIR}`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Remove existing installation if present
|
|
44
|
+
if (fs.existsSync(SKILL_TARGET)) {
|
|
45
|
+
console.log(`Removing existing installation at ${SKILL_TARGET}...`);
|
|
46
|
+
fs.rmSync(SKILL_TARGET, { recursive: true, force: true });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Create target directory
|
|
50
|
+
fs.mkdirSync(SKILL_TARGET, { recursive: true });
|
|
51
|
+
|
|
52
|
+
// Files and directories to copy
|
|
53
|
+
const itemsToCopy = [
|
|
54
|
+
'scripts',
|
|
55
|
+
'templates',
|
|
56
|
+
'references',
|
|
57
|
+
'examples',
|
|
58
|
+
'docs',
|
|
59
|
+
'SKILL.md',
|
|
60
|
+
'CLAUDE.md',
|
|
61
|
+
'README.md',
|
|
62
|
+
'README_EN.md',
|
|
63
|
+
'requirements.txt'
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
// Copy each item
|
|
67
|
+
for (const item of itemsToCopy) {
|
|
68
|
+
const sourcePath = path.join(sourceDir, item);
|
|
69
|
+
const targetPath = path.join(SKILL_TARGET, item);
|
|
70
|
+
|
|
71
|
+
if (!fs.existsSync(sourcePath)) {
|
|
72
|
+
console.log(` Skipping ${item} (not found)`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
try {
|
|
77
|
+
if (fs.statSync(sourcePath).isDirectory()) {
|
|
78
|
+
copyDir(sourcePath, targetPath);
|
|
79
|
+
} else {
|
|
80
|
+
fs.copyFileSync(sourcePath, targetPath);
|
|
81
|
+
}
|
|
82
|
+
console.log(` Copied ${item}`);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
console.error(` Error copying ${item}: ${err.message}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log(`\n✓ ${SKILL_NAME} installed to ${SKILL_TARGET}`);
|
|
89
|
+
console.log('\nNext steps:');
|
|
90
|
+
console.log(' 1. Install Python dependencies:');
|
|
91
|
+
console.log(` pip install -r ${SKILL_TARGET}/requirements.txt`);
|
|
92
|
+
console.log(' 2. Restart your OpenClaw agent');
|
|
93
|
+
console.log(' 3. Configure the skill through the onboarding flow');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function uninstall() {
|
|
97
|
+
console.log(`Uninstalling ${SKILL_NAME} skill...`);
|
|
98
|
+
|
|
99
|
+
if (!fs.existsSync(SKILL_TARGET)) {
|
|
100
|
+
console.log(`${SKILL_NAME} is not installed.`);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
fs.rmSync(SKILL_TARGET, { recursive: true, force: true });
|
|
106
|
+
console.log(`✓ ${SKILL_NAME} removed from ${SKILL_TARGET}`);
|
|
107
|
+
console.log('\nNote: Your learning data is preserved at:');
|
|
108
|
+
console.log(' ~/.openclaw/state/eng-lang-tutor/');
|
|
109
|
+
console.log('\nTo completely remove all data, run:');
|
|
110
|
+
console.log(' rm -rf ~/.openclaw/state/eng-lang-tutor');
|
|
111
|
+
} catch (err) {
|
|
112
|
+
console.error(`Error uninstalling: ${err.message}`);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function copyDir(src, dest) {
|
|
118
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
119
|
+
|
|
120
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
121
|
+
|
|
122
|
+
for (const entry of entries) {
|
|
123
|
+
const srcPath = path.join(src, entry.name);
|
|
124
|
+
const destPath = path.join(dest, entry.name);
|
|
125
|
+
|
|
126
|
+
if (entry.isDirectory()) {
|
|
127
|
+
copyDir(srcPath, destPath);
|
|
128
|
+
} else {
|
|
129
|
+
fs.copyFileSync(srcPath, destPath);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function showHelp() {
|
|
135
|
+
console.log(`
|
|
136
|
+
eng-lang-tutor - English Language Tutor Skill for OpenClaw
|
|
137
|
+
|
|
138
|
+
Usage:
|
|
139
|
+
eng-lang-tutor <command>
|
|
140
|
+
|
|
141
|
+
Commands:
|
|
142
|
+
install Install the skill to ~/.openclaw/skills/eng-lang-tutor/
|
|
143
|
+
uninstall Remove the skill (preserves learning data)
|
|
144
|
+
help Show this help message
|
|
145
|
+
|
|
146
|
+
Environment Variables:
|
|
147
|
+
OPENCLAW_STATE_DIR Custom directory for learning data
|
|
148
|
+
(default: ~/.openclaw/state/eng-lang-tutor)
|
|
149
|
+
|
|
150
|
+
Examples:
|
|
151
|
+
eng-lang-tutor install
|
|
152
|
+
eng-lang-tutor uninstall
|
|
153
|
+
`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Main
|
|
157
|
+
const command = process.argv[2];
|
|
158
|
+
|
|
159
|
+
switch (command) {
|
|
160
|
+
case 'install':
|
|
161
|
+
install();
|
|
162
|
+
break;
|
|
163
|
+
case 'uninstall':
|
|
164
|
+
uninstall();
|
|
165
|
+
break;
|
|
166
|
+
case 'help':
|
|
167
|
+
case '--help':
|
|
168
|
+
case '-h':
|
|
169
|
+
showHelp();
|
|
170
|
+
break;
|
|
171
|
+
default:
|
|
172
|
+
if (command) {
|
|
173
|
+
console.error(`Unknown command: ${command}`);
|
|
174
|
+
}
|
|
175
|
+
showHelp();
|
|
176
|
+
process.exit(command ? 1 : 0);
|
|
177
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# OpenClaw 部署指南
|
|
2
|
+
|
|
3
|
+
本文档说明如何将 `eng-lang-tutor` skill 部署到 OpenClaw 服务器,并通过 Discord 等渠道使用。
|
|
4
|
+
|
|
5
|
+
## 1. 前置条件
|
|
6
|
+
|
|
7
|
+
- 一台已安装 OpenClaw 的服务器
|
|
8
|
+
- OpenClaw Gateway 正在运行
|
|
9
|
+
- 已配置好 Discord Bot(可选其他渠道)
|
|
10
|
+
|
|
11
|
+
## 2. 部署步骤
|
|
12
|
+
|
|
13
|
+
### 2.1 上传 Skill 到服务器
|
|
14
|
+
|
|
15
|
+
**方式 A:使用 SCP 上传**
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# 在本地机器上执行
|
|
19
|
+
scp -r /path/to/eng-lang-tutor user@your-server:~/.openclaw/skills/
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**方式 B:使用 Git Clone**
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# 在服务器上执行
|
|
26
|
+
cd ~/.openclaw/skills/
|
|
27
|
+
git clone https://github.com/rookiestar/eng-lang-tutor.git
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 2.2 确认目录结构
|
|
31
|
+
|
|
32
|
+
确保目录结构如下:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
~/.openclaw/skills/eng-lang-tutor/
|
|
36
|
+
├── SKILL.md # 核心技能文件(必需)
|
|
37
|
+
├── scripts/ # Python 脚本
|
|
38
|
+
│ ├── core/ # 核心模块
|
|
39
|
+
│ │ ├── state_manager.py
|
|
40
|
+
│ │ ├── scorer.py
|
|
41
|
+
│ │ ├── gamification.py
|
|
42
|
+
│ │ ├── constants.py
|
|
43
|
+
│ │ └── error_notebook.py
|
|
44
|
+
│ ├── cli/ # 命令行模块
|
|
45
|
+
│ ├── scheduling/ # 调度模块
|
|
46
|
+
│ ├── utils/ # 工具模块
|
|
47
|
+
│ └── audio/ # 音频模块
|
|
48
|
+
├── templates/ # JSON Schema + Prompt 模板
|
|
49
|
+
├── references/ # 参考资源
|
|
50
|
+
├── examples/ # 示例文件(按 CEFR 级别)
|
|
51
|
+
└── (数据存储在外部目录)
|
|
52
|
+
~/.openclaw/state/eng-lang-tutor/ # 运行时数据(自动创建)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 2.3 验证 Skill 加载
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# 查看已加载的 skills
|
|
59
|
+
openclaw skills list
|
|
60
|
+
|
|
61
|
+
# 查看特定 skill 详情
|
|
62
|
+
openclaw skills info eng-lang-tutor
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 3. 配置 Discord 渠道
|
|
66
|
+
|
|
67
|
+
### 3.1 创建 Discord Bot
|
|
68
|
+
|
|
69
|
+
1. 访问 [Discord Developer Portal](https://discord.com/developers/applications)
|
|
70
|
+
2. 创建新应用,命名为你的 Bot
|
|
71
|
+
3. 进入 Bot 页面,创建 Bot 并获取 Token
|
|
72
|
+
4. 启用 Message Content Intent
|
|
73
|
+
|
|
74
|
+
### 3.2 配置 OpenClaw
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# 设置 Discord Token
|
|
78
|
+
openclaw config set discord.token YOUR_BOT_TOKEN
|
|
79
|
+
|
|
80
|
+
# 设置服务器 ID(可选)
|
|
81
|
+
openclaw config set discord.guildId YOUR_SERVER_ID
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### 3.3 邀请 Bot 到服务器
|
|
85
|
+
|
|
86
|
+
1. 在 Discord Developer Portal 中,进入 OAuth2 > URL Generator
|
|
87
|
+
2. 选择 `bot` 和 `applications.commands` scope
|
|
88
|
+
3. 选择所需权限(Send Messages, Read Messages 等)
|
|
89
|
+
4. 复制生成的邀请链接并在浏览器中打开
|
|
90
|
+
5. 选择要添加 Bot 的服务器
|
|
91
|
+
|
|
92
|
+
### 3.4 完成配对
|
|
93
|
+
|
|
94
|
+
首次与 Bot 对话时,会收到配对码:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# 在服务器上执行配对
|
|
98
|
+
openclaw pairing approve discord YOUR_PAIRING_CODE
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 4. 使用 Skill
|
|
102
|
+
|
|
103
|
+
### 4.1 通过 Discord 使用
|
|
104
|
+
|
|
105
|
+
在 Discord 中与 Bot 对话,触发英语学习功能:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
# 触发今日知识点
|
|
109
|
+
今天有什么英语知识点?
|
|
110
|
+
|
|
111
|
+
# 触发 Quiz
|
|
112
|
+
给我出个 Quiz
|
|
113
|
+
|
|
114
|
+
# 查看学习进度
|
|
115
|
+
我的学习进度怎么样?
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 4.2 设置定时推送(cron)
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# 编辑 crontab
|
|
122
|
+
crontab -e
|
|
123
|
+
|
|
124
|
+
# 添加每日定时推送
|
|
125
|
+
# 早上 6:45 推送知识点
|
|
126
|
+
45 6 * * * openclaw system event --text "Use eng-lang-tutor skill. Push today's keypoint." --mode now
|
|
127
|
+
|
|
128
|
+
# 晚上 22:45 推送 Quiz
|
|
129
|
+
45 22 * * * openclaw system event --text "Use eng-lang-tutor skill. Push today's quiz invitation." --mode now
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 5. 进阶配置
|
|
133
|
+
|
|
134
|
+
### 5.1 配置用户偏好
|
|
135
|
+
|
|
136
|
+
在 Discord 中与 Bot 对话设置:
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
设置我的 CEFR 等级为 B2
|
|
140
|
+
我的导师风格设为严谨
|
|
141
|
+
调整主题配比,增加职场内容的比例
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 5.2 配置环境变量
|
|
145
|
+
|
|
146
|
+
在服务器上设置 API 密钥(如果使用外部 LLM):
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
# 编辑 OpenClaw 配置
|
|
150
|
+
openclaw config set model.provider anthropic
|
|
151
|
+
openclaw config set model.api_key YOUR_API_KEY
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### 5.3 数据持久化
|
|
155
|
+
|
|
156
|
+
数据存储在 `~/.openclaw/state/eng-lang-tutor/` 目录,确保有正确的写入权限:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
chmod -R 755 ~/.openclaw/state/eng-lang-tutor/
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
可通过环境变量 `OPENCLAW_STATE_DIR` 自定义数据目录。
|
|
163
|
+
|
|
164
|
+
## 6. 故障排查
|
|
165
|
+
|
|
166
|
+
### 6.1 Skill 未加载
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
# 检查 skill 目录
|
|
170
|
+
ls -la ~/.openclaw/skills/eng-lang-tutor/
|
|
171
|
+
|
|
172
|
+
# 检查 SKILL.md 是否存在
|
|
173
|
+
cat ~/.openclaw/skills/eng-lang-tutor/SKILL.md
|
|
174
|
+
|
|
175
|
+
# 重启 Gateway
|
|
176
|
+
openclaw gateway restart
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### 6.2 Discord 无响应
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
# 检查 Gateway 日志
|
|
183
|
+
openclaw logs
|
|
184
|
+
|
|
185
|
+
# 验证 Discord Token
|
|
186
|
+
openclaw config get discord.token
|
|
187
|
+
|
|
188
|
+
# 检查 Bot 状态
|
|
189
|
+
openclaw doctor
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 6.3 Python 脚本错误
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# 检查 Python 环境
|
|
196
|
+
python3 --version
|
|
197
|
+
|
|
198
|
+
# 安装依赖(如有需要)
|
|
199
|
+
pip3 install -r ~/.openclaw/skills/eng-lang-tutor/requirements.txt
|
|
200
|
+
|
|
201
|
+
# 手动测试脚本
|
|
202
|
+
cd ~/.openclaw/skills/eng-lang-tutor/
|
|
203
|
+
python3 -m scripts.cli.cli stats
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## 7. 架构图
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
┌─────────────────────────────────────────────────────────┐
|
|
210
|
+
│ Discord │
|
|
211
|
+
│ (用户交互) │
|
|
212
|
+
└─────────────────────────┬───────────────────────────────┘
|
|
213
|
+
│
|
|
214
|
+
▼
|
|
215
|
+
┌─────────────────────────────────────────────────────────┐
|
|
216
|
+
│ OpenClaw Gateway │
|
|
217
|
+
│ (消息路由 + 会话管理) │
|
|
218
|
+
└─────────────────────────┬───────────────────────────────┘
|
|
219
|
+
│
|
|
220
|
+
▼
|
|
221
|
+
┌─────────────────────────────────────────────────────────┐
|
|
222
|
+
│ eng-lang-tutor Skill │
|
|
223
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
224
|
+
│ │ SKILL.md │ │ scripts/ │ │ ~/.openclaw │ │
|
|
225
|
+
│ │ (技能描述) │ │ (Python代码) │ │ (状态存储) │ │
|
|
226
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
227
|
+
└─────────────────────────────────────────────────────────┘
|
|
228
|
+
│
|
|
229
|
+
▼
|
|
230
|
+
┌─────────────────────────────────────────────────────────┐
|
|
231
|
+
│ LLM Provider │
|
|
232
|
+
│ (Claude/GPT/Qwen 等) │
|
|
233
|
+
└─────────────────────────────────────────────────────────┘
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## 8. 参考链接
|
|
237
|
+
|
|
238
|
+
- [OpenClaw 官方文档](https://docs.openclaw.ai)
|
|
239
|
+
- [OpenClaw GitHub](https://github.com/openclaw/openclaw)
|
|
240
|
+
- [Discord 开发者门户](https://discord.com/developers/applications)
|
|
241
|
+
- [OpenClaw Skills 开发指南](https://docs.openclaw.ai/skills)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta": {
|
|
3
|
+
"prompt_version": "keypoint_gen_v2.1"
|
|
4
|
+
},
|
|
5
|
+
"date": "2026-02-25",
|
|
6
|
+
"topic_fingerprint": "daily_life_thank_you",
|
|
7
|
+
"category": "oral",
|
|
8
|
+
"topic": "daily_life",
|
|
9
|
+
"scene": {
|
|
10
|
+
"context": "You are at a shop or restaurant. Someone helps you or gives you something. This is the most basic polite expression in English.",
|
|
11
|
+
"formality": "neutral"
|
|
12
|
+
},
|
|
13
|
+
"expressions": [
|
|
14
|
+
{
|
|
15
|
+
"phrase": "Thank you",
|
|
16
|
+
"pronunciation_tip": "Sounds like 'thank-you', say it as one word. Natural speed: 'than-kyou'",
|
|
17
|
+
"usage_note": "Use this when someone helps you or gives you something. It works in ALL situations."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"phrase": "Thanks",
|
|
21
|
+
"pronunciation_tip": "Short and casual: 'thanks'",
|
|
22
|
+
"usage_note": "More casual than 'Thank you'. Use with friends or in informal situations."
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"alternatives": [
|
|
26
|
+
"Thanks a lot",
|
|
27
|
+
"Thank you very much"
|
|
28
|
+
],
|
|
29
|
+
"chinglish_trap": {
|
|
30
|
+
"wrong": "Thank you very many",
|
|
31
|
+
"correct": "Thank you very much",
|
|
32
|
+
"explanation": "'Many' is for things you can count (many apples). 'Much' is for amount or degree (very much). This is a common mistake from direct Chinese translation."
|
|
33
|
+
},
|
|
34
|
+
"examples": [
|
|
35
|
+
{
|
|
36
|
+
"situation": "At a coffee shop",
|
|
37
|
+
"dialogue": [
|
|
38
|
+
"A: Here's your coffee.",
|
|
39
|
+
"B: Thank you!"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"situation": "Someone holds the door",
|
|
44
|
+
"dialogue": [
|
|
45
|
+
"A: (holds door open)",
|
|
46
|
+
"B: Thanks!"
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
],
|
|
50
|
+
"references": {
|
|
51
|
+
"dictionary": {
|
|
52
|
+
"source": "merriam-webster",
|
|
53
|
+
"url": "https://www.merriam-webster.com/dictionary/thank%20you",
|
|
54
|
+
"note": "Definition and usage examples"
|
|
55
|
+
},
|
|
56
|
+
"usage_context": {
|
|
57
|
+
"source": "youglish",
|
|
58
|
+
"url": "https://youglish.com/pronounce/thank%20you/english/us",
|
|
59
|
+
"note": "Hear it in real YouTube videos"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"display": {
|
|
63
|
+
"title": "🏢 今日知识点 | Today's Knowledge Point",
|
|
64
|
+
"topic_tag": "🏷️ 主题: 日常生活 | Daily Life",
|
|
65
|
+
"formality_tag": "📊 正式度: 中性 | Neutral",
|
|
66
|
+
"scene_intro": "🎬 场景 | Scene",
|
|
67
|
+
"scene_text": "At a shop or restaurant - basic polite expression",
|
|
68
|
+
"expressions_title": "💬 核心表达 | Key Expressions",
|
|
69
|
+
"expressions_formatted": [
|
|
70
|
+
{
|
|
71
|
+
"emoji": "✨",
|
|
72
|
+
"phrase": "**Thank you**",
|
|
73
|
+
"phrase_plain": "Thank you",
|
|
74
|
+
"pronunciation": "🔊 'than-kyou' - say as one word",
|
|
75
|
+
"usage": "💡 Use when someone helps you. Works in ALL situations."
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"emoji": "✨",
|
|
79
|
+
"phrase": "**Thanks**",
|
|
80
|
+
"phrase_plain": "Thanks",
|
|
81
|
+
"pronunciation": "🔊 Short and casual",
|
|
82
|
+
"usage": "💡 More casual. Use with friends."
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"alternatives_title": "🔄 其他说法 | Alternatives",
|
|
86
|
+
"alternatives_formatted": "• **Thanks a lot**\n• **Thank you very much**",
|
|
87
|
+
"chinglish_title": "⚠️ Chinglish 陷阱 | Chinglish Trap",
|
|
88
|
+
"chinglish_formatted": "❌ Wrong: \"Thank you very **many**\"\n✅ Correct: **Thank you very much!**\n\n📝 'Many' = 可数 (many apples). 'Much' = 程度 (very much).",
|
|
89
|
+
"examples_title": "🗣️ 对话示例 | Example Dialogues",
|
|
90
|
+
"examples_formatted": [
|
|
91
|
+
{
|
|
92
|
+
"situation_emoji": "☕",
|
|
93
|
+
"situation": "At a coffee shop",
|
|
94
|
+
"dialogue": "💬 A: Here's your coffee.\n💬 B: **Thank you!**",
|
|
95
|
+
"key_phrase_highlight": "**Thank you**"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"situation_emoji": "🚪",
|
|
99
|
+
"situation": "Someone holds the door",
|
|
100
|
+
"dialogue": "💬 A: (holds door)\n💬 B: **Thanks!**",
|
|
101
|
+
"key_phrase_highlight": "**Thanks**"
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
"references_title": "📖 权威参考 | References",
|
|
105
|
+
"references_formatted": "📚 [Merriam-Webster](https://www.merriam-webster.com/dictionary/thank%20you) - Definition\n🎬 [YouGlish](https://youglish.com/pronounce/thank%20you/english/us) - Real usage",
|
|
106
|
+
"footer": "───────────────────\n📅 2026-02-25 | 📝 Take the quiz to earn XP!"
|
|
107
|
+
},
|
|
108
|
+
"audio": {
|
|
109
|
+
"enabled": true
|
|
110
|
+
},
|
|
111
|
+
"generated": true
|
|
112
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_meta": {
|
|
3
|
+
"prompt_version": "keypoint_gen_v2.1"
|
|
4
|
+
},
|
|
5
|
+
"date": "2026-02-25",
|
|
6
|
+
"topic_fingerprint": "social_nice_to_meet_you",
|
|
7
|
+
"category": "oral",
|
|
8
|
+
"topic": "social",
|
|
9
|
+
"scene": {
|
|
10
|
+
"context": "You are meeting someone for the first time. This is the standard polite expression when introduced to a new person.",
|
|
11
|
+
"formality": "neutral"
|
|
12
|
+
},
|
|
13
|
+
"expressions": [
|
|
14
|
+
{
|
|
15
|
+
"phrase": "Nice to meet you",
|
|
16
|
+
"pronunciation_tip": "Natural: 'nice-tuh-meet-chu'. The 'to' becomes 'tuh' and 'you' becomes 'chu'.",
|
|
17
|
+
"usage_note": "Use ONLY when meeting someone for the FIRST time. This is the most common introduction phrase."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"phrase": "Pleasure to meet you",
|
|
21
|
+
"pronunciation_tip": "More formal: 'pleh-zher-tuh-meet-chu'",
|
|
22
|
+
"usage_note": "Slightly more formal than 'Nice to meet you'. Good for business settings."
|
|
23
|
+
}
|
|
24
|
+
],
|
|
25
|
+
"alternatives": [
|
|
26
|
+
"Good to meet you",
|
|
27
|
+
"It's a pleasure",
|
|
28
|
+
"Glad to meet you"
|
|
29
|
+
],
|
|
30
|
+
"chinglish_trap": {
|
|
31
|
+
"wrong": "Nice to see you (when first meeting)",
|
|
32
|
+
"correct": "Nice to meet you",
|
|
33
|
+
"explanation": "'See you' is for people you already know or have met before. 'Meet you' is ONLY for first introductions. Chinese speakers often mix these up."
|
|
34
|
+
},
|
|
35
|
+
"examples": [
|
|
36
|
+
{
|
|
37
|
+
"situation": "At a party introduction",
|
|
38
|
+
"dialogue": [
|
|
39
|
+
"A: Sarah, this is Tom. Tom, this is Sarah.",
|
|
40
|
+
"B: Nice to meet you, Sarah!",
|
|
41
|
+
"C: Nice to meet you too, Tom!"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"situation": "First day at work",
|
|
46
|
+
"dialogue": [
|
|
47
|
+
"A: Welcome to the team! I'm the manager, Lisa.",
|
|
48
|
+
"B: Pleasure to meet you, Lisa. I'm excited to be here."
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"extended_learning": {
|
|
53
|
+
"related_phrases": [
|
|
54
|
+
"See you later - for someone you'll see again soon",
|
|
55
|
+
"See you soon - promise to meet again",
|
|
56
|
+
"It was nice meeting you - when saying goodbye after first meeting"
|
|
57
|
+
],
|
|
58
|
+
"cultural_note": "In American culture, it's polite to smile and make eye contact when saying 'Nice to meet you'. A firm handshake is common in business settings."
|
|
59
|
+
},
|
|
60
|
+
"references": {
|
|
61
|
+
"dictionary": {
|
|
62
|
+
"source": "merriam-webster",
|
|
63
|
+
"url": "https://www.merriam-webster.com/dictionary/meet",
|
|
64
|
+
"note": "Definition of 'meet' vs 'see'"
|
|
65
|
+
},
|
|
66
|
+
"usage_context": {
|
|
67
|
+
"source": "youglish",
|
|
68
|
+
"url": "https://youglish.com/pronounce/nice%20to%20meet%20you/english/us",
|
|
69
|
+
"note": "Hear it in real introductions"
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"display": {
|
|
73
|
+
"title": "🏢 今日知识点 | Today's Knowledge Point",
|
|
74
|
+
"topic_tag": "🏷️ 主题: 社交 | Social",
|
|
75
|
+
"formality_tag": "📊 正式度: 中性 | Neutral",
|
|
76
|
+
"scene_intro": "🎬 场景 | Scene",
|
|
77
|
+
"scene_text": "Meeting someone for the first time - standard introduction",
|
|
78
|
+
"expressions_title": "💬 核心表达 | Key Expressions",
|
|
79
|
+
"expressions_formatted": [
|
|
80
|
+
{
|
|
81
|
+
"emoji": "✨",
|
|
82
|
+
"phrase": "**Nice to meet you**",
|
|
83
|
+
"phrase_plain": "Nice to meet you",
|
|
84
|
+
"pronunciation": "🔊 'nice-tuh-meet-chu' - natural flow",
|
|
85
|
+
"usage": "💡 ONLY for first-time introductions!"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"emoji": "✨",
|
|
89
|
+
"phrase": "**Pleasure to meet you**",
|
|
90
|
+
"phrase_plain": "Pleasure to meet you",
|
|
91
|
+
"pronunciation": "🔊 'pleh-zher-tuh-meet-chu' - more formal",
|
|
92
|
+
"usage": "💡 Slightly more formal, good for business."
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
"alternatives_title": "🔄 其他说法 | Alternatives",
|
|
96
|
+
"alternatives_formatted": "• **Good to meet you**\n• **It's a pleasure**\n• **Glad to meet you**",
|
|
97
|
+
"chinglish_title": "⚠️ Chinglish 陷阱 | Chinglish Trap",
|
|
98
|
+
"chinglish_formatted": "❌ Wrong: \"Nice to **see** you\" (first meeting)\n✅ Correct: **Nice to meet you!**\n\n📝 'See' = already know. 'Meet' = first time only!",
|
|
99
|
+
"examples_title": "🗣️ 对话示例 | Example Dialogues",
|
|
100
|
+
"examples_formatted": [
|
|
101
|
+
{
|
|
102
|
+
"situation_emoji": "🎉",
|
|
103
|
+
"situation": "At a party introduction",
|
|
104
|
+
"dialogue": "💬 A: Sarah, this is Tom.\n💬 B: **Nice to meet you**, Sarah!\n💬 C: **Nice to meet you too**, Tom!",
|
|
105
|
+
"key_phrase_highlight": "**Nice to meet you**"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"situation_emoji": "💼",
|
|
109
|
+
"situation": "First day at work",
|
|
110
|
+
"dialogue": "💬 A: Welcome! I'm Lisa, the manager.\n💬 B: **Pleasure to meet you**, Lisa.",
|
|
111
|
+
"key_phrase_highlight": "**Pleasure to meet you**"
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
"extended_title": "📚 延伸学习 | Extended Learning",
|
|
115
|
+
"extended_formatted": "🔗 Related: **See you later** | **See you soon** | **It was nice meeting you**\n\n🌎 Tip: Smile + eye contact when saying 'Nice to meet you'!",
|
|
116
|
+
"references_title": "📖 权威参考 | References",
|
|
117
|
+
"references_formatted": "📚 [Merriam-Webster](https://www.merriam-webster.com/dictionary/meet) - Meet vs See\n🎬 [YouGlish](https://youglish.com/pronounce/nice%20to%20meet%20you/english/us) - Real usage",
|
|
118
|
+
"footer": "───────────────────\n📅 2026-02-25 | 📝 Take the quiz to earn XP!"
|
|
119
|
+
},
|
|
120
|
+
"audio": {
|
|
121
|
+
"enabled": true
|
|
122
|
+
},
|
|
123
|
+
"generated": true
|
|
124
|
+
}
|