106 lines
3.3 KiB
PHP
106 lines
3.3 KiB
PHP
<?php
|
|
|
|
namespace app\common\command;
|
|
|
|
use app\common\service\ai\KbService;
|
|
use app\common\service\ai\KbSyncService;
|
|
use think\console\Command;
|
|
use think\console\Input;
|
|
use think\console\Output;
|
|
use think\console\input\Option;
|
|
use think\facade\Db;
|
|
|
|
class KbRebuild extends Command
|
|
{
|
|
protected function configure()
|
|
{
|
|
$this->setName('kb:rebuild')
|
|
->setDescription('重建AI知识库文档')
|
|
->addOption('domain', null, Option::VALUE_OPTIONAL, 'article|post|lottery|match|all', 'all');
|
|
}
|
|
|
|
protected function execute(Input $input, Output $output)
|
|
{
|
|
$domain = (string) $input->getOption('domain');
|
|
$targets = $domain === 'all' ? ['article', 'post', 'lottery', 'match'] : [$domain];
|
|
$summary = ['success' => 0, 'failed' => 0];
|
|
|
|
foreach ($targets as $target) {
|
|
foreach ($this->yieldRows($target) as $row) {
|
|
$result = KbService::upsertDocument($row['domain'], $row['subtype'], (int) $row['source_id']);
|
|
if (!empty($result['success'])) {
|
|
$summary['success']++;
|
|
} else {
|
|
$summary['failed']++;
|
|
$output->writeln(sprintf(
|
|
'[failed] %s/%s/%d %s',
|
|
$row['domain'],
|
|
$row['subtype'],
|
|
$row['source_id'],
|
|
$result['error'] ?? 'unknown'
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (in_array('article', $targets, true)) {
|
|
KbSyncService::markArticleBackfillJobs();
|
|
}
|
|
if (in_array('match', $targets, true)) {
|
|
KbSyncService::markMatchBackfillJobs();
|
|
}
|
|
if (in_array('lottery', $targets, true)) {
|
|
KbSyncService::markLotteryBackfillJobs();
|
|
}
|
|
$output->writeln(sprintf('[kb:rebuild] success=%d failed=%d', $summary['success'], $summary['failed']));
|
|
return 0;
|
|
}
|
|
|
|
private function yieldRows(string $domain): \Generator
|
|
{
|
|
if ($domain === 'article') {
|
|
yield from $this->yieldTableRows('article', 'article', 'article');
|
|
return;
|
|
}
|
|
if ($domain === 'post') {
|
|
yield from $this->yieldTableRows('community_post', 'post', 'post');
|
|
return;
|
|
}
|
|
if ($domain === 'lottery') {
|
|
yield from $this->yieldTableRows('lottery_draw_result', 'lottery', 'draw_result');
|
|
yield from $this->yieldTableRows('lottery_ai_analysis', 'lottery', 'ai_history');
|
|
return;
|
|
}
|
|
if ($domain === 'match') {
|
|
yield from $this->yieldTableRows('match', 'match', 'event');
|
|
}
|
|
}
|
|
|
|
private function yieldTableRows(string $table, string $domain, string $subtype): \Generator
|
|
{
|
|
$lastId = 0;
|
|
$chunkSize = 5000;
|
|
|
|
while (true) {
|
|
$ids = Db::name($table)
|
|
->where('id', '>', $lastId)
|
|
->order('id', 'asc')
|
|
->limit($chunkSize)
|
|
->column('id');
|
|
|
|
if (empty($ids)) {
|
|
break;
|
|
}
|
|
|
|
foreach ($ids as $id) {
|
|
$lastId = (int) $id;
|
|
yield [
|
|
'domain' => $domain,
|
|
'subtype' => $subtype,
|
|
'source_id' => $lastId,
|
|
];
|
|
}
|
|
}
|
|
}
|
|
}
|