1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
Request.php
См. документацию.
1<?php
2declare(strict_types=1);
3
4namespace Bitrix\Landing\Copilot\Generation;
5
6use Bitrix\Landing\Copilot\Connector\AI\IConnector;
7use Bitrix\Landing\Copilot\Connector\AI\Prompt;
8use Bitrix\Landing\Copilot\Connector\AI\RequestLimiter;
9use Bitrix\Landing\Copilot\Converter;
10use Bitrix\Landing\Copilot\Generation;
11use Bitrix\Landing\Copilot\Generation\Type\Errors;
12use Bitrix\Landing\Copilot\Generation\Type\GenerationErrors;
13use Bitrix\Landing\Copilot\Model\EO_Requests;
14use Bitrix\Landing\Copilot\Model\RequestsTable;
15use Bitrix\Landing\Copilot\Model\RequestToStepTable;
16use Bitrix\Main;
17use Bitrix\Main\ORM\Query\Query;
18use Bitrix\Main\ORM\Query\Filter;
19use Bitrix\Main\Type\DateTime;
20use Bitrix\Main\Web;
21use Exception;
22
24{
25 // todo: get individual time from step
26 private const MAX_EXPECTED_TIME = 75;
27
28 private int $generationId;
29 private int $stepId;
30 private ?int $id;
31 private ?string $hash = null;
32 private ?array $result = null;
33 private ?Generation\Error $error = null;
34 private bool $isDeleted = false;
35 private ?int $stepRelationId;
36 private DateTime $dateCreate;
37 private DateTime $dateReceive;
38
39 private Type\RequestStatus $status = Type\RequestStatus::New;
40 private RequestLimiter $requestLimiter;
41
42 public function __construct(int $generationId, int $stepId)
43 {
44 $this->generationId = $generationId;
45 $this->stepId = $stepId;
46 }
47
55 public function send(Prompt $prompt, IConnector $connector): bool
56 {
57 if (!Generation::checkExists($this->generationId))
58 {
59 return false;
60 }
61
62 if ($this->status->value >= Type\RequestStatus::Sent->value)
63 {
64 return false;
65 }
66
67 $result = $connector->request($prompt);
68 if (!$result->isSuccess())
69 {
70 $this->processError($result->getError());
71 }
72
73 $this->status = Type\RequestStatus::Sent;
74 $data = $result->getData();
75
76 // is queued
77 if (isset($data['hash']) && $data['hash'])
78 {
79 $this->hash = $data['hash'];
80
81 return $this->save();
82 }
83
84 // is realtime answer
85 if (isset($data['result']) && $data['result'])
86 {
87 $result = null;
88 if (is_string($data['result']))
89 {
90 try
91 {
92 $result = Converter\Json::expandJsonString($data['result']);
93 $result = Web\Json::decode($result);
94 }
95 catch (Exception)
96 {
97 $error = Generation\Error::createError(Errors::requestError);
98
99 return $this->saveError($error);
100 }
101 }
102
103 return $this->saveResult($result);
104 }
105
106 if (isset($data['error']) && $data['error'])
107 {
108 $error = Generation\Error::createError(Errors::requestError);
109 $error->message .= ': ' . $data['error'];
110
111 return $this->saveError($error);
112 }
113
114 return false;
115 }
116
122 private function processError(?Main\Error $error): void
123 {
124 if ($error === null)
125 {
126 throw new GenerationException(GenerationErrors::notSendRequest);
127 }
128
129 $errorText = $this->getRequestLimiter()->getTextFromError($error);
130
131 if ($errorText)
132 {
133 $params = [
134 'errorText' => $errorText,
135 ];
136
137 throw new GenerationException(GenerationErrors::requestQuotaExceeded, $error->getMessage(), $params);
138 }
139
140 throw new GenerationException(GenerationErrors::errorInRequest, $error->getMessage(), null);
141 }
142
148 private function getRequestLimiter(): RequestLimiter
149 {
150 if (empty($this->requestLimiter))
151 {
152 $this->requestLimiter = new RequestLimiter();
153 }
154
155 return $this->requestLimiter;
156 }
157
158 public function setApplied(): bool
159 {
160 if ($this->status->value < Type\RequestStatus::Received->value)
161 {
162 return false;
163 }
164
165 if (!isset($this->stepRelationId))
166 {
167 return false;
168 }
169
170 if ($this->status === Type\RequestStatus::Applied)
171 {
172 return true;
173 }
174
175 $res = RequestToStepTable::update($this->stepRelationId, [
176 'APPLIED' => true,
177 ]);
178 if (!$res->isSuccess())
179 {
180 return false;
181 }
182
183 $this->status = Type\RequestStatus::Applied;
184
185 return $this->save();
186 }
187
193 public function saveResult(array $result): bool
194 {
195 if ($this->status !== Type\RequestStatus::Sent)
196 {
197 return false;
198 }
199
200 $this->result = $result;
201 $this->status = Type\RequestStatus::Received;
202 $this->dateReceive = new DateTime();
203
204 return $this->save();
205 }
206
212 public function saveError(Generation\Error $error): bool
213 {
214 if ($this->status > Type\RequestStatus::Sent)
215 {
216 return false;
217 }
218
219 $this->error = $error;
220 $this->status = Type\RequestStatus::Received;
221 $this->dateReceive = new DateTime();
222
223 return $this->save();
224 }
225
226 public function setDeleted(): void
227 {
228 $this->isDeleted = true;
229 $this->save();
230 }
231
232 private function save(): bool
233 {
234 if ($this->status->value < Type\RequestStatus::Sent->value)
235 {
236 return false;
237 }
238
239 $fields = [
240 'GENERATION_ID' => $this->generationId,
241 'HASH' => $this->hash,
242 'RESULT' => $this->result,
243 'ERROR' => $this->error?->toArray(),
244 'DELETED' => $this->isDeleted,
245 ];
246
247 if (isset($this->dateReceive))
248 {
249 $fields['DATE_RECEIVE'] = $this->dateReceive;
250 }
251
252 if (isset($this->id) && $this->id)
253 {
254 $res = RequestsTable::update($this->id, $fields);
255 if (!$res->isSuccess())
256 {
257 return false;
258 }
259 }
260 else
261 {
262 $res = RequestsTable::add($fields);
263 if (!$res->isSuccess())
264 {
265 return false;
266 }
267 $this->id = $res->getId();
268 }
269
270 if (!isset($this->stepRelationId))
271 {
272 $res = RequestToStepTable::add([
273 'REQUEST_ID' => $this->id,
274 'GENERATION_ID' => $this->generationId,
275 'STEP' => $this->stepId,
276 ]);
277 if (!$res->isSuccess())
278 {
279 return false;
280 }
281
282 $this->stepRelationId = $res->getId();
283 }
284
285 return true;
286 }
287
292 public function getGenerationId(): int
293 {
294 return $this->generationId;
295 }
296
301 public function getResult(): ?array
302 {
303 return $this->result;
304 }
305
310 public function getError(): ?Generation\Error
311 {
312 return $this->error;
313 }
314
319 public function isReceived(): bool
320 {
321 return $this->status === Type\RequestStatus::Received;
322 }
323
328 public function isApplied(): bool
329 {
330 return $this->status === Type\RequestStatus::Applied;
331 }
332
337 public function getId(): ?int
338 {
339 return $this->id;
340 }
341
347 public static function getByGeneration(int $generationId, int $stepId): array
348 {
349 $filter =
350 Query::filter()
351 ->where('GENERATION_ID', '=', $generationId)
352 ->where('STEP_REF.STEP', '=', $stepId)
353 ->where('DELETED', '=', 'N')
354 ;
355
356 return self::getExists($filter);
357 }
358
359 public static function getByHash(string $hash): ?self
360 {
361 $filter =
362 Query::filter()
363 ->where('HASH', '=', $hash)
364 ->where('DELETED', '=', 'N')
365 ;
366 $exists = self::getExists($filter);
367
368 return array_shift($exists);
369 }
370
371 public static function getById(int $id): ?self
372 {
373 $filter =
374 Query::filter()
375 ->where('ID', '=', $id)
376 ->where('DELETED', '=', 'N')
377 ;
378 $exists = self::getExists($filter);
379
380 return array_shift($exists);
381 }
382
387 private static function getExists(Filter\ConditionTree $filter): array
388 {
389 $exists = [];
390 $res = RequestsTable::query()
391 ->setSelect([
392 'ID',
393 'GENERATION_ID',
394 'HASH',
395 'RESULT',
396 'ERROR',
397 'DELETED',
398 'DATE_CREATE',
399 'DATE_RECEIVE',
400 'STEP' => 'STEP_REF.STEP',
401 ])
402 ->where($filter)
403 ->exec()
404 ;
405 while ($entity = $res->fetchObject())
406 {
407 if (
408 !$entity->getGenerationId()
409 || !$entity->getStepRef()->getStep()
410 )
411 {
412 continue;
413 }
414
415 $request = new Request(
416 $entity->getGenerationId(),
417 $entity->getStepRef()->getStep(),
418 );
419 $request->initByEntity($entity);
420
421 if ($request->isTimeIsOver())
422 {
423 $request->setDeleted();
424
425 continue;
426 }
427
428 $exists[$entity->getId()] = $request;
429 }
430
431 return $exists;
432 }
433
434 private function initByEntity(EO_Requests $request): self
435 {
436 $this->id = $request->getId();
437 $this->isDeleted = $request->getDeleted();
438
439 $hash = $request->getHash();
440 if ($hash)
441 {
442 $this->hash = $hash;
443 $this->status = Type\RequestStatus::Sent;
444 }
445
446 $result = $request->getResult();
447 $error = $request->getError();
448 if (!empty($result))
449 {
450 $this->result = $result;
451 $this->status = Type\RequestStatus::Received;
452 }
453 elseif (!empty($error))
454 {
455 $this->error = Generation\Error::fromArray($error);
456 $this->status = Type\RequestStatus::Received;
457 }
458
459 $this->dateCreate = $request->getDateCreate();
460 $dateReceive = $request->getDateReceive();
461 if ($dateReceive)
462 {
463 $this->dateReceive = $dateReceive;
464 }
465
466 $step = $request->getStepRef();
467 if ($step)
468 {
469 $step->fillApplied();
470 $this->stepRelationId = $step->getId();
471 if (!empty($this->result) && $step->getApplied())
472 {
473 $this->status = Generation\Type\RequestStatus::Applied;
474 }
475 }
476
477 return $this;
478 }
479
480 private function isTimeIsOver(): bool
481 {
482 if (
483 isset($this->dateReceive)
484 || isset($this->result)
485 || isset($this->error)
486 )
487 {
488 return false;
489 }
490
491 return ((new \DateTime())->getTimestamp() - $this->dateCreate->getTimestamp()) > self::MAX_EXPECTED_TIME;
492 }
493}
$hash
Определения ajax_redirector.php:8
if(!Loader::includeModule('catalog')) if(!AccessController::getCurrent() ->check(ActionDictionary::ACTION_PRICE_EDIT)) if(!check_bitrix_sessid()) $request
Определения catalog_reindex.php:36
static expandJsonString(string $json)
Определения Json.php:350
static createError(?Errors $code=null)
Определения Error.php:53
saveResult(array $result)
Определения Request.php:193
static getByGeneration(int $generationId, int $stepId)
Определения Request.php:347
saveError(Generation\Error $error)
Определения Request.php:212
static getById(int $id)
Определения Request.php:371
send(Prompt $prompt, IConnector $connector)
Определения Request.php:55
static getByHash(string $hash)
Определения Request.php:359
__construct(int $generationId, int $stepId)
Определения Request.php:42
Определения error.php:15
Определения request.php:10
static decode($data)
Определения json.php:50
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$entity
$filter
Определения iblock_catalog_list.php:54
Определения collection.php:2
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$error
Определения subscription_card_product.php:20
$fields
Определения yandex_run.php:501