arpakitlib 1.8.327__py3-none-any.whl → 1.8.328__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,204 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+
6
+ import httpx
7
+ from arpakitlib.ar_base64_util import convert_file_to_base64_string
8
+ from openai import OpenAI, AsyncOpenAI
9
+ from openai.types.chat import ChatCompletion
10
+
11
+ """
12
+ https://platform.openai.com/docs/
13
+ """
14
+
15
+
16
+ class EasyOpenAIAPIClient:
17
+ def __init__(
18
+ self,
19
+ *,
20
+ open_ai: OpenAI,
21
+ async_open_ai: AsyncOpenAI
22
+ ):
23
+ self._logger = logging.getLogger(self.__class__.__name__)
24
+
25
+ self.open_ai = open_ai
26
+ self.async_open_ai = async_open_ai
27
+
28
+ @classmethod
29
+ def create_easily(
30
+ cls,
31
+ openai_api_key: str,
32
+ openai_api_base_url: str | None = "https://api.proxyapi.ru/openai/v1"
33
+ ) -> EasyOpenAIAPIClient:
34
+ return EasyOpenAIAPIClient(
35
+ open_ai=OpenAI(
36
+ api_key=openai_api_key,
37
+ base_url=openai_api_base_url,
38
+ timeout=httpx.Timeout(
39
+ timeout=300, # общий таймаут
40
+ connect=5, # таймаут подключения
41
+ read=300, # чтение ответа
42
+ write=60, # запись запроса
43
+ pool=10
44
+ )
45
+ ),
46
+ async_open_ai=AsyncOpenAI(
47
+ api_key=openai_api_key,
48
+ base_url=openai_api_base_url,
49
+ http_client=httpx.AsyncClient(
50
+ timeout=httpx.Timeout(
51
+ timeout=300,
52
+ connect=5,
53
+ read=300,
54
+ write=60,
55
+ pool=10
56
+ )
57
+ )
58
+ )
59
+ )
60
+
61
+ def check_conn(self):
62
+ self.open_ai.models.list()
63
+
64
+ def is_conn_good(self) -> bool:
65
+ try:
66
+ self.check_conn()
67
+ return True
68
+ except Exception as e:
69
+ self._logger.error(e)
70
+ return False
71
+
72
+ async def async_check_conn(self):
73
+ await self.async_open_ai.models.list()
74
+
75
+ async def async_is_conn_good(self) -> bool:
76
+ try:
77
+ await self.async_check_conn()
78
+ return True
79
+ except Exception as e:
80
+ self._logger.error(e)
81
+ return False
82
+
83
+ def simple_ask(
84
+ self,
85
+ *,
86
+ prompt: str | None = None,
87
+ text: str,
88
+ model: str = "gpt-4o",
89
+ image_links: str | list[str] | None = None,
90
+ image_filepaths: str | list[str] | None = None
91
+ ) -> ChatCompletion:
92
+ if isinstance(image_links, str):
93
+ image_links = [image_links]
94
+ if isinstance(image_filepaths, str):
95
+ image_filepaths = [image_filepaths]
96
+
97
+ messages = []
98
+
99
+ if prompt is not None:
100
+ messages.append({
101
+ "role": "system",
102
+ "content": prompt
103
+ })
104
+
105
+ content = [{"type": "text", "text": text}]
106
+
107
+ if image_links:
108
+ for link in image_links:
109
+ content.append({
110
+ "type": "image_url",
111
+ "image_url": {"url": link}
112
+ })
113
+
114
+ if image_filepaths:
115
+ for path in image_filepaths:
116
+ base64_url = convert_file_to_base64_string(filepath=path, raise_for_error=True)
117
+ content.append({
118
+ "type": "image_url",
119
+ "image_url": {"url": base64_url}
120
+ })
121
+
122
+ messages.append({
123
+ "role": "user",
124
+ "content": content
125
+ })
126
+
127
+ response: ChatCompletion = self.open_ai.chat.completions.create(
128
+ model=model,
129
+ messages=messages,
130
+ n=1,
131
+ temperature=0.1,
132
+ top_p=0.9,
133
+ max_tokens=1000
134
+ )
135
+
136
+ return response
137
+
138
+ async def async_simple_ask(
139
+ self,
140
+ *,
141
+ prompt: str | None = None,
142
+ text: str,
143
+ model: str = "gpt-4o",
144
+ image_links: str | list[str] | None = None,
145
+ image_filepaths: str | list[str] | None = None
146
+ ) -> ChatCompletion:
147
+ if isinstance(image_links, str):
148
+ image_links = [image_links]
149
+ if isinstance(image_filepaths, str):
150
+ image_filepaths = [image_filepaths]
151
+
152
+ messages = []
153
+
154
+ if prompt is not None:
155
+ messages.append({
156
+ "role": "system",
157
+ "content": prompt
158
+ })
159
+
160
+ content = [{"type": "text", "text": text}]
161
+
162
+ if image_links:
163
+ for link in image_links:
164
+ content.append({
165
+ "type": "image_url",
166
+ "image_url": {"url": link}
167
+ })
168
+
169
+ if image_filepaths:
170
+ for path in image_filepaths:
171
+ base64_url = convert_file_to_base64_string(filepath=path, raise_for_error=True)
172
+ content.append({
173
+ "type": "image_url",
174
+ "image_url": {"url": base64_url}
175
+ })
176
+
177
+ messages.append({
178
+ "role": "user",
179
+ "content": content
180
+ })
181
+
182
+ response: ChatCompletion = await self.async_open_ai.chat.completions.create(
183
+ model=model,
184
+ messages=messages,
185
+ n=1,
186
+ temperature=0.1,
187
+ top_p=0.9,
188
+ max_tokens=1000
189
+ )
190
+
191
+ return response
192
+
193
+
194
+ def __example():
195
+ pass
196
+
197
+
198
+ async def __async_example():
199
+ pass
200
+
201
+
202
+ if __name__ == '__main__':
203
+ __example()
204
+ asyncio.run(__async_example())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: arpakitlib
3
- Version: 1.8.327
3
+ Version: 1.8.328
4
4
  Summary: arpakitlib
