lionagi 0.7.5__py3-none-any.whl → 0.7.7__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.
lionagi/__init__.py CHANGED
@@ -2,6 +2,8 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
+ from pydantic import BaseModel, Field
6
+
5
7
  from . import _types as types
6
8
  from .operations import types as op
7
9
  from .operatives import types as ops_types # deprecated
@@ -20,4 +22,6 @@ __all__ = (
20
22
  "ops_types",
21
23
  "op",
22
24
  "__version__",
25
+ "BaseModel",
26
+ "Field",
23
27
  )
@@ -387,10 +387,16 @@ async def translate_to_synthlang(
387
387
  calculator = TokenCalculator()
388
388
 
389
389
  len_tokens = calculator.tokenize(text, return_tokens=False)
390
- out = await branch.communicate(
390
+
391
+ kwargs["guidance"] = (
392
+ "Following SynthLang, translate the provided text into SynthLang syntax. "
393
+ "Shrink the token size by 60-85%. Return only the translated text.\n\n"
394
+ + kwargs.get("guidance", "")
395
+ )
396
+
397
+ out = await branch.chat(
391
398
  instruction=f"Converts the given text into SynthLang's hyper-efficient format.",
392
399
  context="Text to convert:\n\n" + text,
393
- guidance=f"Following SynthLang, translate the provided text into SynthLang syntax. Shrink the token size by 60-85%. Return only the translated text.",
394
400
  **kwargs,
395
401
  )
396
402
  if sys1:
@@ -13,6 +13,7 @@ async def interpret(
13
13
  text: str,
14
14
  domain: str | None = None,
15
15
  style: str | None = None,
16
+ sample_writing: str | None = None,
16
17
  **kwargs,
17
18
  ) -> str:
18
19
  instruction = (
@@ -25,14 +26,17 @@ async def interpret(
25
26
  f"Desired style: {style or 'concise'}. "
26
27
  "You can add or clarify context if needed."
27
28
  )
29
+ if sample_writing:
30
+ guidance += f" Sample writing: {sample_writing}"
31
+
28
32
  context = [f"User input: {text}"]
29
33
 
30
34
  # Default temperature if none provided
31
35
  kwargs["temperature"] = kwargs.get("temperature", 0.1)
36
+ kwargs["guidance"] = guidance + "\n" + kwargs.get("guidance", "")
32
37
 
33
38
  refined_prompt = await branch.chat(
34
39
  instruction=instruction,
35
- guidance=guidance,
36
40
  context=context,
37
41
  **kwargs,
38
42
  )
@@ -0,0 +1,22 @@
1
+ from typing import Callable
2
+
3
+ from lionagi.protocols._concepts import Manager
4
+
5
+ """
6
+ experimental
7
+ """
8
+
9
+
10
+ class OperationManager(Manager):
11
+
12
+ def __init__(self, *args, **kwargs):
13
+ super().__init__()
14
+ self.registry: dict[str, Callable] = {}
15
+ self.register_operations(*args, **kwargs)
16
+
17
+ def register_operations(self, *args, **kwargs) -> None:
18
+ operations = {}
19
+ if args:
20
+ operations = {i.__name__ for i in args if hasattr(i, "__name__")}
21
+ operations.update(kwargs)
22
+ self.registry.update(operations)
@@ -47,6 +47,9 @@ async def operate(
47
47
  actions: bool = False,
48
48
  reason: bool = False,
49
49
  action_kwargs: dict = None,
50
+ action_strategy: Literal[
51
+ "sequential", "concurrent", "batch"
52
+ ] = "concurrent",
50
53
  field_models: list[FieldModel] = None,
51
54
  exclude_fields: list | dict | None = None,
52
55
  request_params: ModelParams = None,
@@ -97,6 +100,8 @@ async def operate(
97
100
  instruct.reason = True
98
101
  if actions:
99
102
  instruct.actions = True
103
+ if action_strategy:
104
+ instruct.action_strategy = action_strategy
100
105
 
101
106
  # 1) Create or update the Operative
102
107
  operative = Step.request_operative(
@@ -178,9 +183,15 @@ async def operate(
178
183
  getattr(response_model, "action_required", None) is True
179
184
  and getattr(response_model, "action_requests", None) is not None
180
185
  ):
186
+ action_kwargs = action_kwargs or {}
187
+ action_kwargs["strategy"] = (
188
+ instruct.action_strategy
189
+ if instruct.action_strategy
190
+ else action_kwargs.get("strategy", "concurrent")
191
+ )
192
+
181
193
  action_response_models = await branch.act(
182
- response_model.action_requests,
183
- **(action_kwargs or {}),
194
+ response_model.action_requests, **action_kwargs
184
195
  )
185
196
  # Possibly refine the operative with the tool outputs
186
197
  operative = Step.respond_operative(
@@ -2,6 +2,8 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
+ """deprecated"""
6
+
5
7
  from pydantic import JsonValue
6
8
 
7
9
  from lionagi.libs.validate.common_field_validators import (
@@ -2,26 +2,23 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from typing import Any, ClassVar
5
+ from typing import Any, ClassVar, Literal
6
6
 
7
- from pydantic import JsonValue, field_validator
7
+ from pydantic import Field, JsonValue, field_validator
8
8
 
9
- from lionagi.utils import HashableModel
9
+ from lionagi.libs.validate.common_field_validators import (
10
+ validate_boolean_field,
11
+ validate_nullable_jsonvalue_field,
12
+ )
13
+ from lionagi.utils import HashableModel, to_num
10
14
 
11
15
  from ..models.field_model import FieldModel
12
- from .base import (
13
- ACTIONS_FIELD,
14
- CONTEXT_FIELD,
15
- GUIDANCE_FIELD,
16
- INSTRUCTION_FIELD,
17
- REASON_FIELD,
18
- )
19
16
 
20
17
  __all__ = (
21
18
  "Instruct",
22
19
  "InstructResponse",
23
20
  "INSTRUCT_FIELD",
24
- "LIST_INSTRUCT_FIELD_MODEL",
21
+ "LIST_INSTRUCT_FIELD",
25
22
  )
26
23
 
27
24
 
@@ -40,50 +37,101 @@ class Instruct(HashableModel):
40
37
  "operative",
41
38
  "reason",
42
39
  "actions",
40
+ "action_strategy",
41
+ "batch_size",
43
42
  "request_params",
44
43
  "response_params",
45
44
  ]
46
- instruction: JsonValue | None = INSTRUCTION_FIELD.field_info
47
- guidance: JsonValue | None = GUIDANCE_FIELD.field_info
48
- context: JsonValue | None = CONTEXT_FIELD.field_info
49
- reason: bool = REASON_FIELD.field_info
50
- actions: bool = ACTIONS_FIELD.field_info
51
-
52
- @field_validator("instruction", **INSTRUCTION_FIELD.validator_kwargs)
45
+ instruction: JsonValue | None = Field(
46
+ None,
47
+ title="Primary Instruction",
48
+ description=(
49
+ "A clear, actionable task definition. Specify:\n"
50
+ "1) The primary goal or objective\n"
51
+ "2) Key success criteria or constraints\n"
52
+ "\n"
53
+ "Guidelines:\n"
54
+ "- Start with a direct action verb (e.g., 'Analyze', 'Generate', 'Create')\n"
55
+ "- Include scope, boundaries, or constraints\n"
56
+ "- Provide success criteria if relevant\n"
57
+ "- For complex tasks, break them into logical steps"
58
+ ),
59
+ )
60
+ guidance: JsonValue | None = Field(
61
+ None,
62
+ title="Guidance",
63
+ description=(
64
+ "Strategic direction and constraints for executing the task. "
65
+ "Include:\n"
66
+ "1) Preferred methods or frameworks\n"
67
+ "2) Quality benchmarks (e.g., speed, clarity)\n"
68
+ "3) Resource or environmental constraints\n"
69
+ "4) Relevant compliance or standards\n"
70
+ "Use None if no special guidance."
71
+ ),
72
+ )
73
+ context: JsonValue | None = Field(
74
+ None,
75
+ description=(
76
+ "Background information and current-state data needed for the task. "
77
+ "Should be:\n"
78
+ "1) Directly relevant\n"
79
+ "2) Sufficient to perform the task\n"
80
+ "3) Free of extraneous detail\n"
81
+ "Include environment, prior outcomes, system states, or dependencies. "
82
+ "Use None if no additional context is needed."
83
+ ),
84
+ )
85
+ reason: bool | None = Field(
86
+ None,
87
+ description=(
88
+ "Include a thoughtful explanation of decisions, trade-offs, "
89
+ "and insights. Encourage deeper introspection on why certain "
90
+ "choices were made, potential alternatives, and how confidence "
91
+ "was shaped. If not needed, set to None."
92
+ ),
93
+ )
94
+ actions: bool | None = Field(
95
+ None,
96
+ description=(
97
+ "Controls execution mode. "
98
+ "True: Execute specified actions. "
99
+ "False: Analysis/recommendations only. "
100
+ "None: Contextual execution."
101
+ ),
102
+ )
103
+ action_strategy: Literal["batch", "sequential", "concurrent"] | None = (
104
+ Field(
105
+ None,
106
+ description="Action strategy to use for executing actions. Default "
107
+ "is 'concurrent'. Only provide for if actions are enabled.",
108
+ )
109
+ )
110
+ batch_size: int | None = Field(
111
+ None,
112
+ description="Batch size for executing actions. Only provide for 'batch' strategy.",
113
+ )
114
+
115
+ @field_validator("instruction", "guidance", "context", mode="before")
53
116
  def _validate_instruction(cls, v):
54
- """Field validator for the 'instruction' field.
55
-
56
- Args:
57
- v: The value to validate.
58
-
59
- Returns:
60
- JsonValue | None: The validated instruction value.
61
- """
62
- return INSTRUCTION_FIELD.validator(cls, v)
117
+ return validate_nullable_jsonvalue_field(cls, v)
63
118
 
64
- @field_validator("reason", **REASON_FIELD.validator_kwargs)
119
+ @field_validator("reason", "actions", mode="before")
65
120
  def _validate_reason(cls, v):
66
- """Field validator for the 'reason' field.
67
-
68
- Args:
69
- v: The value to validate.
70
-
71
- Returns:
72
- bool | None: The validated boolean value.
73
- """
74
- return REASON_FIELD.validator(cls, v)
75
-
76
- @field_validator("actions", **ACTIONS_FIELD.validator_kwargs)
77
- def _validate_actions(cls, v):
78
- """Field validator for the 'actions' field.
79
-
80
- Args:
81
- v: The value to validate.
82
-
83
- Returns:
84
- bool | None: The validated boolean value.
85
- """
86
- return ACTIONS_FIELD.validator(cls, v)
121
+ return validate_boolean_field(cls, v)
122
+
123
+ @field_validator("action_strategy", mode="before")
124
+ def _validate_action_strategy(cls, v):
125
+ if v not in ["batch", "sequential", "concurrent"]:
126
+ return "concurrent"
127
+ return v
128
+
129
+ @field_validator("batch_size", mode="before")
130
+ def _validate_batch_size(cls, v):
131
+ try:
132
+ return to_num(v, num_type=int)
133
+ except Exception:
134
+ return None
87
135
 
88
136
 
89
137
  INSTRUCT_FIELD = FieldModel(
@@ -2,6 +2,8 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
+ """deprecated"""
6
+
5
7
  instruction_field_description = (
6
8
  "A clear, actionable task definition. Specify:\n"
7
9
  "1) The primary goal or objective\n"
@@ -2,13 +2,19 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
 
5
- from pydantic import BaseModel, field_validator
5
+ from pydantic import BaseModel, Field, field_validator
6
6
 
7
7
  from lionagi.utils import to_num
8
8
 
9
9
  from ..models.field_model import FieldModel
10
10
 
11
+ __all__ = (
12
+ "Reason",
13
+ "REASON_FIELD",
14
+ )
15
+
11
16
 
17
+ # deprecated
12
18
  def validate_confidence_score(cls, value) -> float:
13
19
  try:
14
20
  return to_num(
@@ -22,6 +28,7 @@ def validate_confidence_score(cls, value) -> float:
22
28
  return -1
23
29
 
24
30
 
31
+ # deprecated
25
32
  confidence_description = (
26
33
  "Numeric confidence score (0.0 to 1.0, up to three decimals) indicating "
27
34
  "how well you've met user expectations. Use this guide:\n"
@@ -31,6 +38,7 @@ confidence_description = (
31
38
  " • 0.0-0.5: Off track"
32
39
  )
33
40
 
41
+ # deprecated
34
42
  CONFIDENCE_SCORE_FIELD = FieldModel(
35
43
  name="confidence_score",
36
44
  annotation=float | None,
@@ -47,13 +55,32 @@ class Reason(BaseModel):
47
55
 
48
56
  title: str | None = None
49
57
  content: str | None = None
50
- confidence_score: float | None = CONFIDENCE_SCORE_FIELD.field_info
51
-
52
- @field_validator(
53
- "confidence_score", **CONFIDENCE_SCORE_FIELD.validator_kwargs
58
+ confidence_score: float | None = Field(
59
+ None,
60
+ title="Confidence Score",
61
+ description=(
62
+ "Numeric confidence score (0.0 to 1.0, up to three decimals) indicating "
63
+ "how well you've met user expectations. Use this guide:\n"
64
+ " • 1.0: Highly confident\n"
65
+ " • 0.8-1.0: Reasonably sure\n"
66
+ " • 0.5-0.8: Re-check or refine\n"
67
+ " • 0.0-0.5: Off track"
68
+ ),
69
+ examples=[0.821, 0.257, 0.923, 0.439],
54
70
  )
71
+
72
+ @field_validator("confidence_score", mode="before")
55
73
  def _validate_confidence(cls, v):
56
- return CONFIDENCE_SCORE_FIELD.validator(cls, v)
74
+ try:
75
+ return to_num(
76
+ v,
77
+ upper_bound=1,
78
+ lower_bound=0,
79
+ num_type=float,
80
+ precision=3,
81
+ )
82
+ except Exception:
83
+ return -1
57
84
 
58
85
 
59
86
  REASON_FIELD = FieldModel(
@@ -62,6 +89,3 @@ REASON_FIELD = FieldModel(
62
89
  title="Reason",
63
90
  description="**Provide a concise reason for the decision made.**",
64
91
  )
65
-
66
-
67
- __all__ = ["Reason"]
@@ -11,50 +11,55 @@ def match_endpoint(
11
11
  endpoint: str,
12
12
  endpoint_params: list[str] | None = None,
13
13
  ) -> EndPoint:
14
- if endpoint not in ["chat/completions", "chat", "messages"]:
15
- raise ValueError(
16
- "Invalid endpoint, must be one of 'chat/completions' (openai compatible), 'chat' (an alias), 'messages' (anthropic), other endpoints are not supported yet"
14
+
15
+ if endpoint in ["chat/completions", "chat", "messages"]:
16
+ from ..providers.openai_.chat_completions import (
17
+ OpenAIChatCompletionEndPoint,
17
18
  )
18
- from ..providers.openai_.chat_completions import (
19
- OpenAIChatCompletionEndPoint,
20
- )
21
19
 
22
- if provider == "openai":
23
- return OpenAIChatCompletionEndPoint()
20
+ if provider == "openai":
21
+ return OpenAIChatCompletionEndPoint()
24
22
 
25
- if provider == "anthropic":
26
- from ..providers.anthropic_.messages import (
27
- AnthropicChatCompletionEndPoint,
28
- )
23
+ if provider == "anthropic":
24
+ from ..providers.anthropic_.messages import (
25
+ AnthropicChatCompletionEndPoint,
26
+ )
29
27
 
30
- return AnthropicChatCompletionEndPoint()
28
+ return AnthropicChatCompletionEndPoint()
31
29
 
32
- if provider == "groq":
33
- from ..providers.groq_.chat_completions import (
34
- GroqChatCompletionEndPoint,
35
- )
30
+ if provider == "groq":
31
+ from ..providers.groq_.chat_completions import (
32
+ GroqChatCompletionEndPoint,
33
+ )
36
34
 
37
- return GroqChatCompletionEndPoint()
35
+ return GroqChatCompletionEndPoint()
38
36
 
39
- if provider == "perplexity":
40
- from ..providers.perplexity_.chat_completions import (
41
- PerplexityChatCompletionEndPoint,
42
- )
37
+ if provider == "perplexity":
38
+ from ..providers.perplexity_.chat_completions import (
39
+ PerplexityChatCompletionEndPoint,
40
+ )
43
41
 
44
- return PerplexityChatCompletionEndPoint()
42
+ return PerplexityChatCompletionEndPoint()
45
43
 
46
- if provider == "openrouter":
47
- from ..providers.openrouter_.chat_completions import (
48
- OpenRouterChatCompletionEndPoint,
44
+ if provider == "openrouter":
45
+ from ..providers.openrouter_.chat_completions import (
46
+ OpenRouterChatCompletionEndPoint,
47
+ )
48
+
49
+ return OpenRouterChatCompletionEndPoint()
50
+
51
+ return OpenAIChatCompletionEndPoint(
52
+ config={
53
+ "provider": provider,
54
+ "base_url": base_url,
55
+ "endpoint": endpoint,
56
+ "endpoint_params": endpoint_params,
57
+ }
49
58
  )
50
59
 
51
- return OpenRouterChatCompletionEndPoint()
60
+ if provider == "exa" and endpoint == "search":
61
+ from ..providers.exa_.search import ExaSearchEndPoint
62
+
63
+ return ExaSearchEndPoint()
52
64
 
53
- return OpenAIChatCompletionEndPoint(
54
- config={
55
- "provider": provider,
56
- "base_url": base_url,
57
- "endpoint": endpoint,
58
- "endpoint_params": endpoint_params,
59
- }
60
- )
65
+ raise ValueError(f"Unsupported endpoint: {endpoint}")
lionagi/service/imodel.py CHANGED
@@ -102,6 +102,8 @@ class iModel:
102
102
  api_key = "PERPLEXITY_API_KEY"
103
103
  case "groq":
104
104
  api_key = "GROQ_API_KEY"
105
+ case "exa":
106
+ api_key = "EXA_API_KEY"
105
107
 
106
108
  if os.getenv(api_key, None) is not None:
107
109
  self.api_key_scheme = api_key
@@ -198,7 +200,9 @@ class iModel:
198
200
  except Exception as e:
199
201
  raise ValueError(f"Failed to stream API call: {e}")
200
202
 
201
- async def invoke(self, **kwargs) -> APICalling | None:
203
+ async def invoke(
204
+ self, api_call: APICalling = None, **kwargs
205
+ ) -> APICalling | None:
202
206
  """Invokes a rate-limited API call with the given arguments.
203
207
 
204
208
  Args:
@@ -215,8 +219,9 @@ class iModel:
215
219
  If the call fails or if an error occurs during invocation.
216
220
  """
217
221
  try:
218
- kwargs.pop("stream", None)
219
- api_call = self.create_api_calling(**kwargs)
222
+ if api_call is None:
223
+ kwargs.pop("stream", None)
224
+ api_call = self.create_api_calling(**kwargs)
220
225
  if (
221
226
  self.executor.processor is None
222
227
  or self.executor.processor.is_stopped()
@@ -252,6 +257,15 @@ class iModel:
252
257
  """
253
258
  return self.endpoint.sequential_exchange
254
259
 
260
+ @property
261
+ def model_name(self) -> str:
262
+ """str: The name of the model used by the endpoint.
263
+
264
+ Returns:
265
+ The model name if available; otherwise, an empty string.
266
+ """
267
+ return self.kwargs.get("model", "")
268
+
255
269
  def to_dict(self):
256
270
  kwargs = self.kwargs
257
271
  if "kwargs" in self.kwargs:
File without changes
@@ -0,0 +1,160 @@
1
+ from enum import Enum
2
+
3
+ from pydantic import BaseModel, Field
4
+
5
+
6
+ class CategoryEnum(str, Enum):
7
+ company = "company"
8
+ research_paper = "research paper"
9
+ news = "news"
10
+ pdf = "pdf"
11
+ github = "github"
12
+ tweet = "tweet"
13
+ personal_site = "personal site"
14
+ linkedin_profile = "linkedin profile"
15
+ financial_report = "financial report"
16
+
17
+
18
+ class LivecrawlEnum(str, Enum):
19
+ never = "never"
20
+ fallback = "fallback"
21
+ always = "always"
22
+
23
+
24
+ class SearchTypeEnum(str, Enum):
25
+ keyword = "keyword"
26
+ neural = "neural"
27
+ auto = "auto"
28
+
29
+
30
+ class ContentsText(BaseModel):
31
+ includeHtmlTags: bool | None = Field(
32
+ default=False,
33
+ description="Whether to include HTML tags in the text. Set to True if you want to retain HTML structure for the LLM to interpret.",
34
+ )
35
+ maxCharacters: int | None = Field(
36
+ default=None,
37
+ description="The maximum number of characters to return from the webpage text.",
38
+ )
39
+
40
+
41
+ class ContentsHighlights(BaseModel):
42
+ highlightsPerUrl: int | None = Field(
43
+ default=1,
44
+ description="The number of highlight snippets you want per page.",
45
+ )
46
+ numSentences: int | None = Field(
47
+ default=5,
48
+ description="Number of sentences to return in each highlight snippet.",
49
+ )
50
+ query: None | str = Field(
51
+ default=None,
52
+ description="A specific query used to generate the highlight snippets.",
53
+ )
54
+
55
+
56
+ class ContentsSummary(BaseModel):
57
+ query: None | str = Field(
58
+ default=None,
59
+ description="A specific query used to generate a summary of the webpage.",
60
+ )
61
+
62
+
63
+ class ContentsExtras(BaseModel):
64
+ links: int | None = Field(
65
+ default=None, description="Number of links to return from each page."
66
+ )
67
+ imageLinks: int | None = Field(
68
+ default=None, description="Number of images to return for each result."
69
+ )
70
+
71
+
72
+ class Contents(BaseModel):
73
+ text: None | ContentsText = Field(
74
+ default=None,
75
+ description="Return full or partial text for each page, with optional HTML structure or size limit.",
76
+ )
77
+ highlights: None | ContentsHighlights = Field(
78
+ default=None, description="Return snippet highlights for each page."
79
+ )
80
+ summary: None | ContentsSummary = Field(
81
+ default=None, description="Return a short summary of each page."
82
+ )
83
+ livecrawl: None | LivecrawlEnum = Field(
84
+ default=LivecrawlEnum.never,
85
+ description="Livecrawling setting for each page. Options: never, fallback, always.",
86
+ )
87
+ livecrawlTimeout: int | None = Field(
88
+ default=10000,
89
+ description="Timeout in milliseconds for livecrawling. Default 10000.",
90
+ )
91
+ subpages: int | None = Field(
92
+ default=None,
93
+ description="Number of subpages to crawl within each URL.",
94
+ )
95
+ subpageTarget: None | str | list[str] = Field(
96
+ default=None,
97
+ description="A target subpage or multiple subpages (list) to crawl, e.g. 'cited papers'.",
98
+ )
99
+ extras: None | ContentsExtras = Field(
100
+ default=None,
101
+ description="Additional extras like links or images to return for each page.",
102
+ )
103
+
104
+
105
+ class ExaSearchRequest(BaseModel):
106
+ query: str = Field(
107
+ ...,
108
+ description="The main query string describing what you're looking for.",
109
+ )
110
+ category: None | CategoryEnum = Field(
111
+ default=None,
112
+ description="A data category to focus on, such as 'company', 'research paper', 'news', etc.",
113
+ )
114
+ type: None | SearchTypeEnum = Field(
115
+ default=None,
116
+ description="The type of search to run. Can be 'auto', 'keyword', or 'neural'.",
117
+ )
118
+ useAutoprompt: None | bool = Field(
119
+ default=False,
120
+ description="If True, Exa auto-optimizes your query for best results (neural or auto search only).",
121
+ )
122
+ numResults: int | None = Field(
123
+ default=10, description="Number of results to return. Default is 10."
124
+ )
125
+ includeDomains: None | list[str] = Field(
126
+ default=None,
127
+ description="List of domains you want to include exclusively.",
128
+ )
129
+ excludeDomains: None | list[str] = Field(
130
+ default=None,
131
+ description="List of domains you do NOT want to see in the results.",
132
+ )
133
+ startCrawlDate: None | str = Field(
134
+ default=None,
135
+ description="Include results crawled after this ISO date (e.g., '2023-01-01T00:00:00.000Z').",
136
+ )
137
+ endCrawlDate: None | str = Field(
138
+ default=None,
139
+ description="Include results crawled before this ISO date.",
140
+ )
141
+ startPublishedDate: None | str = Field(
142
+ default=None,
143
+ description="Only return results published after this ISO date.",
144
+ )
145
+ endPublishedDate: None | str = Field(
146
+ default=None,
147
+ description="Only return results published before this ISO date.",
148
+ )
149
+ includeText: None | list[str] = Field(
150
+ default=None,
151
+ description="Strings that must appear in the webpage text. Only a single string up to 5 words is currently supported.",
152
+ )
153
+ excludeText: None | list[str] = Field(
154
+ default=None,
155
+ description="Strings that must NOT appear in the webpage text. Only a single string up to 5 words is currently supported.",
156
+ )
157
+ contents: None | Contents = Field(
158
+ default=None,
159
+ description="Dict defining the different ways you want to retrieve webpage contents, including text, highlights, or summaries.",
160
+ )
@@ -0,0 +1,80 @@
1
+ from typing import TYPE_CHECKING, Literal
2
+
3
+ from lionagi.service.endpoints.base import EndPoint
4
+
5
+ if TYPE_CHECKING:
6
+ from .models import ExaSearchRequest
7
+
8
+
9
+ CATEGORY_OPTIONS = Literal[
10
+ "article",
11
+ "book",
12
+ "company",
13
+ "research paper",
14
+ "news",
15
+ "pdf",
16
+ "github",
17
+ "tweet",
18
+ "personal site",
19
+ "linkedin profile",
20
+ "financial report",
21
+ ]
22
+
23
+ SEARCH_CONFIG = {
24
+ "provider": "exa",
25
+ "base_url": "https://api.exa.ai",
26
+ "endpoint": "search",
27
+ "method": "post",
28
+ "openai_compatible": False,
29
+ "is_invokeable": False,
30
+ "requires_tokens": False,
31
+ "is_streamable": False,
32
+ "required_kwargs": {
33
+ "query",
34
+ },
35
+ "optional_kwargs": {
36
+ "category",
37
+ "contents",
38
+ "endCrawlDate",
39
+ "endPublishedDate",
40
+ "excludeDomains",
41
+ "excludeText",
42
+ "includeDomains",
43
+ "includeText",
44
+ "numResults",
45
+ "startCrawlDate",
46
+ "startPublishedDate",
47
+ "type", # keyword, neural, auto
48
+ "useAutoPrompt",
49
+ },
50
+ }
51
+
52
+
53
+ class ExaSearchEndPoint(EndPoint):
54
+
55
+ def __init__(self, config: dict = SEARCH_CONFIG):
56
+ super().__init__(config)
57
+
58
+ def create_payload(
59
+ self, request_obj: "ExaSearchRequest" = None, **kwargs
60
+ ) -> dict:
61
+ if request_obj is not None:
62
+ kwargs.update(request_obj.to_dict(exclude_none=True))
63
+
64
+ payload = {}
65
+ is_cached = kwargs.get("is_cached", False)
66
+ headers = kwargs.get("headers", {})
67
+
68
+ for k, v in kwargs.items():
69
+ if k in self.acceptable_kwargs:
70
+ payload[k] = v
71
+ if "api_key" in kwargs:
72
+ headers["x-api-key"] = kwargs["api_key"]
73
+ if "content-type" not in kwargs:
74
+ headers["content-type"] = "application/json"
75
+
76
+ return {
77
+ "payload": payload,
78
+ "headers": headers,
79
+ "is_cached": is_cached,
80
+ }
@@ -0,0 +1,7 @@
1
+ from .models import ExaSearchRequest
2
+ from .search import ExaSearchEndPoint
3
+
4
+ __all__ = (
5
+ "ExaSearchRequest",
6
+ "ExaSearchEndPoint",
7
+ )
@@ -0,0 +1,17 @@
1
+ from .anthropic_.messages import AnthropicChatCompletionEndPoint
2
+ from .exa_.models import ExaSearchRequest
3
+ from .exa_.search import ExaSearchEndPoint
4
+ from .groq_.chat_completions import GroqChatCompletionEndPoint
5
+ from .openai_.chat_completions import OpenAIChatCompletionEndPoint
6
+ from .openrouter_.chat_completions import OpenRouterChatCompletionEndPoint
7
+ from .perplexity_.chat_completions import PerplexityChatCompletionEndPoint
8
+
9
+ __all__ = (
10
+ "AnthropicChatCompletionEndPoint",
11
+ "ExaSearchEndPoint",
12
+ "ExaSearchRequest",
13
+ "GroqChatCompletionEndPoint",
14
+ "OpenAIChatCompletionEndPoint",
15
+ "OpenRouterChatCompletionEndPoint",
16
+ "PerplexityChatCompletionEndPoint",
17
+ )
lionagi/session/branch.py CHANGED
@@ -47,7 +47,7 @@ from lionagi.protocols.types import (
47
47
  )
48
48
  from lionagi.service.types import iModel, iModelManager
49
49
  from lionagi.settings import Settings
50
- from lionagi.utils import UNDEFINED, alcall, copy
50
+ from lionagi.utils import UNDEFINED, alcall, bcall, copy
51
51
 
52
52
  if TYPE_CHECKING:
53
53
  # Forward references for type checking (e.g., in operations or extended modules)
@@ -1103,6 +1103,8 @@ class Branch(Element, Communicatable, Relational):
1103
1103
  self,
1104
1104
  action_request: list | ActionRequest | BaseModel | dict,
1105
1105
  *,
1106
+ strategy: Literal["concurrent", "sequential", "batch"] = "concurrent",
1107
+ batch_size: int = None,
1106
1108
  suppress_errors: bool = True,
1107
1109
  sanitize_input: bool = False,
1108
1110
  unique_input: bool = False,
@@ -1119,7 +1121,7 @@ class Branch(Element, Communicatable, Relational):
1119
1121
  dropna: bool = True,
1120
1122
  unique_output: bool = False,
1121
1123
  flatten_tuple_set: bool = False,
1122
- ) -> list[ActionResponse] | ActionResponse | Any:
1124
+ ) -> list[ActionResponse]:
1123
1125
  """
1124
1126
  Public, potentially batched, asynchronous interface to run one or multiple action requests.
1125
1127
 
@@ -1164,10 +1166,95 @@ class Branch(Element, Communicatable, Relational):
1164
1166
  Any:
1165
1167
  The result or results from the invoked tool(s).
1166
1168
  """
1167
- params = locals()
1168
- params.pop("self")
1169
- params.pop("action_request")
1170
- return await alcall(action_request, self._act, **params)
1169
+ if batch_size and not strategy == "batch":
1170
+ raise ValueError(
1171
+ "Batch size is only applicable for 'batch' strategy."
1172
+ )
1173
+
1174
+ match strategy:
1175
+ case "concurrent":
1176
+ return await self._concurrent_act(
1177
+ action_request,
1178
+ suppress_errors=suppress_errors,
1179
+ sanitize_input=sanitize_input,
1180
+ unique_input=unique_input,
1181
+ num_retries=num_retries,
1182
+ initial_delay=initial_delay,
1183
+ retry_delay=retry_delay,
1184
+ backoff_factor=backoff_factor,
1185
+ retry_default=retry_default,
1186
+ retry_timeout=retry_timeout,
1187
+ retry_timing=retry_timing,
1188
+ max_concurrent=max_concurrent,
1189
+ throttle_period=throttle_period,
1190
+ flatten=flatten,
1191
+ dropna=dropna,
1192
+ unique_output=unique_output,
1193
+ flatten_tuple_set=flatten_tuple_set,
1194
+ )
1195
+ case "sequential":
1196
+ return await self._sequential_act(
1197
+ action_request,
1198
+ suppress_errors=suppress_errors,
1199
+ )
1200
+ case "batch":
1201
+ return await self._batch_act(
1202
+ action_request,
1203
+ batch_size=batch_size or 1,
1204
+ max_concurrent=max_concurrent,
1205
+ suppress_errors=suppress_errors,
1206
+ sanitize_input=sanitize_input,
1207
+ unique_input=unique_input,
1208
+ num_retries=num_retries,
1209
+ initial_delay=initial_delay,
1210
+ retry_delay=retry_delay,
1211
+ backoff_factor=backoff_factor,
1212
+ retry_default=retry_default,
1213
+ retry_timeout=retry_timeout,
1214
+ retry_timing=retry_timing,
1215
+ throttle_period=throttle_period,
1216
+ flatten=flatten,
1217
+ dropna=dropna,
1218
+ unique_output=unique_output,
1219
+ flatten_tuple_set=flatten_tuple_set,
1220
+ )
1221
+
1222
+ async def _concurrent_act(
1223
+ self,
1224
+ action_request: ActionRequest | BaseModel | dict,
1225
+ **kwargs,
1226
+ ) -> list:
1227
+ return await alcall(action_request, self._act, **kwargs)
1228
+
1229
+ async def _sequential_act(
1230
+ self,
1231
+ action_request: ActionRequest | BaseModel | dict,
1232
+ suppress_errors: bool = True,
1233
+ ) -> list:
1234
+ action_request = (
1235
+ action_request
1236
+ if isinstance(action_request, list)
1237
+ else [action_request]
1238
+ )
1239
+ results = []
1240
+ for req in action_request:
1241
+ results.append(
1242
+ await self._act(req, suppress_errors=suppress_errors)
1243
+ )
1244
+ return results
1245
+
1246
+ async def _batch_act(
1247
+ self,
1248
+ action_request: list[ActionRequest | BaseModel | dict],
1249
+ batch_size: int = None,
1250
+ **kwargs,
1251
+ ) -> list:
1252
+ result = []
1253
+ async for i in await bcall(
1254
+ action_request, self._act, batch_size=batch_size, **kwargs
1255
+ ):
1256
+ result.extend(i)
1257
+ return result
1171
1258
 
1172
1259
  async def translate(
1173
1260
  self,
lionagi/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.7.5"
1
+ __version__ = "0.7.7"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lionagi
3
- Version: 0.7.5
3
+ Version: 0.7.7
4
4
  Summary: An Intelligence Operating System.
5
5
  Author-email: HaiyangLi <quantocean.li@gmail.com>
6
6
  License: Apache License
@@ -214,6 +214,7 @@ Classifier: License :: OSI Approved :: Apache Software License
214
214
  Classifier: Operating System :: OS Independent
215
215
  Classifier: Programming Language :: Python :: 3
216
216
  Classifier: Programming Language :: Python :: 3 :: Only
217
+ Classifier: Programming Language :: Python :: 3.10
217
218
  Classifier: Programming Language :: Python :: 3.11
218
219
  Classifier: Programming Language :: Python :: 3.12
219
220
  Classifier: Programming Language :: Python :: 3.13
@@ -1,10 +1,10 @@
1
- lionagi/__init__.py,sha256=Z_cWmXAAYFrUDQsB9xJR8SqCrc7fKShllJFQd1N11BI,505
1
+ lionagi/__init__.py,sha256=-tKLn-wTj_VK4XQr3CV16ioTNnaUYD2fhUAtJOZZ0vU,574
2
2
  lionagi/_class_registry.py,sha256=dutMsw-FQNqVV5gGH-NEIv90uBkSr8fERJ_x3swbb-s,3112
3
3
  lionagi/_errors.py,sha256=wNKdnVQvE_CHEstK7htrrj334RA_vbGcIds-3pUiRkc,455
4
4
  lionagi/_types.py,sha256=9g7iytvSj3UjZxD-jL06_fxuNfgZyWT3Qnp0XYp1wQU,63
5
5
  lionagi/settings.py,sha256=k9zRJXv57TveyfHO3Vr9VGiKrSwlRUUVKt5zf6v9RU4,1627
6
6
  lionagi/utils.py,sha256=X12H-O8Lx9tUOKGtjpoxHjRsKYHRqty0qD9i2W12kpI,73121
7
- lionagi/version.py,sha256=6qL_qyowXO9Pc6v11Zx2s-yd28_548ZZC-OsfzO_Pjc,22
7
+ lionagi/version.py,sha256=eOm8myGPtPLNpkuxL0xhVmstPQbwXv3Ok7FbH0re-TA,22
8
8
  lionagi/libs/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
9
9
  lionagi/libs/parse.py,sha256=tpEbmIRGuHhLCJlUlm6fjmqm_Z6XJLAXGNFHNuk422I,1011
10
10
  lionagi/libs/file/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
@@ -37,7 +37,7 @@ lionagi/libs/schema/json_schema.py,sha256=Z45azAI_7lr5BWj-X6VQwUhuvuqXibciXgla8w
37
37
  lionagi/libs/token_transform/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
38
  lionagi/libs/token_transform/llmlingua.py,sha256=DkeLUlrb7rGx3nZ04aADU9HXXu5mZTf_DBwT0xhzIv4,7
39
39
  lionagi/libs/token_transform/perplexity.py,sha256=XX-RoqGbeVYSl7fG1T_hF3I2pCAJ0A1LSKkrUpqsbeI,14091
40
- lionagi/libs/token_transform/synthlang.py,sha256=dD2JD0WCB0xLMF2PG8nJluJXEQ6VSTyqmTnmrFm9IgU,12709
40
+ lionagi/libs/token_transform/synthlang.py,sha256=xQYbpKIX5T7mK9PoBFikJGB8dp18JlLHdwpFhrIRMgQ,12778
41
41
  lionagi/libs/validate/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
42
42
  lionagi/libs/validate/common_field_validators.py,sha256=5pu3kH13dVy1Nq-AQcHx0bIPusOnhvvCwUmaBX5l8bw,4778
43
43
  lionagi/libs/validate/fuzzy_match_keys.py,sha256=S7kzJnh-aKDMFbecmtMjFHNk2h-xMJqtQygMnq839lY,6255
@@ -45,6 +45,7 @@ lionagi/libs/validate/fuzzy_validate_mapping.py,sha256=SQqyxgrAgJ5zBKxIAnulWsZXb
45
45
  lionagi/libs/validate/string_similarity.py,sha256=7x8D4LZCMNJGz2ZCeKmct7Nc4i8m_ORoHIeGvkeMZOA,8733
46
46
  lionagi/libs/validate/validate_boolean.py,sha256=h3d7Dn7asJokBozWaKxaV_3Y6vUWBc0-zfNJjTQ9Bo8,3614
47
47
  lionagi/operations/__init__.py,sha256=O7nV0tedpUe7_OlUWmCcduGPFtqtzWZcR_SIOnjLsro,134
48
+ lionagi/operations/manager.py,sha256=qjDMSOJ35XjDXkVq0SlEb4inTS7OXGwxly2doiQCNas,556
48
49
  lionagi/operations/types.py,sha256=LIa68xcyKLVafof-DSFwKtSkneuYPFqrtGyClohYI6o,704
49
50
  lionagi/operations/utils.py,sha256=Twy6L_UFt9JqJFRYuKKTKVZIXsePidNl5ipcYcCbesI,1220
50
51
  lionagi/operations/ReAct/ReAct.py,sha256=tAZ-3Ya68tVUa112wgOMUJpBVw-RWBSYTfgicbInRuQ,3954
@@ -62,9 +63,9 @@ lionagi/operations/communicate/communicate.py,sha256=1PzBpzgATcAdBog0EUxtj5_uJGi
62
63
  lionagi/operations/instruct/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
63
64
  lionagi/operations/instruct/instruct.py,sha256=CYICzWvmgALtSPIetfF3csx6WDsCuiu4NRRPL56UA2g,795
64
65
  lionagi/operations/interpret/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
65
- lionagi/operations/interpret/interpret.py,sha256=EtgXTeOezEPR03HSUVz8PGK-xf8p2nXoUMUhFkAntK0,1081
66
+ lionagi/operations/interpret/interpret.py,sha256=mjTcOCOixc34JNnX0WowSVACtZXz9IBuzjp9VyOus5w,1244
66
67
  lionagi/operations/operate/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
67
- lionagi/operations/operate/operate.py,sha256=jgVV9CjtnVLmR5ZdDmunicS5Pp9dT3hV5kMEBuk16iI,6614
68
+ lionagi/operations/operate/operate.py,sha256=kzH7R4J3O-1Ue-PYqIoEdrXHrkYYQVfHa6gSC4Km_sc,7003
68
69
  lionagi/operations/parse/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
69
70
  lionagi/operations/parse/parse.py,sha256=LpF6LVAvCVoE8n63BkhSxXSHYgSx7CNkN7yXUwaNpQo,3003
70
71
  lionagi/operations/plan/__init__.py,sha256=AFkAmOJBTqPlYuqFRRn7rCvIw3CGh9XXH_22cNWbfig,156
@@ -92,12 +93,12 @@ lionagi/operatives/forms/form.py,sha256=5z5VfDqcKVFYvhDVZZQwMDczSof2lSx_VxQo32jl
92
93
  lionagi/operatives/forms/report.py,sha256=KUapeSAB67ElyU1fl4DxtfvobKGnpDPetso6cT6GT4E,11167
93
94
  lionagi/operatives/forms/utils.py,sha256=sCjYRy-EJIh1py9qIb04LVgALy2YiPHbhXhNyDNwvoQ,701
94
95
  lionagi/operatives/instruct/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
95
- lionagi/operatives/instruct/base.py,sha256=dyw5JZw0o1FCm4KQqeSvYGaO75ReHQQ-xOyPjgOdfJM,1877
96
- lionagi/operatives/instruct/instruct.py,sha256=kRKc-OGcY4nSMqTTR7uUjMFBJpYcBfKv8iiEmpKAp0s,2674
96
+ lionagi/operatives/instruct/base.py,sha256=Vw9u3BGzjNRGcPfW1ROr2uCZcZsjrm4WU6491P6ecCI,1895
97
+ lionagi/operatives/instruct/instruct.py,sha256=vzIQks5gSXJQzdEE_l4PgJPw2ZUZPbAfZ-cDt6CPmeQ,4794
97
98
  lionagi/operatives/instruct/instruct_collection.py,sha256=Fj7R7TR33PdkqzbWhev52jKeIMmEQ1q227Bu4zsrHiA,1449
98
99
  lionagi/operatives/instruct/node.py,sha256=0g7g2jsLO8L8VlD-L1mFmjcFTwWy39moWCDtLNmNEFY,317
99
- lionagi/operatives/instruct/prompts.py,sha256=g16IooxpAJfNvv1jdRe7nLQ28mO9UezRS2SDQE8Lnus,1729
100
- lionagi/operatives/instruct/reason.py,sha256=1DYviNf5D_3DH0lnguXYGEyFycYzRjoyLob-BnIpmSA,1679
100
+ lionagi/operatives/instruct/prompts.py,sha256=RG8rB7Y0J17aTHTb9kTTHxltVjgRAuC4vjM9B1_hTuQ,1747
101
+ lionagi/operatives/instruct/reason.py,sha256=mdCMBO3YSWYncXU_B1bYuZqpkj4pfUMsxsz9vXXAMw4,2341
101
102
  lionagi/operatives/models/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
102
103
  lionagi/operatives/models/field_model.py,sha256=yfRRBbfQ5llPGIt_QkyLrIrmNwNQ14aUXA-llHeER4M,6083
103
104
  lionagi/operatives/models/model_params.py,sha256=UnugiT0GDFzB9igYeCvN6pcq01bqTpZuAHom0yCBSdk,9653
@@ -160,18 +161,23 @@ lionagi/protocols/messages/templates/instruction_message.jinja2,sha256=L-ptw5OHx
160
161
  lionagi/protocols/messages/templates/system_message.jinja2,sha256=JRKJ0aFpYfaXSFouKc_N4unZ35C3yZTOWhIrIdCB5qk,215
161
162
  lionagi/protocols/messages/templates/tool_schemas.jinja2,sha256=ozIaSDCRjIAhLyA8VM6S-YqS0w2NcctALSwx4LjDwII,126
162
163
  lionagi/service/__init__.py,sha256=DMGXIqPsmut9H5GT0ZeSzQIzYzzPwI-2gLXydpbwiV8,21
163
- lionagi/service/imodel.py,sha256=MaiBcKM00vH0tq0nD_C7jV6S7OyV71a4YwVDrDfPMrA,11539
164
+ lionagi/service/imodel.py,sha256=Mv5wVsmZj4hYmrvXfHVmA-fskfAKrDY0mbdmgOCAGoE,11946
164
165
  lionagi/service/manager.py,sha256=MKSYBkg23s7YhZy5GEFdnpspEnhPVfFhpkpoJe20D7k,1435
165
166
  lionagi/service/types.py,sha256=v9SAn5-GTmds4Mar13Or_VFrRHCinBK99dmeDUd-QNk,486
166
167
  lionagi/service/endpoints/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
167
168
  lionagi/service/endpoints/base.py,sha256=RbBBQIbtNtkP1LT9U3ZrhL35SfmVIpaq-AGW8d538k4,18275
168
169
  lionagi/service/endpoints/chat_completion.py,sha256=9ltSQaKPH43WdEDW32_-f5x07I9hOU8g-T_PAG-nYsQ,2529
169
- lionagi/service/endpoints/match_endpoint.py,sha256=n7F9NoTXfUBL29HrDcFLF5AXYR8pcx_IumQ7BiJXC-w,1740
170
+ lionagi/service/endpoints/match_endpoint.py,sha256=hIGYyok1y53FfI6av5NfYMygRIpDWYZbdCj0pJJfmPY,1874
170
171
  lionagi/service/endpoints/rate_limited_processor.py,sha256=umri0FofbyBSFdAQBEsviDB5K6N12LkRiXQgSOorGKg,4663
171
172
  lionagi/service/endpoints/token_calculator.py,sha256=MflqImGUr_1jh465hB7cUAaIPICBkjirvre1fWGXLrA,6161
172
173
  lionagi/service/providers/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
174
+ lionagi/service/providers/types.py,sha256=NS91ysRFwOs0cpNeQgFhmtl7JrSz2pJm-tt7sZILmQY,683
173
175
  lionagi/service/providers/anthropic_/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
174
176
  lionagi/service/providers/anthropic_/messages.py,sha256=PTZZ2VXVMRHWY84YFIzrft9gVrcH2V-NIq_Phi9_-xI,1760
177
+ lionagi/service/providers/exa_/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
178
+ lionagi/service/providers/exa_/models.py,sha256=263KP-JSxbxmomNrFeYjB_cebquoMOsCJeWsiKZ0mL4,5420
179
+ lionagi/service/providers/exa_/search.py,sha256=Z9bOxTjPZbtI_qH4fSePYKSXhkc8N3ZFbCHdsml8YSA,1903
180
+ lionagi/service/providers/exa_/types.py,sha256=8ODjXpFajBE9-DGqBJNS--GObwmLSDi667xS84z_AgA,139
175
181
  lionagi/service/providers/groq_/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
176
182
  lionagi/service/providers/groq_/chat_completions.py,sha256=578NqQYyrIYjIemyL3bagvFGE6ear_w4S1HNlPWA5mg,1343
177
183
  lionagi/service/providers/openai_/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
@@ -181,9 +187,9 @@ lionagi/service/providers/openrouter_/chat_completions.py,sha256=MRf4ZbMCgzNIL4g
181
187
  lionagi/service/providers/perplexity_/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
182
188
  lionagi/service/providers/perplexity_/chat_completions.py,sha256=SsDbrtXwQsR4Yu2VMU43KfeS86QWI8UTNhDth5lNWNs,1055
183
189
  lionagi/session/__init__.py,sha256=v8vNyJVIVj8_Oz9RJdVe6ZKUQMYTgDh1VQpnr1KdLaw,112
184
- lionagi/session/branch.py,sha256=2KMMl-YVVfbgbz1qtyXpw3SrRZ5yAfoqm44s-gnbjyU,59319
190
+ lionagi/session/branch.py,sha256=JvErd9YUuGdWyLj37rtKOteSqV0ltn9lg0R2G8GO40c,62539
185
191
  lionagi/session/session.py,sha256=po6C7PnM0iu_ISHUo4PBzzQ61HFOgcsAUfPoO--eLak,8987
186
- lionagi-0.7.5.dist-info/METADATA,sha256=BzOxAvQTuo7KixBKczhR3Ne6LPcWNDo1zOV36Y0fZo4,22768
187
- lionagi-0.7.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
188
- lionagi-0.7.5.dist-info/licenses/LICENSE,sha256=VXFWsdoN5AAknBCgFqQNgPWYx7OPp-PFEP961zGdOjc,11288
189
- lionagi-0.7.5.dist-info/RECORD,,
192
+ lionagi-0.7.7.dist-info/METADATA,sha256=XzhIG5ZehXeF7UXYkd4dvIuqT1W8E969aAOliftxmJU,22819
193
+ lionagi-0.7.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
194
+ lionagi-0.7.7.dist-info/licenses/LICENSE,sha256=VXFWsdoN5AAknBCgFqQNgPWYx7OPp-PFEP961zGdOjc,11288
195
+ lionagi-0.7.7.dist-info/RECORD,,