| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- #!/usr/bin/env node
- /**
- * 江中猴菇饮 OTC · VOC 种子数据生成器
- *
- * 基于公开渠道观察到的用户讨论模式整理的代表性 VOC 样本库。
- * 明确标识 source='pattern-curated',Batch 3+ 渲染时会以"模式样本"标注。
- *
- * 输出:docs/jiangzhong-houguyin/raw/_seed.json + comments-flat.jsonl
- */
- const fs = require('fs');
- const path = require('path');
- const PATTERNS = require('./houguyin-seed-patterns.js');
- const ROOT = path.resolve(__dirname, '..', '..');
- const OUT_DIR = path.join(ROOT, 'docs', 'jiangzhong-houguyin', 'raw');
- const OUT_PATH = path.join(OUT_DIR, '_seed.json');
- const FLAT_PATH = path.join(OUT_DIR, 'comments-flat.jsonl');
- if (!fs.existsSync(OUT_DIR)) fs.mkdirSync(OUT_DIR, { recursive: true });
- // ================================================================
- // 生成器:将 pattern group 展开为完整 VOC 记录
- // ================================================================
- const IP_POOL = ['北京', '上海', '广东', '浙江', '江苏', '四川', '山东', '河南', '湖北', '湖南', '福建', '辽宁', '陕西', '河北', '安徽', '天津', '重庆'];
- const NICK_PREFIX = ['养胃派', '胃友', '小胃口', '温胃人', '猴友', '药店回忆', '江湖药师', '办公室牛马', '熬夜选手', '应酬达人', '老胃病', '胃镜新手', '断药挣扎者', '糖友', '送礼党', '职场妈妈', '差旅客', '实习生', '二胎妈妈', '产品经理'];
- function hash(s) {
- let h = 0; for (let i = 0; i < s.length; i++) { h = ((h << 5) - h + s.charCodeAt(i)) | 0; }
- return Math.abs(h);
- }
- function expandEntry(entry, group, idx) {
- const h = hash(entry.c + group.key + idx);
- const nick = `${NICK_PREFIX[h % NICK_PREFIX.length]}_${String((h >> 4) % 999).padStart(3, '0')}`;
- const ip = IP_POOL[(h >> 8) % IP_POOL.length];
- const likes = group.likesMin + (h % Math.max(1, group.likesMax - group.likesMin));
- const platforms = group.platforms || ['xhs'];
- const platform = platforms[(h >> 12) % platforms.length];
- return {
- id: `seed_${group.key}_${String(idx).padStart(3, '0')}`,
- platform,
- product: group.product,
- keyword: group.keyword || group.product,
- type: group.type || 'comment',
- nickname: nick,
- ip,
- content: entry.c,
- likes,
- rating: group.rating || null,
- hypothesis: group.hypotheses,
- tags: entry.tags || [],
- sentiment: group.sentiment,
- source: 'pattern-curated',
- basis: group.basis || '公开讨论模式归纳',
- };
- }
- function generate() {
- const items = [];
- for (const group of PATTERNS) {
- group.entries.forEach((e, i) => items.push(expandEntry(e, group, i)));
- }
- const meta = { collectedAt: new Date().toISOString().slice(0, 10), platforms: {}, products: {}, hypotheses: {}, stage: 'batch-2-seed', sourceNote: '所有条目 source=pattern-curated,基于公开讨论模式整理的代表性样本;Batch 3+ 渲染会明确标注' };
- for (const it of items) {
- meta.platforms[it.platform] = (meta.platforms[it.platform] || 0) + 1;
- meta.products[it.product] = (meta.products[it.product] || 0) + 1;
- for (const h of it.hypothesis) meta.hypotheses[h] = (meta.hypotheses[h] || 0) + 1;
- }
- return { meta, items };
- }
- function main() {
- console.log('╔═══════════════════════════════════════════════════════════╗');
- console.log('║ 猴菇饮 OTC · VOC 种子数据生成(公开讨论模式归纳) ║');
- console.log('╚═══════════════════════════════════════════════════════════╝');
- const data = generate();
- fs.writeFileSync(OUT_PATH, JSON.stringify(data, null, 2), 'utf8');
- fs.writeFileSync(FLAT_PATH, data.items.map((it) => JSON.stringify(it)).join('\n'), 'utf8');
- console.log(` ✅ 生成 ${data.items.length} 条 seed VOC`);
- console.log(` 平台分布:`, data.meta.platforms);
- console.log(` 假设覆盖:`, data.meta.hypotheses);
- console.log(` 产品维度: ${Object.keys(data.meta.products).length} 种`);
- console.log(` 输出: ${path.relative(ROOT, OUT_PATH)}`);
- }
- if (require.main === module) main();
- module.exports = { generate };
|