chat analytics protocol
Browse files
src/knowlang/chat_bot/feedback.py
CHANGED
@@ -1,41 +1,62 @@
|
|
1 |
-
from mixpanel import Mixpanel
|
2 |
-
from datetime import datetime
|
3 |
from enum import Enum
|
4 |
-
from
|
|
|
|
|
5 |
|
6 |
class ChatFeedback(Enum):
|
7 |
POSITIVE = "positive"
|
8 |
NEGATIVE = "negative"
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
class ChatAnalytics:
|
12 |
def __init__(self, config: ChatbotAnalyticsConfig):
|
13 |
-
self.
|
14 |
|
15 |
-
def track_query(
|
16 |
-
|
17 |
-
|
18 |
-
client_ip: str
|
19 |
-
):
|
20 |
-
"""Track query event in Mixpanel"""
|
21 |
-
self.mp.track(
|
22 |
-
distinct_id=hash(client_ip), # Hash for privacy
|
23 |
event_name="chat_query",
|
24 |
-
|
25 |
-
|
26 |
-
}
|
27 |
)
|
28 |
|
29 |
-
def track_feedback(
|
30 |
-
|
31 |
-
|
32 |
-
query: str,
|
33 |
-
client_ip: str
|
34 |
-
):
|
35 |
-
"""Track feedback event in Mixpanel"""
|
36 |
-
self.mp.track(
|
37 |
-
distinct_id=hash(client_ip), # Hash for privacy
|
38 |
event_name="chat_feedback",
|
|
|
39 |
properties={
|
40 |
"feedback": ChatFeedback.POSITIVE.value if like else ChatFeedback.NEGATIVE.value,
|
41 |
"query": query,
|
|
|
|
|
|
|
1 |
from enum import Enum
|
2 |
+
from typing import Protocol
|
3 |
+
from mixpanel import Mixpanel
|
4 |
+
from knowlang.configs.chat_config import ChatbotAnalyticsConfig, AnalyticsProvider
|
5 |
|
6 |
class ChatFeedback(Enum):
|
7 |
POSITIVE = "positive"
|
8 |
NEGATIVE = "negative"
|
9 |
|
10 |
+
class AnalyticsProviderProtocol(Protocol):
|
11 |
+
"""Protocol defining what an analytics provider must implement"""
|
12 |
+
def track_event(self, event_name: str, distinct_id: str, properties: dict) -> None:
|
13 |
+
"""Track an event with the analytics provider"""
|
14 |
+
...
|
15 |
+
|
16 |
+
class NoopAnalyticsProvider:
|
17 |
+
"""Provider that does nothing - used when analytics are disabled"""
|
18 |
+
def track_event(self, event_name: str, distinct_id: str, properties: dict) -> None:
|
19 |
+
pass
|
20 |
+
|
21 |
+
class MixpanelProvider:
|
22 |
+
"""Concrete implementation for Mixpanel"""
|
23 |
+
def __init__(self, api_key: str):
|
24 |
+
self._mp = Mixpanel(api_key)
|
25 |
+
|
26 |
+
def track_event(self, event_name: str, distinct_id: str, properties: dict) -> None:
|
27 |
+
self._mp.track(
|
28 |
+
distinct_id=distinct_id,
|
29 |
+
event_name=event_name,
|
30 |
+
properties=properties
|
31 |
+
)
|
32 |
+
|
33 |
+
def create_analytics_provider(config: ChatbotAnalyticsConfig) -> AnalyticsProviderProtocol:
|
34 |
+
"""Factory function to create the appropriate analytics provider"""
|
35 |
+
if not config.enabled or not config.api_key:
|
36 |
+
return NoopAnalyticsProvider()
|
37 |
+
|
38 |
+
if config.provider == AnalyticsProvider.MIXPANEL:
|
39 |
+
return MixpanelProvider(config.api_key)
|
40 |
+
|
41 |
+
raise ValueError(f"Unsupported analytics provider: {config.provider}")
|
42 |
|
43 |
class ChatAnalytics:
|
44 |
def __init__(self, config: ChatbotAnalyticsConfig):
|
45 |
+
self._provider = create_analytics_provider(config)
|
46 |
|
47 |
+
def track_query(self, query: str, client_ip: str) -> None:
|
48 |
+
"""Track query event"""
|
49 |
+
self._provider.track_event(
|
|
|
|
|
|
|
|
|
|
|
50 |
event_name="chat_query",
|
51 |
+
distinct_id=str(hash(client_ip)), # Hash for privacy
|
52 |
+
properties={"query": query}
|
|
|
53 |
)
|
54 |
|
55 |
+
def track_feedback(self, like: bool, query: str, client_ip: str) -> None:
|
56 |
+
"""Track feedback event"""
|
57 |
+
self._provider.track_event(
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
event_name="chat_feedback",
|
59 |
+
distinct_id=str(hash(client_ip)), # Hash for privacy
|
60 |
properties={
|
61 |
"feedback": ChatFeedback.POSITIVE.value if like else ChatFeedback.NEGATIVE.value,
|
62 |
"query": query,
|