|
|
@@ -8,6 +8,7 @@ use App\Facade\Site;
|
|
|
use App\Libs\ActShowContent;
|
|
|
use App\Libs\JsonSafeRepair;
|
|
|
use App\Libs\Utils;
|
|
|
+use App\Libs\ScriptAnchor;
|
|
|
use GuzzleHttp\Client;
|
|
|
use DateTime;
|
|
|
use DateTimeZone;
|
|
|
@@ -326,12 +327,15 @@ class DeepSeekService
|
|
|
// 根据模型类型选择流式实现
|
|
|
$streamGenerator = $this->dispatchStreamByModel($post_data);
|
|
|
|
|
|
+ // 计费锚点与业务来源(前端有传才记录)
|
|
|
+ $chargeContext = ScriptAnchor::chargeContextFromRequest($data);
|
|
|
+
|
|
|
if ($chargePoints > 0) {
|
|
|
- return $this->wrapGenerateTextCharge($streamGenerator, $uid, $model, $chargePoints, $chargeModality);
|
|
|
+ return $this->wrapGenerateTextCharge($streamGenerator, $uid, $model, $chargePoints, $chargeModality, $chargeContext);
|
|
|
}
|
|
|
|
|
|
// 免费场景(0 积分):流式生成成功后仅记录 token 使用明细
|
|
|
- return $this->wrapGenerateTextTokenRecord($streamGenerator, $uid, $model);
|
|
|
+ return $this->wrapGenerateTextTokenRecord($streamGenerator, $uid, $model, $chargeContext);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -342,15 +346,15 @@ class DeepSeekService
|
|
|
* @param string $model
|
|
|
* @return \Generator
|
|
|
*/
|
|
|
- private function wrapGenerateTextTokenRecord(\Generator $generator, int $uid, string $model, string $source = 'generateText'): \Generator
|
|
|
+ private function wrapGenerateTextTokenRecord(\Generator $generator, int $uid, string $model, array $chargeContext = []): \Generator
|
|
|
{
|
|
|
$recorded = false;
|
|
|
foreach ($generator as $chunk) {
|
|
|
if (!$recorded && isset($chunk['type']) && $chunk['type'] === 'done') {
|
|
|
- $this->recordTextTokenOnly($uid, $this->pointsService->getTokensFromUsage(getProp($chunk, 'usage', [])), [
|
|
|
+ $this->recordTextTokenOnly($uid, $this->pointsService->getTokensFromUsage(getProp($chunk, 'usage', [])), array_merge([
|
|
|
'model' => $model,
|
|
|
- 'source' => $source,
|
|
|
- ], $model);
|
|
|
+ 'source' => 'generateText',
|
|
|
+ ], $chargeContext), $model);
|
|
|
$recorded = true;
|
|
|
}
|
|
|
yield $chunk;
|
|
|
@@ -367,14 +371,14 @@ class DeepSeekService
|
|
|
* @param string $modality
|
|
|
* @return \Generator
|
|
|
*/
|
|
|
- private function wrapGenerateTextCharge(\Generator $generator, int $uid, string $model, int $points, string $modality): \Generator
|
|
|
+ private function wrapGenerateTextCharge(\Generator $generator, int $uid, string $model, int $points, string $modality, array $chargeContext = []): \Generator
|
|
|
{
|
|
|
$charged = false;
|
|
|
foreach ($generator as $chunk) {
|
|
|
if (!$charged && isset($chunk['type']) && $chunk['type'] === 'done') {
|
|
|
$fullContent = (string)getProp($chunk, 'full_content', getProp($chunk, 'answer', ''));
|
|
|
if ($fullContent !== '') {
|
|
|
- $this->chargeMultimodal($uid, $model, $points, $modality, getProp($chunk, 'usage', []));
|
|
|
+ $this->chargeMultimodal($uid, $model, $points, $modality, getProp($chunk, 'usage', []), $chargeContext);
|
|
|
$charged = true;
|
|
|
}
|
|
|
}
|
|
|
@@ -392,17 +396,17 @@ class DeepSeekService
|
|
|
* @param mixed $usage
|
|
|
* @return void
|
|
|
*/
|
|
|
- private function chargeMultimodal(int $uid, string $model, int $points, string $modality, $usage): void
|
|
|
+ private function chargeMultimodal(int $uid, string $model, int $points, string $modality, $usage, array $chargeContext = []): void
|
|
|
{
|
|
|
$result = $this->pointsService->recordChatCharge(
|
|
|
$uid,
|
|
|
$points,
|
|
|
$this->pointsService->getTokensFromUsage($usage),
|
|
|
- [
|
|
|
+ array_merge([
|
|
|
'model' => $model,
|
|
|
'modality' => $modality,
|
|
|
'source' => 'generateText',
|
|
|
- ],
|
|
|
+ ], $chargeContext),
|
|
|
'',
|
|
|
$model
|
|
|
);
|
|
|
@@ -989,6 +993,8 @@ class DeepSeekService
|
|
|
'sequence' => $sequence,
|
|
|
'original_prompt' => getProp($data, 'prompt', ''),
|
|
|
'response_format' => $responseFormat,
|
|
|
+ // 计费锚点与业务来源(前端有传才记录)
|
|
|
+ 'charge_context' => ScriptAnchor::chargeContextFromRequest($data),
|
|
|
]);
|
|
|
}
|
|
|
|
|
|
@@ -1088,12 +1094,12 @@ class DeepSeekService
|
|
|
]);
|
|
|
}
|
|
|
if ($ctx['has_valid_script'] && $fullContent !== '') {
|
|
|
- $this->chargeChatSuccess($ctx['uid'], $this->pointsService->getTokensFromUsage($usage), [
|
|
|
+ $this->chargeChatSuccess($ctx['uid'], $this->pointsService->getTokensFromUsage($usage), array_merge([
|
|
|
'model' => $ctx['model'],
|
|
|
'script_id' => $ctx['script_id'],
|
|
|
'sequence' => $ctx['sequence'],
|
|
|
'source' => 'newGenerateText',
|
|
|
- ]);
|
|
|
+ ], $ctx['charge_context'] ?? []));
|
|
|
}
|
|
|
});
|
|
|
|
|
|
@@ -1729,12 +1735,12 @@ class DeepSeekService
|
|
|
|
|
|
// 调用成功且存在有效剧本时,返回结果前扣除积分并记录明细(chat类型10积分)
|
|
|
if ($hasValidScript && $aiResult && !empty($aiResult['content'])) {
|
|
|
- $this->chargeChatSuccess($uid, $this->pointsService->getTokensFromUsage($aiResult['usage'] ?? []), [
|
|
|
+ $this->chargeChatSuccess($uid, $this->pointsService->getTokensFromUsage($aiResult['usage'] ?? []), array_merge([
|
|
|
'model' => $model,
|
|
|
'script_id' => $script_id,
|
|
|
'sequence' => $sequence,
|
|
|
'source' => 'newGenerateText',
|
|
|
- ]);
|
|
|
+ ], ScriptAnchor::chargeContextFromRequest($data)));
|
|
|
}
|
|
|
|
|
|
// 新增: 如果提供了script_id,保存对话记录
|