| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- #!/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 { rankCreators } = require('../mcp/src/features/tihao-sourcing/ranker');
- async function main() {
- const output = fs.mkdtempSync(path.join(os.tmpdir(), 'tihao-reference-rules-'));
- const result = await runTihaoSourcing({
- collectionMode: 'sample',
- briefText: [
- '客户名称:花漾肌研',
- '产品:敏感肌屏障修护精华',
- '平台:小红书',
- '参考账号:一个是专业成分科普,一个是轻娱乐剧情种草。',
- '关键词:敏感肌、屏障、修护、成分党、真实体验',
- '偏好真实体验、素人感、成分拆解,不要硬广。'
- ].join('\n'),
- referenceStyleFingerprints: [
- {
- referenceId: 'ref-professional-science',
- url: 'https://www.xiaohongshu.com/explore/ref-professional-science',
- platform: 'xiaohongshu',
- contentType: 'image_text',
- accountName: '专业成分科普号',
- personaType: '专业成分党',
- contentStructure: '成分解释-功效边界-使用建议',
- tone: '理性科普、低情绪',
- title: '敏感肌屏障修护怎么选'
- },
- {
- referenceId: 'ref-light-entertainment',
- url: 'https://www.xiaohongshu.com/explore/ref-light-entertainment',
- platform: 'xiaohongshu',
- contentType: 'video',
- accountName: '轻娱乐剧情种草号',
- personaType: '剧情生活方式',
- contentStructure: '剧情冲突-夸张反应-种草转折',
- tone: '轻娱乐、情绪化、剧情感',
- title: '办公室女孩的护肤翻车剧情',
- asrText: '用剧情方式展示护肤翻车和修护体验',
- frameUrls: ['https://cdn.example.test/reference-frame.jpg']
- }
- ],
- output
- });
- assert(result.status === 'ok', 'reference rules sample should run ok');
- const usability = result.data.criteria.referenceUsability || {};
- assert(usability.status === 'reference_conflict', 'conflicting reference fingerprints should be marked as reference_conflict');
- assert(usability.conflict === true, 'reference usability should mark conflict=true');
- assert(String(usability.note || '').includes('不能强行合并'), 'reference conflict note should prevent forced unified standard');
- const reportPath = path.join(output, 'tihao-sourcing-report.md');
- const report = fs.readFileSync(reportPath, 'utf8');
- assert(report.includes('reference_conflict'), 'report should expose reference conflict status');
- assert(report.includes('不能强行合并为单一调性标准'), 'report should explain that conflicting references cannot be merged');
- const strong = (result.data.candidates || []).filter(item => item.recommendStatus === '强推荐');
- assert(strong.length >= 1, 'sample should still produce strong candidates');
- assert(strong.every(item => (item.briefHitConditions || []).length >= 2), 'strong candidates should have at least two brief hit conditions');
- assert(strong.every(item => ((item.referenceStyleHitPoints || []).length + (item.homepageEvidenceHitPoints || []).length) >= 1), 'strong candidates should have reference style or homepage evidence');
- assert(strong.every(item => !(item.referenceStyleHitPoints || []).some(point => /待补|需补/.test(String(point)))), 'strong reference style hit points should not contain placeholder evidence');
- assert(strong.every(item => String(item.recommendReason || '').includes('参考/风格命中')), 'strong candidate reasons should explain reference/style evidence');
- assert(strong.every(item => String(item.recommendReason || '').includes('主页证据命中')), 'strong candidate reasons should explain homepage evidence');
- const weakReferenceOnly = rankCreators([{
- platform: 'xiaohongshu',
- platformUserId: 'weak-reference-placeholder',
- displayName: '泛生活方式弱参考号',
- profileUrl: 'https://www.xiaohongshu.com/user/profile/weak-reference-placeholder',
- fansCount: 90000,
- minPrice: 7000,
- contentTags: ['护肤', '女性', '生活方式'],
- personaTags: ['好物分享'],
- recentEvidence: ['近期内容泛生活方式,没有命中参考账号调性']
- }], {
- brand: '花漾肌研',
- category: '护肤',
- platforms: ['xiaohongshu'],
- keywords: ['护肤', '女性'],
- stylePreferences: [],
- referenceSignals: ['专业成分党', '低情绪理性科普'],
- referenceLinks: [{ url: 'https://www.xiaohongshu.com/user/profile/ref-account', platform: 'xiaohongshu' }],
- fanRange: { min: 10000, max: 500000 },
- budgetRange: { min: 3000, max: 10000 }
- })[0];
- assert((weakReferenceOnly.referenceFallbackHitPoints || []).some(point => /需补/.test(String(point))), 'weak reference candidate should keep fallback reference hint');
- assert((weakReferenceOnly.referenceStyleHitPoints || []).length === 0, 'fallback reference hints should not enter concrete reference style hit points');
- assert(weakReferenceOnly.referenceEvidenceConcrete === false, 'weak reference candidate should mark reference evidence as non-concrete');
- assert(weakReferenceOnly.recommendStatus !== '强推荐', 'weak placeholder reference evidence should not be enough for strong recommendation');
- console.log(JSON.stringify({
- ok: true,
- output,
- referenceStatus: usability.status,
- strong: strong.length
- }, null, 2));
- }
- 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);
- });
|