5
5
  License-Expression: Apache-2.0
6
6
  License-File: LICENSE
@@ -408,6 +408,7 @@ arpakitlib/ar_log_async_func_if_error_util.py,sha256=8qtcxRk6OqfwVsGE2wCpuIY7fju
408
408
  arpakitlib/ar_logging_util.py,sha256=8TdaCWeSk4_GAmuWFO49l8JAVfLJCqUxgSpTYvlWvsk,1308
409
409
  arpakitlib/ar_mongodb_util.py,sha256=orRb81o9CzD9kkWbbNQCbSMTl2xLcctUDdx_FxirKww,3411
410
410
  arpakitlib/ar_need_type_util.py,sha256=XmY1kswz8j9oo5f9CxRu0_zgfvxWrXPYKOj6MM04sGk,2604
411
+ arpakitlib/ar_openai_api_client_util.py,sha256=dIPHNrDRkclRa__qPj7glkv232C97tzAAFEFuXtvV1E,5569
411
412
  arpakitlib/ar_parse_command_util.py,sha256=1WTdQoWVshoDZ1jDaKeTzajfqaYHP3FNO0-REyo1aMY,3003
412
413
  arpakitlib/ar_postgresql_util.py,sha256=1AuLjEaa1Lg4pzn-ukCVnDi35Eg1k91APRTqZhIJAdo,945
413
414
  arpakitlib/ar_pydantic_schema_from_sqlalchemy_model_util.py,sha256=SddmsEdRdVbmdZ5aSuwy6DfGYmYx_JO6lKzuEJeBAV8,10553
@@ -428,8 +429,8 @@ arpakitlib/ar_str_util.py,sha256=6KlLL-SB8gzK-6gwQEd3zuYbRvtjd9HFpJ9-xHbkH6U,435
428
429
  arpakitlib/ar_type_util.py,sha256=Cs_tef-Fc5xeyAF54KgISCsP11NHyzIsglm4S3Xx7iM,4049
429
430
  arpakitlib/ar_uppercase_env_keys_util.py,sha256=BsUCJhfchBIav0AE54_tVgYcE4p1JYoWdPGCHWZnROA,2790
430
431
  arpakitlib/ar_yookassa_api_client_util.py,sha256=7DL_0GyIOTuSNBHUO3qWxAXMKlBRHjKgcA6ttst8k1A,5265
431
- arpakitlib-1.8.327.dist-info/METADATA,sha256=-pMxjG5dQPSW-_vsrE8TI3YNBDASDHJ-h3NzbKJT1JA,3804
432
- arpakitlib-1.8.327.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
433
- arpakitlib-1.8.327.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
434
- arpakitlib-1.8.327.dist-info/licenses/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
435
- arpakitlib-1.8.327.dist-info/RECORD,,
432
+ arpakitlib-1.8.328.dist-info/METADATA,sha256=89Z-J3Lhic6uYoQgkP8PN0m5uTDxjwlUMK6Y6UaL24A,3804
433
+ arpakitlib-1.8.328.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
434
+ arpakitlib-1.8.328.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
435
+ arpakitlib-1.8.328.dist-info/licenses/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
436
+ arpakitlib-1.8.328.dist-info/RECORD,,