docent-python 0.1.0a1__py3-none-any.whl → 0.1.0a3__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 docent-python might be problematic. Click here for more details.

@@ -1,11 +1,5 @@
1
1
  from docent.data_models.agent_run import AgentRun
2
2
  from docent.data_models.citation import Citation
3
- from docent.data_models.filters import (
4
- AgentRunIdFilter,
5
- BaseFrameFilter,
6
- ComplexFilter,
7
- SearchResultPredicateFilter,
8
- )
9
3
  from docent.data_models.metadata import BaseAgentRunMetadata, BaseMetadata, FrameDimension
10
4
  from docent.data_models.regex import RegexSnippet
11
5
  from docent.data_models.transcript import Transcript
@@ -14,11 +8,7 @@ __all__ = [
14
8
  "AgentRun",
15
9
  "Citation",
16
10
  "RegexSnippet",
17
- "AgentRunIdFilter",
18
11
  "FrameDimension",
19
- "BaseFrameFilter",
20
- "SearchResultPredicateFilter",
21
- "ComplexFilter",
22
12
  "BaseAgentRunMetadata",
23
13
  "BaseMetadata",
24
14
  "Transcript",
docent/sdk/client.py CHANGED
@@ -5,7 +5,6 @@ import requests
5
5
 
6
6
  from docent._log_util.logger import get_logger
7
7
  from docent.data_models.agent_run import AgentRun
8
- from docent.data_models.filters import FrameFilter
9
8
 
10
9
  logger = get_logger(__name__)
11
10
 
@@ -24,7 +23,11 @@ class Docent:
24
23
  """
25
24
 
26
25
  def __init__(
27
- self, server_url: str, web_url: str, email: str | None = None, password: str | None = None
26
+ self,
27
+ server_url: str = "https://aws-docent-backend.transluce.org",
28
+ web_url: str = "https://aws-docent.transluce.org",
29
+ email: str | None = None,
30
+ password: str | None = None,
28
31
  ):
29
32
  self._server_url = server_url.rstrip("/") + "/rest"
30
33
  self._web_url = web_url.rstrip("/")
@@ -177,53 +180,6 @@ class Docent:
177
180
  logger.info(f"Successfully added {total_runs} agent runs to FrameGrid '{fg_id}'")
178
181
  return {"status": "success", "total_runs_added": total_runs}
179
182
 
180
- def get_base_filter(self, fg_id: str) -> dict[str, Any] | None:
181
- """Retrieves the base filter for a FrameGrid.
182
-
183
- The base filter defines default filtering applied to all views.
184
-
185
- Args:
186
- fg_id: ID of the FrameGrid.
187
-
188
- Returns:
189
- dict or None: Filter data if a filter exists, None otherwise.
190
-
191
- Raises:
192
- requests.exceptions.HTTPError: If the API request fails.
193
- """
194
- url = f"{self._server_url}/{fg_id}/base_filter"
195
- response = self._session.get(url)
196
- response.raise_for_status()
197
- # The endpoint returns the filter model directly or null
198
- filter_data = response.json()
199
- return filter_data
200
-
201
- def set_base_filter(self, fg_id: str, filter: FrameFilter | None) -> dict[str, Any]:
202
- """Sets the base filter for a FrameGrid.
203
-
204
- The base filter defines default filtering applied to all views.
205
-
206
- Args:
207
- fg_id: ID of the FrameGrid.
208
- filter: FrameFilter object defining the filter, or None to clear the filter.
209
-
210
- Returns:
211
- dict: API response data.
212
-
213
- Raises:
214
- requests.exceptions.HTTPError: If the API request fails.
215
- """
216
- url = f"{self._server_url}/{fg_id}/base_filter"
217
- payload = {
218
- "filter": filter.model_dump() if filter else None,
219
- }
220
-
221
- response = self._session.post(url, json=payload)
222
- response.raise_for_status()
223
-
224
- logger.info(f"Successfully set base filter for FrameGrid '{fg_id}'")
225
- return response.json()
226
-
227
183
  def list_framegrids(self) -> list[dict[str, Any]]:
228
184
  """Lists all available FrameGrids.
229
185
 
@@ -1,16 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: docent-python
3
- Version: 0.1.0a1
3
+ Version: 0.1.0a3
4
4
  Summary: Docent SDK
5
5
  Project-URL: Homepage, https://github.com/TransluceAI/docent
6
6
  Project-URL: Issues, https://github.com/TransluceAI/docent/issues
7
7
  Project-URL: Docs, https://transluce-docent.readthedocs-hosted.com/en/latest
8
- Author-email: Transluce AI <info@transluce.org>
8
+ Author-email: Transluce <info@transluce.org>
9
9
  License-Expression: MIT
10
10
  License-File: LICENSE.md
11
11
  Requires-Python: >=3.11
12
- Requires-Dist: logging>=0.4.9.6
13
12
  Requires-Dist: pydantic>=2.11.7
14
13
  Requires-Dist: pyyaml>=6.0.2
15
- Requires-Dist: sqlalchemy>=2.0.41
16
14
  Requires-Dist: tiktoken>=0.7.0
@@ -2,11 +2,10 @@ docent/__init__.py,sha256=J2BbO6rzilfw9WXRUeolr439EGFezqbMU_kCpCCryRA,59
2
2
  docent/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  docent/_log_util/__init__.py,sha256=3HXXrxrSm8PxwG4llotrCnSnp7GuroK1FNHsdg6f7aE,73
4
4
  docent/_log_util/logger.py,sha256=kwM0yRW1IJd6-XTorjWn48B4l8qvD2ZM6VDjY5eskQI,4422
5
- docent/data_models/__init__.py,sha256=M84x4yoPZz97-e-2KQ4qXud8i6Ykdjl1ChbwZalu2NQ,689
5
+ docent/data_models/__init__.py,sha256=SbXBXpI2HLI2qeGoKD-6Qp0gY3igQAw6qOsolc_rj7Q,448
6
6
  docent/data_models/_tiktoken_util.py,sha256=hC0EDDWItv5-0cONBnHWgZtQOflDU7ZNEhXPFo4DvPc,3057
7
7
  docent/data_models/agent_run.py,sha256=sdvoUUpOhQAHqJHNR5KoHthCXrpJajdIREMacoR1ODk,9516
8
8
  docent/data_models/citation.py,sha256=WsVQZcBT2EJD24ysyeVOC5Xfo165RI7P5_cOnJBgHj0,10015
9
- docent/data_models/filters.py,sha256=nZquRQji_xZwea6nBxM_SRECaYECDMEQ8Zt1TXl-_jI,7484
10
9
  docent/data_models/metadata.py,sha256=yBEm5M_gSNuoG---Fezsjm0YDGUQoJeM_BL9rwbBt-U,8035
11
10
  docent/data_models/regex.py,sha256=0ciIerkrNwb91bY5mTcyO5nDWH67xx2tZYObV52fmBo,1684
12
11
  docent/data_models/shared_types.py,sha256=jjm-Dh5S6v7UKInW7SEqoziOsx6Z7Uu4e3VzgCbTWvc,225
@@ -16,8 +15,8 @@ docent/data_models/chat/content.py,sha256=Co-jO8frQa_DSP11wJuhPX0s-GpJk8yqtKqPei
16
15
  docent/data_models/chat/message.py,sha256=iAo38kbV6wYbFh8S23cxLy6HY4C_i3PzQ6RpSQG5dxM,3861
17
16
  docent/data_models/chat/tool.py,sha256=x7NKINswPe0Kqvcx4ubjHzB-n0-i4DbFodvaBb2vitk,3042
18
17
  docent/sdk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- docent/sdk/client.py,sha256=XoeO8d7vCghf0WZoc22lJdPRBt6i88S2QV-viQubuEA,10090
20
- docent_python-0.1.0a1.dist-info/METADATA,sha256=NewmZvefKjD0vLDEHpc_VRf4v-asf_jf9DEEsVG2xmw,562
21
- docent_python-0.1.0a1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
22
- docent_python-0.1.0a1.dist-info/licenses/LICENSE.md,sha256=-TCY5GNyVAczrb96jTgTPalccQeyZqVXgs0N_dhC1OI,1086
23
- docent_python-0.1.0a1.dist-info/RECORD,,
18
+ docent/sdk/client.py,sha256=J6xd100KWym-jOrXjaEyagi85ddklymF9QEOJmYxJP8,8588
19
+ docent_python-0.1.0a3.dist-info/METADATA,sha256=v_-KmR9urNIEdjduRZ_wzZXpplPvImgT--y_QKgGHAI,493
20
+ docent_python-0.1.0a3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
21
+ docent_python-0.1.0a3.dist-info/licenses/LICENSE.md,sha256=vOHzq3K4Ndu0UV9hPrtXvlD7pHOjyDQmGjHuLSIkRQY,1087
22
+ docent_python-0.1.0a3.dist-info/RECORD,,
@@ -4,4 +4,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
4
 
5
5
  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
6
 
7
- THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,205 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING, Annotated, Any, Literal, Type, Union
4
- from uuid import uuid4
5
-
6
- from pydantic import BaseModel, Discriminator, Field, field_validator
7
- from sqlalchemy import ColumnElement, and_, or_
8
-
9
- from docent._log_util import get_logger
10
-
11
- if TYPE_CHECKING:
12
- from docent_core._db_service.schemas.tables import SQLAAgentRun
13
-
14
- logger = get_logger(__name__)
15
-
16
-
17
- class BaseFrameFilter(BaseModel):
18
- """Base class for all frame filters."""
19
-
20
- id: str = Field(default_factory=lambda: str(uuid4()))
21
- name: str | None = None
22
- supports_sql: bool = True # All filters must support SQL
23
-
24
- def to_sqla_where_clause(self, table: Type["SQLAAgentRun"]) -> ColumnElement[bool] | None:
25
- """Convert this filter to a SQLAlchemy WHERE clause.
26
-
27
- All filters must implement this method to support SQL execution.
28
- """
29
- raise NotImplementedError(
30
- f"Filter {self.__class__.__name__} must implement to_sqla_where_clause"
31
- )
32
-
33
-
34
- class PrimitiveFilter(BaseFrameFilter):
35
- """Filter that applies a primitive operation to a metadata field."""
36
-
37
- type: Literal["primitive"] = "primitive"
38
- key_path: list[str]
39
- value: Any
40
- op: Literal[">", ">=", "<", "<=", "==", "!=", "~*", "!~*"]
41
-
42
- def to_sqla_where_clause(self, table: Type["SQLAAgentRun"]) -> ColumnElement[bool] | None:
43
- """Convert this filter to a SQLAlchemy WHERE clause."""
44
-
45
- mode = self.key_path[0]
46
-
47
- # Extract value from JSONB using the table parameter
48
- if mode == "text":
49
- sqla_value = table.text_for_search # type: ignore
50
- elif mode == "metadata":
51
- sqla_value = table.metadata_json # type: ignore
52
- else:
53
- raise ValueError(f"Unsupported mode: {mode}")
54
-
55
- for key in self.key_path[1:]:
56
- sqla_value = sqla_value[key]
57
-
58
- # Cast the extracted value to the correct type
59
- # This is only necessary for metadata which is JSONB
60
- if mode == "metadata":
61
- if isinstance(self.value, str):
62
- sqla_value = sqla_value.as_string()
63
- elif isinstance(self.value, bool):
64
- sqla_value = sqla_value.as_boolean()
65
- elif isinstance(self.value, float) or isinstance(self.value, int): # type: ignore warning about unnecessary comparison
66
- # if self.value is an int, we may still need to do sql comparisons with floats
67
- sqla_value = sqla_value.as_float()
68
- else:
69
- raise ValueError(f"Unsupported value type: {type(self.value)}")
70
-
71
- # Handle different operations using SQLAlchemy expressions
72
- if self.op == "==":
73
- return sqla_value == self.value
74
- elif self.op == "!=":
75
- return sqla_value != self.value
76
- elif self.op == ">":
77
- return sqla_value > self.value
78
- elif self.op == ">=":
79
- return sqla_value >= self.value
80
- elif self.op == "<":
81
- return sqla_value < self.value
82
- elif self.op == "<=":
83
- return sqla_value <= self.value
84
- elif self.op == "~*":
85
- return sqla_value.op("~*")(self.value)
86
- else:
87
- raise ValueError(f"Unsupported operation: {self.op}")
88
-
89
-
90
- class ComplexFilter(BaseFrameFilter):
91
- """Filter that combines multiple filters with AND/OR/NOT logic."""
92
-
93
- type: Literal["complex"] = "complex"
94
- filters: list[FrameFilter]
95
- op: Literal["and", "or"] = "and"
96
-
97
- @field_validator("filters")
98
- @classmethod
99
- def validate_filters(cls, v: list[FrameFilter]) -> list[FrameFilter]:
100
- if not v:
101
- raise ValueError("ComplexFilter must have at least one filter")
102
- return v
103
-
104
- def to_sqla_where_clause(self, table: Type["SQLAAgentRun"]) -> ColumnElement[bool] | None:
105
- """Convert this filter to a SQLAlchemy WHERE clause."""
106
-
107
- # Get WHERE clauses for all sub-filters
108
- where_clauses: list[ColumnElement[bool]] = []
109
- for filter_obj in self.filters:
110
- where_clause = filter_obj.to_sqla_where_clause(table)
111
- if where_clause is not None:
112
- where_clauses.append(where_clause)
113
-
114
- if not where_clauses:
115
- return None
116
-
117
- # Apply the operation
118
- if self.op == "and":
119
- result = and_(*where_clauses)
120
- elif self.op == "or":
121
- result = or_(*where_clauses)
122
- else:
123
- raise ValueError(f"Unsupported operation: {self.op}")
124
-
125
- return result
126
-
127
-
128
- class AgentRunIdFilter(BaseFrameFilter):
129
- """Filter that matches specific agent run IDs."""
130
-
131
- type: Literal["agent_run_id"] = "agent_run_id"
132
- agent_run_ids: list[str]
133
-
134
- @field_validator("agent_run_ids")
135
- @classmethod
136
- def validate_agent_run_ids(cls, v: list[str]) -> list[str]:
137
- if not v:
138
- raise ValueError("AgentRunIdFilter must have at least one agent run ID")
139
- return v
140
-
141
- def to_sqla_where_clause(self, table: Type["SQLAAgentRun"]) -> ColumnElement[bool] | None:
142
- """Convert to SQLAlchemy WHERE clause for agent run ID filtering."""
143
- return table.id.in_(self.agent_run_ids)
144
-
145
-
146
- class SearchResultPredicateFilter(BaseFrameFilter):
147
- """Filter that applies a predicate to search results."""
148
-
149
- type: Literal["search_result_predicate"] = "search_result_predicate"
150
- predicate: str
151
- search_query: str
152
-
153
- def to_sqla_where_clause(self, table: Type["SQLAAgentRun"]) -> ColumnElement[bool] | None:
154
- """Convert to SQLAlchemy WHERE clause for search result filtering."""
155
- # This filter requires joining with search results table
156
- # For now, we'll return None to indicate it needs special handling
157
- # In practice, this would join with the search_results table
158
- return None
159
-
160
-
161
- class SearchResultExistsFilter(BaseFrameFilter):
162
- """Filter that checks if search results exist."""
163
-
164
- type: Literal["search_result_exists"] = "search_result_exists"
165
- search_query: str
166
-
167
- def to_sqla_where_clause(self, table: Type["SQLAAgentRun"]) -> ColumnElement[bool] | None:
168
- """Convert to SQLAlchemy WHERE clause for search result existence filtering."""
169
- # This filter requires joining with search results table
170
- # For now, we'll return None to indicate it needs special handling
171
- # In practice, this would join with the search_results table
172
- return None
173
-
174
-
175
- FrameFilter = Annotated[
176
- Union[
177
- PrimitiveFilter,
178
- ComplexFilter,
179
- AgentRunIdFilter,
180
- SearchResultPredicateFilter,
181
- SearchResultExistsFilter,
182
- ],
183
- Discriminator("type"),
184
- ]
185
-
186
-
187
- def parse_filter_dict(filter_dict: dict[str, Any]) -> FrameFilter:
188
- """Parse a filter dictionary into a FrameFilter object."""
189
- filter_type = filter_dict.get("type")
190
-
191
- if filter_type == "primitive":
192
- return PrimitiveFilter(**filter_dict)
193
- elif filter_type == "complex":
194
- # Recursively parse nested filters
195
- nested_filters = [parse_filter_dict(f) for f in filter_dict.get("filters", [])]
196
- filter_dict["filters"] = nested_filters
197
- return ComplexFilter(**filter_dict)
198
- elif filter_type == "agent_run_id":
199
- return AgentRunIdFilter(**filter_dict)
200
- elif filter_type == "search_result_predicate":
201
- return SearchResultPredicateFilter(**filter_dict)
202
- elif filter_type == "search_result_exists":
203
- return SearchResultExistsFilter(**filter_dict)
204
- else:
205
- raise ValueError(f"Unknown filter type: {filter_type}")