nora-lib 0.0.4__tar.gz → 0.0.5.dev0__tar.gz

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.
Files changed (26) hide show
  1. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/PKG-INFO +1 -1
  2. nora_lib-0.0.5.dev0/nora_lib/context/context_service.py +42 -0
  3. nora_lib-0.0.5.dev0/nora_lib/context/models.py +11 -0
  4. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/interactions/interactions_service.py +12 -0
  5. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/interactions/models.py +34 -0
  6. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib.egg-info/PKG-INFO +1 -1
  7. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/setup.py +1 -1
  8. nora_lib-0.0.4/nora_lib/context/context_service.py +0 -95
  9. nora_lib-0.0.4/nora_lib/context/models.py +0 -21
  10. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/README.md +0 -0
  11. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/__init__.py +0 -0
  12. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/context/__init__.py +0 -0
  13. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/interactions/__init__.py +0 -0
  14. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/py.typed +0 -0
  15. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/tasks/__init__.py +0 -0
  16. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/tasks/models.py +0 -0
  17. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib/tasks/state.py +0 -0
  18. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib.egg-info/SOURCES.txt +0 -0
  19. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib.egg-info/dependency_links.txt +0 -0
  20. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib.egg-info/requires.txt +0 -0
  21. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/nora_lib.egg-info/top_level.txt +0 -0
  22. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/pyproject.toml +0 -0
  23. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/setup.cfg +0 -0
  24. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/tests/tasks/__init__.py +0 -0
  25. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/tests/tasks/test_state.py +0 -0
  26. {nora_lib-0.0.4 → nora_lib-0.0.5.dev0}/tests/test_placeholder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nora_lib
3
- Version: 0.0.4
3
+ Version: 0.0.5.dev0
4
4
  Summary: For making and coordinating agents and tools
5
5
  Home-page: https://github.com/allenai/nora_lib
6
6
  Requires-Python: >=3.9
