h-ai-brain 0.0.6__py3-none-any.whl → 0.0.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.
- h_ai/application/hai_service.py +19 -9
- h_ai/application/priority_queue_service.py +34 -0
- h_ai/domain/priorityqueue/__init__.py +0 -0
- h_ai/domain/priorityqueue/priority_queue_repository.py +34 -0
- h_ai/domain/priorityqueue/queue_item.py +43 -0
- h_ai/infrastructure/priorityqueue/__init__.py +0 -0
- h_ai/infrastructure/priorityqueue/in_memory_priority_queue_repository.py +87 -0
- {h_ai_brain-0.0.6.dist-info → h_ai_brain-0.0.7.dist-info}/METADATA +1 -1
- {h_ai_brain-0.0.6.dist-info → h_ai_brain-0.0.7.dist-info}/RECORD +13 -7
- {h_ai_brain-0.0.6.dist-info → h_ai_brain-0.0.7.dist-info}/WHEEL +1 -1
- {h_ai_brain-0.0.6.dist-info → h_ai_brain-0.0.7.dist-info}/licenses/LICENSE +0 -0
- {h_ai_brain-0.0.6.dist-info → h_ai_brain-0.0.7.dist-info}/licenses/NOTICE.txt +0 -0
- {h_ai_brain-0.0.6.dist-info → h_ai_brain-0.0.7.dist-info}/top_level.txt +0 -0
h_ai/application/hai_service.py
CHANGED
@@ -1,17 +1,22 @@
|
|
1
|
-
import datetime
|
2
|
-
|
3
1
|
from h_message_bus import NatsPublisherAdapter
|
4
|
-
from h_message_bus.domain.twitter_get_user_request_message import TwitterGetUserRequestMessage
|
5
|
-
from h_message_bus.domain.twitter_get_user_response_message import TwitterGetUserResponseMessage
|
6
|
-
from h_message_bus.domain.
|
7
|
-
|
2
|
+
from h_message_bus.domain.request_messages.twitter_get_user_request_message import TwitterGetUserRequestMessage
|
3
|
+
from h_message_bus.domain.request_messages.twitter_get_user_response_message import TwitterGetUserResponseMessage
|
4
|
+
from h_message_bus.domain.request_messages.vector_read_metadata_request_message import VectorReadMetaDataRequestMessage
|
5
|
+
from h_message_bus.domain.request_messages.vector_read_metadata_response_message import \
|
6
|
+
VectorReadMetaDataResponseMessage
|
7
|
+
from h_message_bus.domain.request_messages.vector_save_request_message import VectorSaveRequestMessage
|
8
|
+
|
9
|
+
from .priority_queue_service import PriorityQueueService
|
8
10
|
from ..application.web_docs_service import WebDocsService
|
11
|
+
from ..infrastructure.priorityqueue.in_memory_priority_queue_repository import InMemoryPriorityQueueRepository
|
9
12
|
|
10
13
|
|
11
14
|
class HaiService:
|
12
15
|
def __init__(self, nats_publisher_adapter: NatsPublisherAdapter):
|
13
16
|
self.nats_publisher_adapter = nats_publisher_adapter
|
14
17
|
self.web_docs_service = WebDocsService()
|
18
|
+
queue = InMemoryPriorityQueueRepository()
|
19
|
+
self.queue_service = PriorityQueueService(queue)
|
15
20
|
|
16
21
|
async def detect_and_store_documentation(self, twitter_screen_name: str):
|
17
22
|
req_message = TwitterGetUserRequestMessage.create_message(twitter_screen_name)
|
@@ -31,8 +36,7 @@ class HaiService:
|
|
31
36
|
document_id = f"{doc.title}_{chapter.heading}_{i}"
|
32
37
|
|
33
38
|
req_metadata = {
|
34
|
-
"source": doc.url
|
35
|
-
"updated": datetime.datetime.utcnow().isoformat()
|
39
|
+
"source": doc.url
|
36
40
|
}
|
37
41
|
i = i + 1
|
38
42
|
|
@@ -45,4 +49,10 @@ class HaiService:
|
|
45
49
|
await self.nats_publisher_adapter.publish(request)
|
46
50
|
|
47
51
|
else:
|
48
|
-
print(f"No documentation found for {twitter_user.screen_name}")
|
52
|
+
print(f"No documentation found for {twitter_user.screen_name}")
|
53
|
+
|
54
|
+
async def load_current_knowledge_base_metadata(self):
|
55
|
+
message = VectorReadMetaDataRequestMessage.create_message()
|
56
|
+
response = await self.nats_publisher_adapter.request(message)
|
57
|
+
metadata_result = VectorReadMetaDataResponseMessage.from_hai_message(response)
|
58
|
+
print(metadata_result)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
from typing import Any, List, Optional
|
3
|
+
|
4
|
+
from ..domain.priorityqueue.priority_queue_repository import PriorityQueueRepository
|
5
|
+
from ..domain.priorityqueue.queue_item import QueueItem
|
6
|
+
|
7
|
+
|
8
|
+
class PriorityQueueService:
|
9
|
+
"""Application service to manage priority queue operations"""
|
10
|
+
|
11
|
+
def __init__(self, repository: PriorityQueueRepository):
|
12
|
+
self.repository = repository
|
13
|
+
|
14
|
+
def add_item(self, queue_name: str, content: Any, priority: int, metadata: Optional[dict] = None) -> QueueItem:
|
15
|
+
"""Add an item to the specified queue"""
|
16
|
+
item = QueueItem.create(content, priority, metadata)
|
17
|
+
self.repository.add_item(queue_name, item)
|
18
|
+
return item
|
19
|
+
|
20
|
+
def get_next_item(self, queue_name: str) -> Optional[QueueItem]:
|
21
|
+
"""Get and remove the highest priority item from the queue"""
|
22
|
+
return self.repository.get_highest_priority_item(queue_name)
|
23
|
+
|
24
|
+
def get_items(self, queue_name: str, limit: int = 10) -> List[QueueItem]:
|
25
|
+
"""Get multiple items from the queue in priority order without removing them"""
|
26
|
+
return self.repository.get_items(queue_name, limit)
|
27
|
+
|
28
|
+
def get_queue_length(self, queue_name: str) -> int:
|
29
|
+
"""Get the number of items in the queue"""
|
30
|
+
return self.repository.queue_length(queue_name)
|
31
|
+
|
32
|
+
def get_available_queues(self) -> List[str]:
|
33
|
+
"""Get a list of all available queue names"""
|
34
|
+
return self.repository.get_queue_names()
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from typing import List, Optional
|
4
|
+
|
5
|
+
from .queue_item import QueueItem
|
6
|
+
|
7
|
+
|
8
|
+
class PriorityQueueRepository(ABC):
|
9
|
+
"""Repository interface for priority queue operations"""
|
10
|
+
|
11
|
+
@abstractmethod
|
12
|
+
def add_item(self, queue_name: str, item: QueueItem) -> None:
|
13
|
+
"""Add an item to the specified queue"""
|
14
|
+
pass
|
15
|
+
|
16
|
+
@abstractmethod
|
17
|
+
def get_highest_priority_item(self, queue_name: str) -> Optional[QueueItem]:
|
18
|
+
"""Get and remove the highest priority item from the queue"""
|
19
|
+
pass
|
20
|
+
|
21
|
+
@abstractmethod
|
22
|
+
def get_items(self, queue_name: str, limit: int = 10) -> List[QueueItem]:
|
23
|
+
"""Get multiple items from the queue in priority order without removing them"""
|
24
|
+
pass
|
25
|
+
|
26
|
+
@abstractmethod
|
27
|
+
def queue_length(self, queue_name: str) -> int:
|
28
|
+
"""Get the number of items in the queue"""
|
29
|
+
pass
|
30
|
+
|
31
|
+
@abstractmethod
|
32
|
+
def get_queue_names(self) -> List[str]:
|
33
|
+
"""Get a list of all available queue names"""
|
34
|
+
pass
|
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
import uuid
|
3
|
+
from dataclasses import dataclass
|
4
|
+
from datetime import datetime
|
5
|
+
from typing import Optional
|
6
|
+
|
7
|
+
from h_message_bus import HaiMessage
|
8
|
+
|
9
|
+
|
10
|
+
@dataclass(frozen=True)
|
11
|
+
class QueueItem:
|
12
|
+
"""Value object representing an item in the priority queue"""
|
13
|
+
id: str
|
14
|
+
content: HaiMessage
|
15
|
+
priority: int
|
16
|
+
created_at: datetime
|
17
|
+
metadata: Optional[dict] = None
|
18
|
+
|
19
|
+
@classmethod
|
20
|
+
def create(cls, content: HaiMessage, priority: int, metadata: Optional[dict] = None) -> "QueueItem":
|
21
|
+
"""Factory method to create a new QueueItem"""
|
22
|
+
return cls(
|
23
|
+
id=str(uuid.uuid4()),
|
24
|
+
content=content,
|
25
|
+
priority=priority,
|
26
|
+
created_at=datetime.utcnow(),
|
27
|
+
metadata=metadata
|
28
|
+
)
|
29
|
+
|
30
|
+
def __lt__(self, other):
|
31
|
+
"""Comparison method for priority queue ordering
|
32
|
+
- Primary sort by priority: Higher number = higher priority
|
33
|
+
- Secondary sort by timestamp: Earlier timestamp = higher priority (FIFO)
|
34
|
+
"""
|
35
|
+
if not isinstance(other, QueueItem):
|
36
|
+
return NotImplemented
|
37
|
+
|
38
|
+
# First, compare by priority (higher priority value comes first)
|
39
|
+
if self.priority != other.priority:
|
40
|
+
return self.priority > other.priority
|
41
|
+
|
42
|
+
# If priorities are equal, compare by timestamp (older timestamp comes first)
|
43
|
+
return self.created_at < other.created_at
|
File without changes
|
@@ -0,0 +1,87 @@
|
|
1
|
+
|
2
|
+
import threading
|
3
|
+
from queue import PriorityQueue
|
4
|
+
from typing import Dict, List, Optional
|
5
|
+
|
6
|
+
from ...domain.priorityqueue.priority_queue_repository import PriorityQueueRepository
|
7
|
+
from ...domain.priorityqueue.queue_item import QueueItem
|
8
|
+
|
9
|
+
|
10
|
+
class InMemoryPriorityQueueRepository(PriorityQueueRepository):
|
11
|
+
"""In-memory implementation of the PriorityQueueRepository using Python's PriorityQueue"""
|
12
|
+
|
13
|
+
def __init__(self):
|
14
|
+
# Dictionary mapping queue names to their PriorityQueue instances
|
15
|
+
self.queues: Dict[str, PriorityQueue] = {}
|
16
|
+
# Locks to ensure thread safety
|
17
|
+
self.locks: Dict[str, threading.Lock] = {}
|
18
|
+
|
19
|
+
def _get_or_create_queue(self, queue_name: str, maxsize: int = 10000) -> PriorityQueue:
|
20
|
+
"""Get or create a queue with the given name"""
|
21
|
+
if queue_name not in self.queues:
|
22
|
+
self.queues[queue_name] = PriorityQueue(maxsize=maxsize)
|
23
|
+
self.locks[queue_name] = threading.Lock()
|
24
|
+
return self.queues[queue_name]
|
25
|
+
|
26
|
+
def _get_lock(self, queue_name: str) -> threading.Lock:
|
27
|
+
"""Get the lock for the specified queue"""
|
28
|
+
if queue_name not in self.locks:
|
29
|
+
self.locks[queue_name] = threading.Lock()
|
30
|
+
return self.locks[queue_name]
|
31
|
+
|
32
|
+
def add_item(self, queue_name: str, item: QueueItem) -> None:
|
33
|
+
"""Add an item to the specified queue"""
|
34
|
+
queue = self._get_or_create_queue(queue_name)
|
35
|
+
with self._get_lock(queue_name):
|
36
|
+
# The queue automatically orders by priority
|
37
|
+
queue.put(item)
|
38
|
+
|
39
|
+
def get_highest_priority_item(self, queue_name: str) -> Optional[QueueItem]:
|
40
|
+
"""Get and remove the highest priority item from the queue"""
|
41
|
+
if queue_name not in self.queues:
|
42
|
+
return None
|
43
|
+
|
44
|
+
queue = self.queues[queue_name]
|
45
|
+
with self._get_lock(queue_name):
|
46
|
+
if queue.empty():
|
47
|
+
return None
|
48
|
+
return queue.get()
|
49
|
+
|
50
|
+
def get_items(self, queue_name: str, limit: int = 10) -> List[QueueItem]:
|
51
|
+
"""Get multiple items from the queue in priority order without removing them"""
|
52
|
+
if queue_name not in self.queues:
|
53
|
+
return []
|
54
|
+
|
55
|
+
queue = self.queues[queue_name]
|
56
|
+
result = []
|
57
|
+
|
58
|
+
with self._get_lock(queue_name):
|
59
|
+
# Create a temporary list to hold items that we'll put back
|
60
|
+
temp_items = []
|
61
|
+
|
62
|
+
# Get up to 'limit' items
|
63
|
+
count = 0
|
64
|
+
while not queue.empty() and count < limit:
|
65
|
+
item = queue.get()
|
66
|
+
temp_items.append(item)
|
67
|
+
result.append(item)
|
68
|
+
count += 1
|
69
|
+
|
70
|
+
# Put all the items back in the same order
|
71
|
+
for item in temp_items:
|
72
|
+
queue.put(item)
|
73
|
+
|
74
|
+
return result
|
75
|
+
|
76
|
+
def queue_length(self, queue_name: str) -> int:
|
77
|
+
"""Get the number of items in the queue"""
|
78
|
+
if queue_name not in self.queues:
|
79
|
+
return 0
|
80
|
+
|
81
|
+
queue = self.queues[queue_name]
|
82
|
+
with self._get_lock(queue_name):
|
83
|
+
return queue.qsize()
|
84
|
+
|
85
|
+
def get_queue_names(self) -> List[str]:
|
86
|
+
"""Get a list of all available queue names"""
|
87
|
+
return list(self.queues.keys())
|
@@ -1,10 +1,14 @@
|
|
1
1
|
h_ai/__init__.py,sha256=bmHMDoui52Q73UvXdHslQ3w_LubmhRuKRlrjOYyCP8c,153
|
2
2
|
h_ai/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
h_ai/application/hai_service.py,sha256=
|
3
|
+
h_ai/application/hai_service.py,sha256=ZSbDLP8oCBliLpbhpKOf7Xv6cWDsLCSeDeurn207FsA,3005
|
4
|
+
h_ai/application/priority_queue_service.py,sha256=qi1PZMLYxy3HzG6cu-2hLijUYGcYGYMpzAp4S0vl0I0,1462
|
4
5
|
h_ai/application/web_docs_service.py,sha256=YiPBfPyjlloDq6CIOP0u7F1jNBK-elYRU8xl4qJ1oVc,1652
|
5
6
|
h_ai/application/system_prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
7
|
h_ai/application/system_prompts/roles/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
8
|
h_ai/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
|
+
h_ai/domain/priorityqueue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
+
h_ai/domain/priorityqueue/priority_queue_repository.py,sha256=XCjBrJezloblcqOPJUStTmU5tofx954h-mzxOsYIAbg,1042
|
11
|
+
h_ai/domain/priorityqueue/queue_item.py,sha256=aP2Sd3ig9dgKnAsKE_rr3uRjJ_ClWIrvz0Y3nC8XbmE,1417
|
8
12
|
h_ai/domain/reasoning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
13
|
h_ai/domain/reasoning/llm_chat_repository.py,sha256=rY2izDyaDnoyyrCRS1qc9erHB98vARj4Mp-SnPwNhyY,211
|
10
14
|
h_ai/domain/reasoning/llm_generate_respository.py,sha256=DPiV6ldCE8YhDdVb5rj98MBudKalDQHV3CZ2ADTm_f8,178
|
@@ -42,9 +46,11 @@ h_ai/infrastructure/llm/ollama/models/ollama_chat_message.py,sha256=ZIz4PQ3869vI
|
|
42
46
|
h_ai/infrastructure/llm/ollama/models/ollama_chat_session.py,sha256=GZ_ddpbWa8iy6NZq50vokUFVZBiX0WNa81z9-r9RzTY,392
|
43
47
|
h_ai/infrastructure/playwright/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
44
48
|
h_ai/infrastructure/playwright/playwright_web_content_fetcher.py,sha256=FVwcK6hv_6aE4fYlJapLHyxNHsztQkKaulklHabyrEc,2684
|
45
|
-
|
46
|
-
|
47
|
-
h_ai_brain-0.0.
|
48
|
-
h_ai_brain-0.0.
|
49
|
-
h_ai_brain-0.0.
|
50
|
-
h_ai_brain-0.0.
|
49
|
+
h_ai/infrastructure/priorityqueue/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
50
|
+
h_ai/infrastructure/priorityqueue/in_memory_priority_queue_repository.py,sha256=-DodmvFBUFnglJJmbUFEi3HpqxEdZvYrOpwZrWZrSU0,3262
|
51
|
+
h_ai_brain-0.0.7.dist-info/licenses/LICENSE,sha256=SbvpEU5JIU3yzMMkyzrI0dGqHDoJR_lMKGdl6GZHsy4,11558
|
52
|
+
h_ai_brain-0.0.7.dist-info/licenses/NOTICE.txt,sha256=vxeIKUiGqAePLvDW4AVm3Xh-3BcsvMtCMn1tbsr9zsE,668
|
53
|
+
h_ai_brain-0.0.7.dist-info/METADATA,sha256=KxLN_FGexCNE_QbLb9lpyx_YWEM7-P8VO_Zoy--v1Yk,735
|
54
|
+
h_ai_brain-0.0.7.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
55
|
+
h_ai_brain-0.0.7.dist-info/top_level.txt,sha256=3MChDBWvDJV4cEHuZhzeODxQ4ewtw-arOuyaDOc6sIo,5
|
56
|
+
h_ai_brain-0.0.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|