feat: [esign] HWR API 호출 시 AI 토큰 사용량 자동 기록 (google-vision $0.0015/건)

This commit is contained in:
김보곤
2026-03-23 08:55:20 +09:00
parent 0cfd84121f
commit 1c12eaa8ff

View File

@@ -4,12 +4,15 @@
use App\Models\ESign\EsignHandwritingVerification;
use App\Models\ESign\EsignVerificationTemplate;
use App\Models\System\AiPricingConfig;
use App\Models\System\AiTokenUsage;
use App\Services\ESign\Adapters\GoogleVisionAdapter;
use App\Services\ESign\Adapters\NaverClovaAdapter;
use App\Services\ESign\Adapters\TesseractAdapter;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class HandwritingVerificationService
{
@@ -229,6 +232,8 @@ private function recognizeText(string $base64Image): array
$result = $adapter->recognize($base64Image);
if ($result['text'] !== '') {
$this->recordTokenUsage($engineName);
return [
'text' => $result['text'],
'confidence' => $result['confidence'],
@@ -420,6 +425,49 @@ public function demo(string $base64Image, string $expectedText): array
];
}
/**
* HWR API 호출을 AI 토큰 사용량에 기록한다.
*
* Google Vision: $1.50 / 1,000건 = $0.0015/건
* Naver Clova: 월 300건 무료, 초과 시 $0.003/건 (추정)
* Tesseract: 무료 (로컬)
*/
private function recordTokenUsage(string $engineName): void
{
$costMap = [
'google_vision' => 0.0015,
'clova' => 0.003,
'tesseract' => 0.0,
];
$modelMap = [
'google_vision' => 'google-vision',
'clova' => 'naver-clova',
'tesseract' => 'tesseract',
];
$costUsd = $costMap[$engineName] ?? 0.0;
$model = $modelMap[$engineName] ?? $engineName;
$exchangeRate = AiPricingConfig::getExchangeRate();
try {
AiTokenUsage::create([
'tenant_id' => session('selected_tenant_id', 1),
'model' => $model,
'menu_name' => '전자서명 고도화',
'prompt_tokens' => 1,
'completion_tokens' => 0,
'total_tokens' => 1,
'cost_usd' => $costUsd,
'cost_krw' => round($costUsd * $exchangeRate, 2),
'request_id' => (string) Str::uuid(),
'created_by' => auth()->id(),
]);
} catch (\Throwable $e) {
Log::warning('AI 토큰 사용량 기록 실패', ['error' => $e->getMessage()]);
}
}
/**
* 템플릿 ID로 단계 목록을 해석한다. 미지정 시 기본 단계를 반환한다.
*