Files
zyt/server/app/adminapi/service/AiContextCompactionCache.php
T
2026-10-22 16:42:26 +08:00

59 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace app\adminapi\service;
use app\common\service\NihaixiaClinicalSkill;
use app\common\service\TcmAncientBooksReference;
use think\facade\Cache;
/** Short-lived evidence only. The caller must re-authorize and aggregate before lookup. */
final class AiContextCompactionCache
{
public static function remember(string $scope, string $profile, string $source, callable $produce): array
{
$config = config('prescription_ai') ?: [];
$ttl = max(0, min(600, (int) ($config['context_compaction_cache_ttl'] ?? 300)));
$key = self::key($scope, $profile, $source, $config);
if ($scope !== '' && $ttl > 0) {
try {
$cached = Cache::get($key);
if (self::valid($cached, strlen($source))) {
$cached['cache_hit'] = true;
return $cached;
}
} catch (\Throwable $ignored) {
// An unavailable cache must not prevent a complete fresh analysis.
}
}
$result = $produce();
if ($scope !== '' && $ttl > 0 && self::valid($result, strlen($source))) {
try {
Cache::set($key, $result, $ttl);
} catch (\Throwable $ignored) {
}
}
return $result + ['cache_hit' => false];
}
private static function key(string $scope, string $profile, string $source, array $config): string
{
return 'ai-context-evidence:' . hash('sha256', serialize([
'evidence-extraction-v2', $scope, $profile, hash('sha256', $source),
$config['base_url'] ?? '', $config['models'][$profile] ?? [],
NihaixiaClinicalSkill::VERSION, TcmAncientBooksReference::COMMIT,
]));
}
private static function valid($value, int $sourceBytes): bool
{
return is_array($value) && is_string($value['text'] ?? null)
&& trim($value['text']) !== '' && strlen($value['text']) <= 240000
&& ($value['source_bytes'] ?? null) === $sourceBytes
&& is_int($value['chunk_count'] ?? null) && $value['chunk_count'] > 0
&& is_int($value['reduction_rounds'] ?? null) && $value['reduction_rounds'] >= 0
&& ($value['compacted'] ?? null) === true;
}
}