tamar-model-client 0.1.15__py3-none-any.whl → 0.1.16__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.
@@ -203,6 +203,37 @@ class AsyncTamarModelClient:
203
203
  logger.error(f"❌ Non-retryable gRPC error: {e}", exc_info=True)
204
204
  raise
205
205
 
206
+ async def _retry_request_stream(self, func, *args, **kwargs):
207
+ retry_count = 0
208
+ while retry_count < self.max_retries:
209
+ try:
210
+ return func(*args, **kwargs)
211
+ except (grpc.aio.AioRpcError, grpc.RpcError) as e:
212
+ # 对于取消的情况进行指数退避重试
213
+ if isinstance(e, grpc.aio.AioRpcError) and e.code() == grpc.StatusCode.CANCELLED:
214
+ retry_count += 1
215
+ logger.warning(f"❌ RPC cancelled, retrying {retry_count}/{self.max_retries}...")
216
+ if retry_count < self.max_retries:
217
+ delay = self.retry_delay * (2 ** (retry_count - 1))
218
+ await asyncio.sleep(delay)
219
+ else:
220
+ logger.error("❌ Max retry reached for CANCELLED")
221
+ raise
222
+ # 针对其他 RPC 错误类型,如暂时的连接问题、服务器超时等
223
+ elif isinstance(e, grpc.RpcError) and e.code() in {grpc.StatusCode.UNAVAILABLE,
224
+ grpc.StatusCode.DEADLINE_EXCEEDED}:
225
+ retry_count += 1
226
+ logger.warning(f"❌ gRPC error {e.code()}, retrying {retry_count}/{self.max_retries}...")
227
+ if retry_count < self.max_retries:
228
+ delay = self.retry_delay * (2 ** (retry_count - 1))
229
+ await asyncio.sleep(delay)
230
+ else:
231
+ logger.error(f"❌ Max retry reached for {e.code()}")
232
+ raise
233
+ else:
234
+ logger.error(f"❌ Non-retryable gRPC error: {e}", exc_info=True)
235
+ raise
236
+
206
237
  def _build_auth_metadata(self, request_id: str) -> list:
207
238
  # if not self.jwt_token and self.jwt_handler:
208
239
  # 更改为每次请求都生成一次token
@@ -263,25 +294,23 @@ class AsyncTamarModelClient:
263
294
  logger.info(f"🚀 Retrying connection (attempt {retry_count}/{self.max_retries}) after {delay:.2f}s delay...")
264
295
  await asyncio.sleep(delay)
265
296
 
266
- async def _stream_inner(self, model_request, metadata, invoke_timeout) -> AsyncIterator[ModelResponse]:
267
- """Inner function to handle the actual streaming gRPC call."""
268
- async for response in self.stub.Invoke(model_request, metadata=metadata, timeout=invoke_timeout):
297
+ async def _stream(self, request, metadata, invoke_timeout) -> AsyncIterator[ModelResponse]:
298
+ async for response in self.stub.Invoke(request, metadata=metadata, timeout=invoke_timeout):
269
299
  yield ModelResponse(
270
300
  content=response.content,
271
301
  usage=json.loads(response.usage) if response.usage else None,
272
- raw_response=json.loads(response.raw_response) if response.raw_response else None,
273
302
  error=response.error or None,
303
+ raw_response=json.loads(response.raw_response) if response.raw_response else None,
304
+ request_id=response.request_id if response.request_id else None,
274
305
  )
275
306
 
276
- async def _stream(self, model_request, metadata, invoke_timeout) -> AsyncIterator[ModelResponse]:
277
- return await self._retry_request(self._stream_inner, model_request, metadata, invoke_timeout)
278
-
279
307
  async def _invoke_request(self, request, metadata, invoke_timeout):
280
308
  async for response in self.stub.Invoke(request, metadata=metadata, timeout=invoke_timeout):
281
309
  return ModelResponse(
282
310
  content=response.content,
283
311
  usage=json.loads(response.usage) if response.usage else None,
284
312
  error=response.error or None,
313
+ raw_response=json.loads(response.raw_response) if response.raw_response else None,
285
314
  request_id=response.request_id if response.request_id else None,
286
315
  )
