euriai 1.0.2__tar.gz → 1.0.3__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: euriai
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Python client for Euri API (euron.one) with CLI, LangChain, and LlamaIndex integration
5
5
  Author: Euri
6
6
  Author-email: tech@euron.one
@@ -482,11 +482,9 @@ class EuriaiChatModel(BaseChatModel):
482
482
  self,
483
483
  schema: Union[Dict, Type[BaseModel]],
484
484
  **kwargs: Any
485
- ) -> "EuriaiChatModel":
485
+ ) -> "EuriaiStructuredChatModel":
486
486
  """Create a version that returns structured output."""
487
- # This would need to be implemented with proper schema validation
488
- # For now, return self with structured output enabled
489
- return self.__class__(
487
+ return EuriaiStructuredChatModel(
490
488
  api_key=self.api_key,
491
489
  model=self.model,
492
490
  temperature=self.temperature,
@@ -497,11 +495,136 @@ class EuriaiChatModel(BaseChatModel):
497
495
  streaming=self.streaming,
498
496
  supports_function_calling=self.supports_function_calling,
499
497
  supports_structured_output=True,
500
- _structured_output_schema=schema,
498
+ schema=schema,
501
499
  **kwargs
502
500
  )
503
501
 
504
502
 
503
+ class EuriaiStructuredChatModel(EuriaiChatModel):
504
+ """
505
+ EuriaiChatModel with structured output support.
506
+
507
+ This class extends EuriaiChatModel to parse responses into structured Pydantic models.
508
+ """
509
+
510
+ def __init__(self, schema: Union[Dict, Type[BaseModel]], **kwargs):
511
+ # Initialize the parent class first
512
+ super().__init__(**kwargs)
513
+
514
+ # Store schema in private attributes to avoid Pydantic conflicts
515
+ self._output_schema = schema
516
+ self._schema_name = getattr(schema, '__name__', 'OutputSchema')
517
+
518
+ @property
519
+ def schema(self):
520
+ """Get the output schema."""
521
+ return self._output_schema
522
+
523
+ @property
524
+ def schema_name(self):
525
+ """Get the schema name."""
526
+ return self._schema_name
527
+
528
+ def _get_json_schema(self) -> Dict[str, Any]:
529
+ """Generate JSON schema from the Pydantic model."""
530
+ if hasattr(self.schema, 'model_json_schema'):
531
+ # Pydantic v2
532
+ return self.schema.model_json_schema()
533
+ elif hasattr(self.schema, 'schema'):
534
+ # Pydantic v1
535
+ return self.schema.schema()
536
+ else:
537
+ # Dictionary schema
538
+ return self.schema
539
+
540
+ def _create_structured_prompt(self, original_prompt: str) -> str:
541
+ """Create a prompt that requests structured JSON output."""
542
+ json_schema = self._get_json_schema()
543
+
544
+ structured_prompt = f"""{original_prompt}
545
+
546
+ Please respond with a valid JSON object that matches this exact schema:
547
+ ```json
548
+ {json.dumps(json_schema, indent=2)}
549
+ ```
550
+
551
+ Your response must be valid JSON that can be parsed. Do not include any other text outside the JSON object."""
552
+
553
+ return structured_prompt
554
+
555
+ def _parse_structured_response(self, response_content: str) -> Any:
556
+ """Parse the response content into the structured format."""
557
+ try:
558
+ # Try to find JSON in the response
559
+ response_content = response_content.strip()
560
+
561
+ # Handle cases where the response might have extra text
562
+ if '```json' in response_content:
563
+ # Extract JSON from code block
564
+ start = response_content.find('```json') + 7
565
+ end = response_content.find('```', start)
566
+ if end == -1:
567
+ end = len(response_content)
568
+ json_str = response_content[start:end].strip()
569
+ elif response_content.startswith('{') and response_content.endswith('}'):
570
+ # Response is already JSON
571
+ json_str = response_content
572
+ else:
573
+ # Try to find JSON object in the response
574
+ import re
575
+ json_match = re.search(r'\{.*\}', response_content, re.DOTALL)
576
+ if json_match:
577
+ json_str = json_match.group(0)
578
+ else:
579
+ raise ValueError("No JSON object found in response")
580
+
581
+ # Parse JSON
582
+ parsed_data = json.loads(json_str)
583
+
584
+ # Convert to Pydantic model if schema is a BaseModel
585
+ if hasattr(self.schema, 'model_validate'):
586
+ # Pydantic v2
587
+ return self.schema.model_validate(parsed_data)
588
+ elif hasattr(self.schema, 'parse_obj'):
589
+ # Pydantic v1
590
+ return self.schema.parse_obj(parsed_data)
591
+ else:
592
+ # Dictionary schema - return parsed data
593
+ return parsed_data
594
+
595
+ except Exception as e:
596
+ # Fallback: return raw response if parsing fails
597
+ raise ValueError(f"Failed to parse structured output: {e}\nResponse: {response_content}")
598
+
599
+ def _messages_to_prompt(self, messages: List[BaseMessage]) -> str:
600
+ """Convert LangChain messages to a single prompt string with structured output instructions."""
601
+ # Get the original prompt
602
+ original_prompt = super()._messages_to_prompt(messages)
603
+
604
+ # Add structured output instructions
605
+ return self._create_structured_prompt(original_prompt)
606
+
607
+ def invoke(self, input, config=None, **kwargs):
608
+ """Invoke the model and return structured output."""
609
+ # Get the regular AI message response
610
+ response = super().invoke(input, config, **kwargs)
611
+
612
+ # Parse the response content into structured format
613
+ structured_result = self._parse_structured_response(response.content)
614
+
615
+ return structured_result
616
+
617
+ async def ainvoke(self, input, config=None, **kwargs):
618
+ """Async invoke the model and return structured output."""
619
+ # Get the regular AI message response
620
+ response = await super().ainvoke(input, config, **kwargs)
621
+
622
+ # Parse the response content into structured format
623
+ structured_result = self._parse_structured_response(response.content)
624
+
625
+ return structured_result
626
+
627
+
505
628
  class EuriaiEmbeddings(Embeddings):
506
629
  """
507
630
  Enhanced LangChain Embeddings implementation using Euri API.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: euriai
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Python client for Euri API (euron.one) with CLI, LangChain, and LlamaIndex integration
5
5
  Author: Euri
6
6
  Author-email: tech@euron.one
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = euriai
3
- version = 1.0.2
3
+ version = 1.0.3
4
4
  license = MIT
5
5
  description = Python client for EURI LLM API (euron.one) with CLI, LangChain, LlamaIndex, LangGraph, SmolAgents, and n8n integration
6
6
  keywords = euriai, llm, langchain, llamaindex, langgraph, smolagents, n8n, agents, ai, sdk
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  setup(
4
4
  name="euriai",
5
- version="1.0.2",
5
+ version="1.0.3",
6
6
  description="Python client for Euri API (euron.one) with CLI, LangChain, and LlamaIndex integration",
7
7
  long_description=open("README.md", encoding="utf-8").read(),
8
8
  long_description_content_type="text/markdown",
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes