beekeeper-core 1.0.10__py3-none-any.whl → 1.0.12__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.
@@ -1,15 +1,16 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Any, List, Optional
2
+ from typing import Any, Optional
3
3
 
4
4
  from beekeeper.core.llms.types import ChatMessage, ChatResponse, GenerateResponse
5
5
  from beekeeper.core.monitors import BaseMonitor
6
6
  from pydantic import BaseModel
7
7
 
8
8
 
9
- class BaseLLM(ABC, BaseModel):
9
+ class BaseLLM(BaseModel, ABC):
10
10
  """Abstract base class defining the interface for LLMs."""
11
11
 
12
12
  model_config = {"arbitrary_types_allowed": True}
13
+ model: str
13
14
  callback_manager: Optional[BaseMonitor] = None
14
15
 
15
16
  @classmethod
@@ -34,6 +35,6 @@ class BaseLLM(ABC, BaseModel):
34
35
 
35
36
  @abstractmethod
36
37
  def chat_completion(
37
- self, messages: List[ChatMessage], **kwargs: Any
38
+ self, messages: list[ChatMessage | dict], **kwargs: Any
38
39
  ) -> ChatResponse:
39
40
  """Generates a chat completion for LLM."""
@@ -6,17 +6,12 @@ from typing import Callable
6
6
 
7
7
  from beekeeper.core.llms.types import ChatMessage
8
8
  from beekeeper.core.monitors.types import PayloadRecord
9
- from deprecated import deprecated
9
+ from beekeeper.core.prompts.utils import extract_template_vars
10
10
 
11
11
  logger = getLogger(__name__)
12
12
 
13
13
 