287
316
 
@@ -373,7 +402,7 @@ class AsyncTamarModelClient:
373
402
  try:
374
403
  invoke_timeout = timeout or self.default_invoke_timeout
375
404
  if model_request.stream:
376
- return await self._stream(request, metadata, invoke_timeout)
405
+ return await self._retry_request_stream(self._stream, request, metadata, invoke_timeout)
377
406
  else:
378
407
  return await self._retry_request(self._invoke_request, request, metadata, invoke_timeout)
379
408
  except grpc.RpcError as e:
@@ -247,20 +247,16 @@ class TamarModelClient:
247
247
  logger.info(f"🚀 Retrying connection (attempt {retry_count}/{self.max_retries}) after {delay:.2f}s delay...")
248
248
  time.sleep(delay) # Blocking sleep in sync version
249
249
 
250
- def _stream_inner(self, model_request, metadata, invoke_timeout) -> Iterator[ModelResponse]:
251
- """Inner function to handle the actual streaming gRPC call."""
252
- response = self.stub.Invoke(model_request, metadata=metadata, timeout=invoke_timeout)
253
- for res in response:
250
+ def _stream(self, request, metadata, invoke_timeout) -> Iterator[ModelResponse]:
251
+ for response in self.stub.Invoke(request, metadata=metadata, timeout=invoke_timeout):
254
252
  yield ModelResponse(
255
- content=res.content,
256
- usage=json.loads(res.usage) if res.usage else None,
257
- raw_response=json.loads(res.raw_response) if res.raw_response else None,
258
- error=res.error or None,
253
+ content=response.content,
254
+ usage=json.loads(response.usage) if response.usage else None,
255
+ error=response.error or None,
256
+ raw_response=json.loads(response.raw_response) if response.raw_response else None,
257
+ request_id=response.request_id if response.request_id else None,
259
258
  )
260
259
 
261
- def _stream(self, model_request, metadata, invoke_timeout) -> Iterator[ModelResponse]:
262
- return self._retry_request(self._stream_inner, model_request, metadata, invoke_timeout)
263
-
264
260
  def _invoke_request(self, request, metadata, invoke_timeout):
265
261
  response = self.stub.Invoke(request, metadata=metadata, timeout=invoke_timeout)
266
262
  for response in response:
@@ -268,6 +264,7 @@ class TamarModelClient:
268
264
  content=response.content,
269
265
  usage=json.loads(response.usage) if response.usage else None,
270
266
  error=response.error or None,
267
+ raw_response=json.loads(response.raw_response) if response.raw_response else None,
271
268
  request_id=response.request_id if response.request_id else None,
272
269
  )
273
270
 
@@ -358,7 +355,7 @@ class TamarModelClient:
358
355
  try:
359
356
  invoke_timeout = timeout or self.default_invoke_timeout
360
357
  if model_request.stream:
361
- return self._stream(request, metadata, invoke_timeout)
358
+ return self._retry_request(self._stream, request, metadata, invoke_timeout)
362
359
  else:
363
360
  return self._retry_request(self._invoke_request, request, metadata, invoke_timeout)
364
361
  except grpc.RpcError as e:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tamar-model-client
3
- Version: 0.1.15
3
+ Version: 0.1.16
4
4
  Summary: A Python SDK for interacting with the Model Manager gRPC service
5
5
  Home-page: http://gitlab.tamaredge.top/project-tap/AgentOS/model-manager-client
6
6
  Author: Oscar Ou
@@ -273,13 +273,13 @@ async def main():
273
273
  )
274
274
 
275
275
  # 发送请求并获取响应
276
- response = await client.invoke(request_data)
277
- if response.error:
278
- print(f"错误: {response.error}")
279
- else:
280
- print(f"响应: {response.content}")
281
- if response.usage:
282
- print(f"Token 使用情况: {response.usage}")
276
+ async for r in await client.invoke(model_request):
277
+ if r.error:
278
+ print(f"错误: {r.error}")
279
+ else:
280
+ print(f"响应: {r.content}")
281
+ if r.usage:
282
+ print(f"Token 使用情况: {r.usage}")
283
283
 
