Files

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,
];
}
}
}
}