| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- #!/usr/bin/env node
- const fs = require('fs');
- const os = require('os');
- const path = require('path');
- const { runTihaoSourcing } = require('../mcp/src/tools/tihao-brief-sourcing-run');
- const { readFeedbackCsv } = require('./import-feedback-memory');
- const { readMemory, applyFeedbackRecordsToMemory } = require('../mcp/src/features/tihao-sourcing/preference-memory');
- async function main() {
- const out = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-feedback-roundtrip-'));
- const memoryPath = path.join(out, 'memory.json');
- const feedbackPath = path.join(out, 'feedback.csv');
- const blockedNames = [
- '618母婴好物清单',
- '精致生活小鹿',
- '办公室健康零食测评',
- '真实家居清洁实验室'
- ];
- fs.writeFileSync(feedbackPath, [
- 'brief编号,平台,博主名称,主页链接,人工复核标签,反馈原因,归因类型,影响范围,是否升级为团队规则,下一轮动作',
- 'flower-skincare,小红书,618母婴好物清单,https://www.xiaohongshu.com/user/profile/xhs-dha-003,跑偏,护肤 Brief 不应优先推荐母婴清单号,需求解析,客户品牌级,否,剔除账号',
- 'flower-skincare,小红书,精致生活小鹿,https://www.xiaohongshu.com/user/profile/xhs-beauty-002,调性不符,封面下沉且主页质感不符,主页证据,团队规则,是,剔除账号',
- 'flower-skincare,小红书,办公室健康零食测评,https://www.xiaohongshu.com/user/profile/xhs-food-001,主页质感不符,封面下沉且主页质感不符,主页证据,团队规则,是,剔除账号',
- 'flower-skincare,小红书,真实家居清洁实验室,https://www.xiaohongshu.com/user/profile/xhs-home-001,参考账号不像,封面下沉且主页质感不符,主页证据,团队规则,是,剔除账号',
- 'flower-skincare,小红书,下沉硬广一号,https://www.xiaohongshu.com/user/profile/xhs-low-001,主页质感不符,封面下沉且主页质感不符,主页证据,团队规则,是,剔除账号',
- 'flower-skincare,小红书,下沉硬广二号,https://www.xiaohongshu.com/user/profile/xhs-low-002,主页质感不符,封面下沉且主页质感不符,主页证据,团队规则,是,剔除账号'
- ].join('\n'), 'utf8');
- const memory = applyFeedbackRecordsToMemory(readMemory(memoryPath), readFeedbackCsv(feedbackPath));
- fs.writeFileSync(memoryPath, JSON.stringify(memory, null, 2), 'utf8');
- const result = await runTihaoSourcing({
- collectionMode: 'sample',
- briefText: [
- '客户名称:花漾肌研',
- '平台与人数:小红书 6 人,抖音 2 人',
- '粉丝量范围:2万-50万',
- '预算范围:3000-18000',
- '偏好真实体验、素人感、成分拆解、敏感肌修护,不要硬广。'
- ].join('\n'),
- memory: memoryPath,
- output: path.join(out, 'second-round')
- });
- assert(result.status === 'ok', 'second round sourcing should return ok');
- for (const name of blockedNames) {
- assert(memory.blockedCreators.includes(name), `${name} should be blocked in memory`);
- assert(!result.data.candidates.some(item => item.displayName === name), `${name} should not enter client-ready candidates`);
- }
- assert(memory.blockedStyles.some(item => item.includes('封面下沉且主页质感不符')), 'tone/homepage feedback should create blocked style memory');
- assert(memory.teamRuleSuggestions.length >= 1, 'three repeated team-scope feedback rows should create team rule suggestion');
- assert(memory.teamRuleSuggestions[0].count >= 3, 'team rule suggestion should require repeated evidence');
- assert(result.data.criteria.memory.feedbackSummary.total === 6, 'second round should carry feedback summary');
- console.log(`feedback roundtrip smoke ok: ${out}`);
- }
- function assert(condition, message) {
- if (!condition) throw new Error(message);
- }
- main().catch(error => {
- console.error(error && error.stack ? error.stack : String(error));
- process.exit(1);
- });
|