14
- @deprecated(
15
- reason="'llm_chat_observer()' is deprecated and will be removed in a future version. Use 'llm_chat_monitor()'.",
16
- version="1.0.8",
17
- action="always",
18
- )
19
- def llm_chat_observer() -> Callable:
14
+ def llm_chat_monitor() -> Callable:
20
15
  """
21
16
  Decorator to wrap a method with llm handler logic.
22
17
  Looks for observability instances in `self.callback_manager`.
@@ -60,89 +55,29 @@ def llm_chat_observer() -> Callable:
60
55
  system_messages[0].content if system_messages else None
61
56
  )
62
57
 
63
- callback = callback_manager_fns(
64
- payload=PayloadRecord(
65
- input_text=(system_message or "") + last_user_message,
66
- generated_text=llm_return_val.message.content,
67
- generated_token_count=llm_return_val.raw["usage"][
68
- "completion_tokens"
69
- ],
70
- input_token_count=llm_return_val.raw["usage"][
71
- "prompt_tokens"
72
- ],
73
- response_time=response_time,
58
+ # Extract template variables values from the prompt template if available
59
+ template_var_values = (
60
+ extract_template_vars(
61
+ callback_manager_fns.prompt_template.template,
62
+ (system_message or ""),
74
63
  )
75
- )
76
-
77
- if asyncio.iscoroutine(callback):
78
- asyncio.run(callback)
79
-
80
- except Exception as e:
81
- logger.error(f"Observability callback error: {e}")
82
-
83
- threading.Thread(target=async_callback_thread).start()
84
-
85
- return llm_return_val
86
-
87
- return async_wrapper
88
-
89
- return decorator
90
-
91
-
92
- def llm_chat_monitor() -> Callable:
93
- """
94
- Decorator to wrap a method with llm handler logic.
95
- Looks for observability instances in `self.callback_manager`.
96
- """
97
-
98
- def decorator(f: Callable) -> Callable:
99
- def async_wrapper(self, *args, **kwargs):
100
- callback_manager_fns = getattr(self, "callback_manager", None)
101
-
102
- start_time = time.time()
103
- llm_return_val = f(self, *args, **kwargs)
104
- response_time = int((time.time() - start_time) * 1000)
105
-
106
- if callback_manager_fns:
107
-
108
- def async_callback_thread():
109
- try:
110
- # Extract input messages
111
- if len(args) > 0 and isinstance(args[0], ChatMessage):
112
- input_chat_messages = args[0]
113
- elif "messages" in kwargs:
114
- input_chat_messages = kwargs["messages"]
115
- else:
116
- raise ValueError(
117
- "No messages provided in positional or keyword arguments"
118
- )
119
-
120
- # Get the user's latest message after each interaction to chat observability.
121
- user_messages = [
122
- msg for msg in input_chat_messages if msg.role == "user"
123
- ]
124
- last_user_message = (
125
- user_messages[-1].content if user_messages else None
126
- )
127
-
128
- # Get the system/instruct (first) message to chat observability.
129
- system_messages = [
130
- msg for msg in input_chat_messages if msg.role == "system"
131
- ]
132
- system_message = (
133
- system_messages[0].content if system_messages else None
64
+ if callback_manager_fns.prompt_template
65
+ else {}
134
66
  )
135
67
 
136
68
  callback = callback_manager_fns(
137
69
  payload=PayloadRecord(
138
- input_text=(system_message or "") + last_user_message,
70
+ system_prompt=(system_message or ""),
71
+ input_text=last_user_message,
72
+ prompt_variables=list(template_var_values.keys()),
73
+ prompt_variable_values=template_var_values,
139
74
  generated_text=llm_return_val.message.content,
140
- generated_token_count=llm_return_val.raw["usage"][
141
- "completion_tokens"
142
- ],
143
75
  input_token_count=llm_return_val.raw["usage"][
144
76
  "prompt_tokens"
145
77
  ],
78
+ generated_token_count=llm_return_val.raw["usage"][
79
+ "completion_tokens"
80
+ ],
146
81
  response_time=response_time,
147
82
  )
148
83
  )
@@ -151,7 +86,7 @@ def llm_chat_monitor() -> Callable:
151
86
  asyncio.run(callback)
152
87
 
153
88
  except Exception as e:
154
- logger.error(f"Observability callback error: {e}")
89
+ logger.error(f"Observability callback: {e}")
155
90
 
156
91
  threading.Thread(target=async_callback_thread).start()
157
92
 
@@ -22,6 +22,26 @@ class ChatMessage(BaseModel):
22
22
  """Convert ChatMessage to dict."""
23
23
  return self.model_dump(exclude_none=True)
24
24
 
25
+ @classmethod
26
+ def from_value(cls, value: dict) -> "ChatMessage":
27
+ if value is None:
28
+ raise ValueError("Invalid 'ChatMessage', cannot be None")
29
+
30
+ if isinstance(value, cls):
31
+ return value
32
+
33
+ if isinstance(value, dict):
34
+ try:
35
+ return cls.model_validate(value)
36
+ except Exception as e:
37
+ raise ValueError(
38
+ "Invalid 'ChatMessage' dict. Received: '{}'.".format(e)
39
+ )
40
+
41
+ raise TypeError(
42
+ f"Invalid 'ChatMessage' type. Expected dict or ChatMessage, but received {type(value).__name__}."
43
+ )
44
+
25
45
 
26
46
  class GenerateResponse(BaseModel):
27
47
  """Generate response."""
@@ -17,7 +17,7 @@ class PromptMonitor(BaseMonitor):
17
17
  """Abstract base class defining the interface for prompt observability."""
18
18
 
19
19
  def __init__(self, prompt_template: Optional[PromptTemplate] = None) -> None:
20
- self.prompt_template = prompt_template
20
+ self.prompt_template = PromptTemplate.from_value(prompt_template)
21
21
 
22
22
  @classmethod
23
23
  def class_name(cls) -> str:
@@ -4,8 +4,11 @@ from pydantic import BaseModel
4
4
  class PayloadRecord(BaseModel):
5
5
  """Payload record."""
6
6
 
7
+ system_prompt: str | None = None
7
8
  input_text: str
9
+ prompt_variables: list[str] | None = None
10
+ prompt_variable_values: dict[str, str] | None = None
8
11
  generated_text: str
9
- generated_token_count: int
10
12
  input_token_count: int
13
+ generated_token_count: int
11
14
  response_time: int
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: beekeeper-core
3
- Version: 1.0.10
3
+ Version: 1.0.12
4
4
  Summary: Load any data in one line of code and connect with AI applications
5
5
  Project-URL: Repository, https://github.com/beekeeper-ai/beekeeper
6
6
  Author-email: Leonardo Furnielis <leonardofurnielis@outlook.com>
@@ -12,12 +12,12 @@ beekeeper/core/guardrails/__init__.py,sha256=onznwYWAyOaxOVeYZle7oDtj3QJODQvJHcf
12
12
  beekeeper/core/guardrails/base.py,sha256=T-Ywr80iTL0EFYarCymFEEI3QkMsrw27JVh_0407sEU,427
13
13
  beekeeper/core/guardrails/types.py,sha256=7sgw1S5BZY0OqO-n04pHXPU7sG-NEZJlQyIeb2Fsq9Q,359
14
14
  beekeeper/core/llms/__init__.py,sha256=PN-5Y_Km_l2vO8v9d7iJ6_5xPCZJBh8UzwqRvQZlmTo,250
15
- beekeeper/core/llms/base.py,sha256=jFU1om9Qk6KTIsZXeke7lMp--x009G6-fnM1615l2BQ,1292
16
- beekeeper/core/llms/decorators.py,sha256=wRYXlKD5Cc8k1qPGYEEv-RSJdoHj-MQqKuAAQzkN9Fc,6534
17
- beekeeper/core/llms/types.py,sha256=lWswZ_bJkPmoTeheWxB1-OnABTYIVAcASkZCwjaTLzE,847
15
+ beekeeper/core/llms/base.py,sha256=fxjOJJR3pNJxtvkICr0Nq9A9wnqf3SMM4cm4sAhA9-o,1308
16
+ beekeeper/core/llms/decorators.py,sha256=KzU5VrHrXpJBHWqDl0lUxeqrUHmaPiJovEeUTM_RNeU,4036
17
+ beekeeper/core/llms/types.py,sha256=ttPCZ3VYtY6tx-E6VIOTicflYMJ3m0aw1znZeYAEVu8,1489
18
18
  beekeeper/core/monitors/__init__.py,sha256=TvoiIUJtWRO_4zqCICsFaGl_v4Tpvft1M542Bi13pOI,112
19
- beekeeper/core/monitors/base.py,sha256=3ooSfgVpWoRLe2TqizHMRK_bI5C-sla57aYJ47FmIXM,980
20
- beekeeper/core/monitors/types.py,sha256=s-4tB8OdeaCUIRvi6FLuib2u4Yl9evqQdCundNREXQY,217
19
+ beekeeper/core/monitors/base.py,sha256=_MY0AXCqlLpptwBEOpIfw-lCfRog4rXe_WALPvkHFNk,1007
20
+ beekeeper/core/monitors/types.py,sha256=kAA0g6YT_Menlc0HLPl87Rk9o4r2TybGfLlzuGlL40Y,357
21
21
  beekeeper/core/observers/__init__.py,sha256=Z5sDAajai4QLdGIrjq-vr5eJEBhriMMCw5u46j6xHvA,149
22
22
  beekeeper/core/observers/base.py,sha256=y1SE_0WQusKhVomFuZCkk42Jb7r93ZS6r_j8vs_Y_r4,1203
23
23
  beekeeper/core/observers/types.py,sha256=s-4tB8OdeaCUIRvi6FLuib2u4Yl9evqQdCundNREXQY,217
@@ -38,6 +38,6 @@ beekeeper/core/tools/base.py,sha256=A6TXn7g3DAZMREYAobfVlyOBuJn_8mIeCByc5412L9Y,
38
38
  beekeeper/core/utils/pairwise.py,sha256=cpi8GItPFSYP4sjB5zgTFHi6JfBVWsMnNu8koA9VYQU,536
39
39
  beekeeper/core/vector_stores/__init__.py,sha256=R5SRG3YpOZqRwIfBLB8KVV6FALWqhIzIhCjRGj-bwPc,93
40
40
  beekeeper/core/vector_stores/base.py,sha256=YFW1ioZbFEcJovAh0ZCpHnj0eiXtZvqy_pj2lxPS92k,1652
41
- beekeeper_core-1.0.10.dist-info/METADATA,sha256=6yt3XFndeAKudQ_UsnQFZ_B_MeibOrrrIk_yt_zRV_0,1331
42
- beekeeper_core-1.0.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
- beekeeper_core-1.0.10.dist-info/RECORD,,
41
+ beekeeper_core-1.0.12.dist-info/METADATA,sha256=6ZkWc4BXq7HnmKUADUKCmRGR2QRPLHVd1dxegvYUj-k,1331
42
+ beekeeper_core-1.0.12.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
43
+ beekeeper_core-1.0.12.dist-info/RECORD,,