vulcan-core 1.0.0__py3-none-any.whl → 1.1.0__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.

Potentially problematic release.


This version of vulcan-core might be problematic. Click here for more details.

vulcan_core/ast_utils.py CHANGED
@@ -152,16 +152,35 @@ class ASTProcessor[T: Callable]:
152
152
  raise ASTProcessingError(msg)
153
153
 
154
154
  # The source includes the entire line of code (e.g., assignment and condition() call)
155
- # We need to parse parentheses to extract just the lambda expression, handling any
156
- # nested parentheses in the lambda's body correctly
155
+ # We need to extract just the lambda expression, handling nested structures correctly
157
156
  source = self.source[lambda_start:]
157
+
158
+ # Track depth of various brackets to ensure we don't split inside valid nested structures apart from trailing
159
+ # arguments within the condition() call
158
160
  paren_level = 0
161
+ bracket_level = 0
162
+ brace_level = 0
163
+
159
164
  for i, char in enumerate(source):
160
165
  if char == "(":
161
166
  paren_level += 1
162
- elif char == ")" and paren_level > 0:
163
- paren_level -= 1
164
- elif char == ")" and paren_level == 0:
167
+ elif char == ")":
168
+ if paren_level > 0:
169
+ paren_level -= 1
170
+ elif paren_level == 0: # End of expression in a function call
171
+ return source[:i]
172
+ elif char == "[":
173
+ bracket_level += 1
174
+ elif char == "]":
175
+ if bracket_level > 0:
176
+ bracket_level -= 1
177
+ elif char == "{":
178
+ brace_level += 1
179
+ elif char == "}":
180
+ if brace_level > 0:
181
+ brace_level -= 1
182
+ # Only consider comma as a separator when not inside any brackets
183
+ elif char == "," and paren_level == 0 and bracket_level == 0 and brace_level == 0:
165
184
  return source[:i]
166
185
 
167
186
  return source
vulcan_core/conditions.py CHANGED
@@ -8,11 +8,11 @@ import re
8
8
  from abc import abstractmethod
9
9
  from dataclasses import dataclass, field
10
10
  from enum import Enum, auto
11
+ from functools import lru_cache
11
12
  from string import Formatter
12
13
  from typing import TYPE_CHECKING
13
14
 
14
15
  from langchain.prompts import ChatPromptTemplate
15
- from langchain_openai import ChatOpenAI
16
16
  from pydantic import BaseModel, Field
17
17
 
18
18
  from vulcan_core.actions import ASTProcessor
@@ -22,6 +22,11 @@ if TYPE_CHECKING: # pragma: no cover - not used at runtime
22
22
  from langchain_core.language_models import BaseChatModel
23
23
  from langchain_core.runnables import RunnableSerializable
24
24
 
25
+ import importlib.util
26
+ import logging
27
+
28
+ logger = logging.getLogger(__name__)
29
+
25
30
 
26
31
  @dataclass(frozen=True, slots=True)
27
32
  class Expression(DeclaresFacts):
@@ -182,6 +187,7 @@ class LiteralFormatter(Formatter):
182
187
  @dataclass(frozen=True, slots=True)
183
188
  class AICondition(Condition):
184
189
  chain: RunnableSerializable
190
+ model: BaseChatModel
185
191
  system_template: str
186
192
  inquiry_template: str
187
193
  func: None = field(init=False, default=None)
@@ -238,13 +244,23 @@ def ai_condition(model: BaseChatModel, inquiry: str) -> AICondition:
238
244
  )
239
245
  structured_model = model.with_structured_output(BooleanDecision)
240
246
  chain = prompt_template | structured_model
241
- return AICondition(chain=chain, system_template=system, inquiry_template=inquiry, facts=facts)
247
+ return AICondition(chain=chain, model=model, system_template=system, inquiry_template=inquiry, facts=facts)
242
248
 
243
249
 
244
- default_model = ChatOpenAI(model="gpt-4o-mini", temperature=0, max_tokens=100) # type: ignore[call-arg] - pyright can't see the args for some reason
250
+ @lru_cache(maxsize=1)
251
+ def _detect_default_model() -> BaseChatModel:
252
+ # TODO: Expand this to detect other providers
253
+ if importlib.util.find_spec("langchain_openai"):
254
+ from langchain_openai import ChatOpenAI
255
+
256
+ logger.debug("Using OpenAI as the default LLM model provider.")
257
+ return ChatOpenAI(model="gpt-4o-mini", temperature=0, max_tokens=100) # type: ignore[call-arg] - pyright can't see the args for some reason
258
+ else:
259
+ msg = "Unable to import a default LLM provider. Please install `vulcan_core` with the approriate extras package or specify your custom model explicitly."
260
+ raise ImportError(msg)
245
261
 
246
262
 