284
284
 
285
285
  # 运行异步示例
@@ -531,7 +531,7 @@ python make_grpc.py
531
531
  ### 部署到 pip
532
532
  ```bash
533
533
  python setup.py sdist bdist_wheel
534
- twine check dist/*
534
+ twine upload dist/*
535
535
 
536
536
  ```
537
537
 
@@ -1,8 +1,8 @@
1
1
  tamar_model_client/__init__.py,sha256=LMECAuDARWHV1XzH3msoDXcyurS2eihRQmBy26_PUE0,328
2
- tamar_model_client/async_client.py,sha256=Ckg9BbndvlqhngixaEe-Yfu9Fkh5T9FOqToYGAHhRg4,23941
2
+ tamar_model_client/async_client.py,sha256=K14GigYdcsHQg83PP1YH3wxxZEUwvFlIFMWdFfegnhc,25655
3
3
  tamar_model_client/auth.py,sha256=gbwW5Aakeb49PMbmYvrYlVx1mfyn1LEDJ4qQVs-9DA4,438
4
4
  tamar_model_client/exceptions.py,sha256=jYU494OU_NeIa4X393V-Y73mTNm0JZ9yZApnlOM9CJQ,332
5
- tamar_model_client/sync_client.py,sha256=wMZw-d5s2ctaNIDUCUeRK2iZDLzuRryNjDaAVemFhk8,22558
5
+ tamar_model_client/sync_client.py,sha256=B4itGuFy1T6g2pnC-95RbaaOqtRIYLeW9eah-CRFRM0,22486
6
6
  tamar_model_client/enums/__init__.py,sha256=3cYYn8ztNGBa_pI_5JGRVYf2QX8fkBVWdjID1PLvoBQ,182
7
7
  tamar_model_client/enums/channel.py,sha256=wCzX579nNpTtwzGeS6S3Ls0UzVAgsOlfy4fXMzQTCAw,199
8
8
  tamar_model_client/enums/invoke.py,sha256=WufImoN_87ZjGyzYitZkhNNFefWJehKfLtyP-DTBYlA,267
@@ -13,7 +13,7 @@ tamar_model_client/generated/model_service_pb2_grpc.py,sha256=k4tIbp3XBxdyuOVR18
13
13
  tamar_model_client/schemas/__init__.py,sha256=AxuI-TcvA4OMTj2FtK4wAItvz9LrK_293pu3cmMLE7k,394
14
14
  tamar_model_client/schemas/inputs.py,sha256=AlvjTRp_UGnbmqzv4OJ3RjH4UGErzSNfKS8Puj6oEXQ,19088
15
15
  tamar_model_client/schemas/outputs.py,sha256=M_fcqUtXPJnfiLabHlyA8BorlC5pYkf5KLjXO1ysKIQ,1031
16
- tamar_model_client-0.1.15.dist-info/METADATA,sha256=ZXSYngVn_8ors2DORv7CxzadNvCD7927Duqk0lEY5yc,16566
17
- tamar_model_client-0.1.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
- tamar_model_client-0.1.15.dist-info/top_level.txt,sha256=_LfDhPv_fvON0PoZgQuo4M7EjoWtxPRoQOBJziJmip8,19
19
- tamar_model_client-0.1.15.dist-info/RECORD,,
16
+ tamar_model_client-0.1.16.dist-info/METADATA,sha256=YaPEPgdIVcJVSZ55rzx-G5TtjHTT0teXJspOz5O3vyE,16562
17
+ tamar_model_client-0.1.16.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ tamar_model_client-0.1.16.dist-info/top_level.txt,sha256=_LfDhPv_fvON0PoZgQuo4M7EjoWtxPRoQOBJziJmip8,19
19
+ tamar_model_client-0.1.16.dist-info/RECORD,,