44
55namespace Elegantly \Translator \Services \Translate ;
66
7+ use Closure ;
78use InvalidArgumentException ;
89use OpenAI ;
910
@@ -32,7 +33,7 @@ public static function makeClient(): \OpenAI\Client
3233 $ apiKey = config ('translator.translate.services.openai.key ' ) ?? config ('translator.services.openai.key ' );
3334 $ organization = config ('translator.translate.services.openai.organization ' ) ?? config ('translator.services.openai.organization ' );
3435 $ project = config ('translator.translate.services.openai.project ' ) ?? config ('translator.services.openai.project ' );
35- $ timeout = config ( ' translator.translate.services.openai.request_timeout ' ) ?? config ( ' translator.services.openai.request_timeout ' ) ?? 120 ;
36+ $ timeout = static :: getTimeout () ;
3637
3738 if (blank ($ apiKey )) {
3839 throw new InvalidArgumentException (
@@ -50,32 +51,64 @@ public static function makeClient(): \OpenAI\Client
5051 ->make ();
5152 }
5253
54+ public static function getTimeout (): int
55+ {
56+ return (int ) (config ('translator.translate.services.openai.request_timeout ' ) ?? config ('translator.services.openai.request_timeout ' ) ?? 120 );
57+ }
58+
59+ /**
60+ * @template TValue
61+ *
62+ * @param (Closure():TValue) $callback
63+ * @return TValue
64+ */
65+ protected function withTemporaryTimeout (int $ limit , Closure $ callback ): mixed
66+ {
67+ $ initial = (int ) ini_get ('max_execution_time ' );
68+
69+ set_time_limit ($ limit );
70+
71+ try {
72+ return $ callback ();
73+ } catch (\Throwable $ th ) {
74+ throw $ th ;
75+ } finally {
76+ set_time_limit ($ initial );
77+ }
78+ }
79+
5380 public function translateAll (array $ texts , string $ targetLocale ): array
5481 {
55- return collect ($ texts )
56- ->chunk (20 )
57- ->map (function ($ chunk ) use ($ targetLocale ) {
58- $ response = $ this ->client ->chat ()->create ([
59- 'model ' => $ this ->model ,
60- 'response_format ' => ['type ' => 'json_object ' ],
61- 'messages ' => [
62- [
63- 'role ' => 'system ' ,
64- 'content ' => str_replace ('{targetLocale} ' , $ targetLocale , $ this ->prompt ),
65- ],
66- [
67- 'role ' => 'user ' ,
68- 'content ' => $ chunk ->toJson (),
69- ],
70- ],
71- ]);
72-
73- $ content = $ response ->choices [0 ]->message ->content ;
74- $ translations = json_decode ($ content , true );
75-
76- return $ translations ;
77- })
78- ->collapse ()
79- ->toArray ();
82+ return $ this ->withTemporaryTimeout (
83+ static ::getTimeout (),
84+ function () use ($ texts , $ targetLocale ) {
85+ return collect ($ texts )
86+ ->chunk (50 )
87+ ->map (function ($ chunk ) use ($ targetLocale ) {
88+ $ response = $ this ->client ->chat ()->create ([
89+ 'model ' => $ this ->model ,
90+ 'response_format ' => ['type ' => 'json_object ' ],
91+ 'messages ' => [
92+ [
93+ 'role ' => 'system ' ,
94+ 'content ' => str_replace ('{targetLocale} ' , $ targetLocale , $ this ->prompt ),
95+ ],
96+ [
97+ 'role ' => 'user ' ,
98+ 'content ' => $ chunk ->toJson (),
99+ ],
100+ ],
101+ ]);
102+
103+ $ content = $ response ->choices [0 ]->message ->content ;
104+ $ translations = json_decode ($ content , true );
105+
106+ return $ translations ;
107+ })
108+ ->collapse ()
109+ ->toArray ();
110+ }
111+ );
112+
80113 }
81114}
0 commit comments