247
- def condition(func: ConditionCallable | str) -> Condition:
263
+ def condition(func: ConditionCallable | str, model: BaseChatModel | None = None) -> Condition:
248
264
  """
249
265
  Creates a Condition object from a lambda or function. It performs limited static analysis of the code to ensure
250
266
  proper usage and discover the facts/attributes accessed by the condition. This allows the rule engine to track
@@ -284,10 +300,14 @@ def condition(func: ConditionCallable | str) -> Condition:
284
300
  """
285
301
 
286
302
  if not isinstance(func, str):
303
+ # Logic condition assumed, ignore kwargs
287
304
  processed = ASTProcessor[ConditionCallable](func, condition, bool)
288
305
  return Condition(processed.facts, processed.func)
289
306
  else:
290
- return ai_condition(default_model, func)
307
+ # AI condition assumed
308
+ if not model:
309
+ model = _detect_default_model()
310
+ return ai_condition(model, func)
291
311
 
292
312
 
293
313
  # TODO: Create a convenience function for creating OnFactChanged conditions
vulcan_core/models.py CHANGED
@@ -258,3 +258,6 @@ class RetrieverAdapter(Similarity):
258
258
 
259
259
  def __len__(self) -> int:
260
260
  raise NotImplementedError
261
+
262
+ def __str__(self) -> str:
263
+ return f"RetrieverAdapter(search_type={self.store.search_type})"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: vulcan-core
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: AI-Hybrid Rules Engine for Logical Reasoning.
5
5
  License: Apache-2.0
6
6
  Keywords: rules,logic,reasoning,ai,artificial intelligence,RAG,LLM
@@ -0,0 +1,12 @@
1
+ vulcan_core/__init__.py,sha256=pjCnmbMjrsp672WXRQeOV0aSKUEoA_mj0o7q_ouMWs8,1057
2
+ vulcan_core/actions.py,sha256=RO5w5X-drxtDY_mVv0xR2njasWkGPt1AZo9RXsBi8X0,917
3
+ vulcan_core/ast_utils.py,sha256=dIJgiPaozUZ7ggY9_wksSWO0htG1rxaBJzGpWW3CmUU,12576
4
+ vulcan_core/conditions.py,sha256=znFG9eaIib_iA36kOQJFXySisjgexbNqGUYAw3419c0,13198
5
+ vulcan_core/engine.py,sha256=UtrfNkrokZazW_l3_zmwKyackJLON-mpGvnNmZyjBqM,9313
6
+ vulcan_core/models.py,sha256=gFc5SOE_weoNPZo_kV_R95OYdeOp7L57rKlIwSAwqh4,8584
7
+ vulcan_core/util.py,sha256=THlBzIO9zw7JiKGYB8PIan4oRjsGuNaZpx-lgCmUAVI,3419
8
+ vulcan_core-1.1.0.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
9
+ vulcan_core-1.1.0.dist-info/METADATA,sha256=Hw2a87OIUInw-2wpPdXgXLNtx0Ra3r_82r4qsFFrBaI,4349
10
+ vulcan_core-1.1.0.dist-info/NOTICE,sha256=UN1_Gd_Snmu8T62mxExNUdIF2o7DMdGu8bI8rKqhVnc,244
11
+ vulcan_core-1.1.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
12
+ vulcan_core-1.1.0.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- vulcan_core/__init__.py,sha256=pjCnmbMjrsp672WXRQeOV0aSKUEoA_mj0o7q_ouMWs8,1057
2
- vulcan_core/actions.py,sha256=RO5w5X-drxtDY_mVv0xR2njasWkGPt1AZo9RXsBi8X0,917
3
- vulcan_core/ast_utils.py,sha256=eNFcgmUaAXfkMjNy8rF2LDHslqj-4l2bqiUns_80fXY,11818
4
- vulcan_core/conditions.py,sha256=3TuXSd7UNlpwQnPy-5YJ-6zNGNZcW7b4iMGzo3fzBQE,12423
5
- vulcan_core/engine.py,sha256=UtrfNkrokZazW_l3_zmwKyackJLON-mpGvnNmZyjBqM,9313
6
- vulcan_core/models.py,sha256=j9uA4MjzemN4BCVvifqAdFCanUguMeafhulr6GiI49Q,8480
7
- vulcan_core/util.py,sha256=THlBzIO9zw7JiKGYB8PIan4oRjsGuNaZpx-lgCmUAVI,3419
8
- vulcan_core-1.0.0.dist-info/LICENSE,sha256=psuoW8kuDP96RQsdhzwOqi6fyWv0ct8CR6Jr7He_P_k,10173
9
- vulcan_core-1.0.0.dist-info/METADATA,sha256=q4hqsr_6-G5pCkPFMeZcpgJYn7iq5vAKDYtax9rx4Dk,4349
10
- vulcan_core-1.0.0.dist-info/NOTICE,sha256=UN1_Gd_Snmu8T62mxExNUdIF2o7DMdGu8bI8rKqhVnc,244
11
- vulcan_core-1.0.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
12
- vulcan_core-1.0.0.dist-info/RECORD,,