@@ -0,0 +1,42 @@
1
+ from datetime import datetime, timezone
2
+ from typing import List, Optional
3
+ from uuid import UUID
4
+
5
+ from nora_lib.interactions.interactions_service import InteractionsService
6
+ from nora_lib.interactions.models import (
7
+ ReturnedMessage,
8
+ ReturnedAgentContextMessage,
9
+ ReturnedAgentContextEvent,
10
+ EventType,
11
+ AgentMessageData,
12
+ Event,
13
+ )
14
+ from nora_lib.context.models import WrappedTaskObject
15
+
16
+
17
+ class ContextService:
18
+ """
19
+ Save and retrieve task agent context from interaction store
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ agent_actor_id: str, # uuid representing this agent in interaction store
25
+ interactions_base_url: str,
26
+ interactions_bearer_token: Optional[str],
27
+ timeout: int = 30,
28
+ ):
29
+ self.interactions_service = self._get_interactions_service(
30
+ interactions_base_url, interactions_bearer_token, timeout
31
+ )
32
+ self.agent_actor_id = agent_actor_id
33
+
34
+ def _get_interactions_service(self, url, token, timeout) -> InteractionsService:
35
+ return InteractionsService(url, timeout, token)
36
+
37
+ def get_message(self, message_id: str) -> str:
38
+ message: ReturnedMessage = self.interactions_service.get_message(message_id)
39
+ if message.annotated_text:
40
+ return message.annotated_text
41
+ else:
42
+ return message.text
@@ -0,0 +1,11 @@
1
+ from typing import Optional
2
+ from pydantic import BaseModel, Field
3
+
4
+
5
+ class WrappedTaskObject(BaseModel):
6
+ """Encloses request or response object with additional metadata"""
7
+
8
+ message_id: str = Field(
9
+ description="id of originating message; key for istore retrieval"
10
+ )
11
+ data: dict = Field(description="Tool-defined request or response")
@@ -5,6 +5,7 @@ from typing import List, Optional
5
5
  from nora_lib.interactions.models import (
6
6
  Event,
7
7
  EventType,
8
+ Message,
8
9
  ReturnedMessage,
9
10
  ThreadRelationsResponse,
10
11
  ThreadForkEventData,
@@ -22,6 +23,17 @@ class InteractionsService:
22
23
  self.timeout = timeout
23
24
  self.headers = {"Authorization": f"Bearer {token}"}
24
25
 
26
+ def save_message(self, message: Message) -> None:
27
+ """Save a message to the Interactions API"""
28
+ message_url = f"{self.base_url}/interaction/v1/message"
29
+ response = requests.post(
30
+ message_url,
31
+ json=message.model_dump(),
32
+ headers=self.headers,
33
+ timeout=int(self.timeout),
34
+ )
35
+ response.raise_for_status()
36
+
25
37
  def save_event(self, event: Event) -> None:
26
38
  """Save an event to the Interactions API"""
27
39
  event_url = f"{self.base_url}/interaction/v1/event"
@@ -10,6 +10,40 @@ from uuid import UUID
10
10
  from pydantic import BaseModel, Field, field_serializer, ConfigDict
11
11
 
12
12
 
13
+ class Surface(str, Enum):
14
+ SLACK = "Slack"
15
+ WEB = "NoraWebapp"
16
+
17
+
18
+ class Annotation(BaseModel):
19
+ # Need this config to stringify numeric values in attributes.
20
+ # Otherwise, we'll get 'Input should be a valid string' error.
21
+ model_config = ConfigDict(coerce_numbers_to_str=True)
22
+
23
+ tag: str
24
+ span: Tuple[int, int]
25
+ attributes: Optional[Dict[str, str]] = None
26
+
27
+
28
+ class Message(BaseModel):
29
+ message_id: str
30
+ actor_id: UUID
31
+ text: str
32
+ thread_id: Optional[str]
33
+ channel_id: str
34
+ surface: Surface
35
+ ts: datetime
36
+ annotations: Optional[List[Annotation]] = None
37
+
38
+ @field_serializer("actor_id")
39
+ def serialize_actor_id(self, actor_id: UUID):
40
+ return str(actor_id)
41
+
42
+ @field_serializer("ts")
43
+ def serialize_ts(self, ts: datetime):
44
+ return ts.isoformat()
45
+
46
+
13
47
  class EventType(str, Enum):
14
48
  """Event types for the interactions service"""
15
49
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nora_lib
3
- Version: 0.0.4
3
+ Version: 0.0.5.dev0
4
4
  Summary: For making and coordinating agents and tools
5
5
  Home-page: https://github.com/allenai/nora_lib
6
6
  Requires-Python: >=3.9
@@ -7,7 +7,7 @@ dev_requirements = ["mypy", "pytest", "black", "types-requests"]
7
7
 
8
8
  setuptools.setup(
9
9
  name="nora_lib",
10
- version="0.0.4",
10
+ version="0.0.5.dev0",
11
11
  description="For making and coordinating agents and tools",
12
12
  url="https://github.com/allenai/nora_lib",
13
13
  packages=setuptools.find_packages(exclude=(["tests"])),
@@ -1,95 +0,0 @@
1
- from datetime import datetime, timezone
2
- from typing import List, Optional
3
- from uuid import UUID
4
-
5
- from nora_lib.interactions.interactions_service import InteractionsService
6
- from nora_lib.interactions.models import (
7
- ReturnedMessage,
8
- ReturnedAgentContextMessage,
9
- ReturnedAgentContextEvent,
10
- EventType,
11
- AgentMessageData,
12
- Event,
13
- )
14
- from nora_lib.context.models import WrappedTaskObject
15
-
16
-
17
- class ContextService:
18
- """
19
- Save and retrieve task agent context from interaction store
20
- """
21
-
22
- def __init__(
23
- self,
24
- agent_actor_id: str, # uuid representing this agent in interaction store
25
- interactions_base_url: str,
26
- interactions_bearer_token: Optional[str],
27
- timeout: int = 30,
28
- ):
29
- self.interactions_service = self._get_interactions_service(
30
- interactions_base_url, interactions_bearer_token, timeout
31
- )
32
- self.agent_actor_id = agent_actor_id
33
-
34
- def _get_interactions_service(self, url, token, timeout) -> InteractionsService:
35
- return InteractionsService(url, timeout, token)
36
-
37
- def get_message(self, message_id: str) -> str:
38
- message: ReturnedMessage = self.interactions_service.get_message(message_id)
39
- if message.annotated_text:
40
- return message.annotated_text
41
- else:
42
- return message.text
43
-
44
- def fetch_context(
45
- self, request: WrappedTaskObject
46
- ) -> List[ReturnedAgentContextMessage]:
47
- message_id = request.message_id
48
-
49
- returned_messages: List[ReturnedMessage] = (
50
- self.interactions_service.fetch_messages_and_events_for_forked_thread(
51
- message_id, EventType.AGENT_CONTEXT
52
- )
53
- )
54
-
55
- messages_with_filtered_events: List[ReturnedAgentContextMessage] = []
56
- for message in returned_messages:
57
- events_saved_by_this_agent: List[ReturnedAgentContextEvent] = []
58
- if message.events:
59
- for event in message.events:
60
- context_event = ReturnedAgentContextEvent.model_validate(event)
61
- if context_event.actor_id == self.agent_actor_id:
62
- events_saved_by_this_agent.append(context_event)
63
-
64
- events_saved_by_this_agent.sort(
65
- key=lambda event: datetime.fromisoformat(event.timestamp)
66
- )
67
-
68
- updated_message = ReturnedAgentContextMessage(
69
- message_id=message.message_id,
70
- actor_id=message.actor_id,
71
- text=message.text,
72
- ts=message.ts,
73
- annotated_text=message.annotated_text,
74
- events=events_saved_by_this_agent,
75
- )
76
-
77
- messages_with_filtered_events.append(updated_message)
78
-
79
- return messages_with_filtered_events
80
-
81
- def save_context(self, event_data: WrappedTaskObject):
82
- agent_data = AgentMessageData(
83
- message_data=event_data.model_dump(),
84
- data_sender_actor_id=event_data.sender_actor_id,
85
- virtual_thread_id=event_data.virtual_thread_id,
86
- )
87
- event = Event(
88
- type=EventType.AGENT_CONTEXT,
89
- actor_id=UUID(self.agent_actor_id),
90
- timestamp=datetime.now(timezone.utc),
91
- data=agent_data.model_dump(),
92
- message_id=event_data.message_id,
93
- )
94
-
95
- self.interactions_service.save_event(event)
@@ -1,21 +0,0 @@
1
- from typing import Generic, Optional, TypeVar
2
- from pydantic import BaseModel, Field
3
-
4
-
5
- R = TypeVar("R", bound=BaseModel)
6
-
7
-
8
- class WrappedTaskObject(BaseModel, Generic[R]):
9
- """Encloses request or response object with additional metadata"""
10
-
11
- message_id: str = Field(
12
- description="id of originating message; key for istore retrieval"
13
- )
14
- sender_actor_id: str = Field(
15
- description="string representation of uuid identifying agent sending data"
16
- )
17
- virtual_thread_id: Optional[str] = Field(
18
- description="Tool-defined local thread to associate follow up requests"
19
- )
20
- task_id: Optional[str] = Field(description="Reference to a long-running task")
21
- data: R = Field(description="Tool-defined request or response")
File without changes
File without changes
File without changes