Async call to the Dashscope API.
(
self, api_kwargs: Dict = {}, model_type: ModelType = ModelType.UNDEFINED
)
| 496 | max_time=5, |
| 497 | ) |
| 498 | async def acall( |
| 499 | self, api_kwargs: Dict = {}, model_type: ModelType = ModelType.UNDEFINED |
| 500 | ): |
| 501 | """Async call to the Dashscope API.""" |
| 502 | if not self.async_client: |
| 503 | self.async_client = self.init_async_client() |
| 504 | |
| 505 | if model_type == ModelType.LLM: |
| 506 | if not api_kwargs.get("stream", False): |
| 507 | # For non-streaming, enable_thinking must be false. |
| 508 | extra_body = api_kwargs.get("extra_body", {}) |
| 509 | extra_body["enable_thinking"] = False |
| 510 | api_kwargs["extra_body"] = extra_body |
| 511 | |
| 512 | completion = await self.async_client.chat.completions.create(**api_kwargs) |
| 513 | |
| 514 | # For async calls with streaming enabled, wrap the AsyncStream |
| 515 | # into an async generator of plain text chunks so that callers |
| 516 | # can simply `async for text in response`. |
| 517 | if api_kwargs.get("stream", False): |
| 518 | |
| 519 | async def async_stream_generator(): |
| 520 | async for chunk in completion: |
| 521 | log.debug(f"Raw async chunk completion: {chunk}") |
| 522 | try: |
| 523 | parsed_content = parse_stream_response(chunk) |
| 524 | except Exception as e: |
| 525 | log.error(f"Error parsing async stream chunk: {e}") |
| 526 | parsed_content = None |
| 527 | if parsed_content: |
| 528 | yield parsed_content |
| 529 | |
| 530 | return async_stream_generator() |
| 531 | else: |
| 532 | return self.parse_chat_completion(completion) |
| 533 | elif model_type == ModelType.EMBEDDER: |
| 534 | # Extract input texts from api_kwargs |
| 535 | texts = api_kwargs.get("input", []) |
| 536 | |
| 537 | if not texts: |
| 538 | log.warning("😭 No input texts provided") |
| 539 | return EmbedderOutput(data=[], error="No input texts provided", raw_response=None) |
| 540 | |
| 541 | # Ensure texts is a list |
| 542 | if isinstance(texts, str): |
| 543 | texts = [texts] |
| 544 | |
| 545 | # Filter out empty or None texts - following HuggingFace client pattern |
| 546 | valid_texts = [] |
| 547 | valid_indices = [] |
| 548 | for i, text in enumerate(texts): |
| 549 | if text and isinstance(text, str) and text.strip(): |
| 550 | valid_texts.append(text) |
| 551 | valid_indices.append(i) |
| 552 | else: |
| 553 | log.warning(f"🔍 Skipping empty or invalid text at index {i}: type={type(text)}, length={len(text) if hasattr(text, '__len__') else 'N/A'}, repr={repr(text)[:100]}") |
| 554 | |
| 555 | if not valid_texts: |
no test coverage detected