Skip to content

Commit a638687

Browse files
authored
Revert "orjson optional wip (#1223)" (#1228)
This reverts commit 3fce7b7.
1 parent db2f128 commit a638687

File tree

10 files changed

+46
-147
lines changed

10 files changed

+46
-147
lines changed

python/langsmith/_internal/_background_thread.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -155,25 +155,13 @@ def tracing_control_thread_func(client_ref: weakref.ref[Client]) -> None:
155155
# 1 for this func, 1 for getrefcount, 1 for _get_data_type_cached
156156
num_known_refs = 3
157157

158-
def keep_thread_active() -> bool:
159-
# if `client.cleanup()` was called, stop thread
160-
if client and client._manual_cleanup:
161-
return False
162-
if not threading.main_thread().is_alive():
163-
# main thread is dead. should not be active
164-
return False
165-
166-
if hasattr(sys, "getrefcount"):
167-
# check if client refs count indicates we're the only remaining
168-
# reference to the client
169-
return sys.getrefcount(client) > num_known_refs + len(sub_threads)
170-
else:
171-
# in PyPy, there is no sys.getrefcount attribute
172-
# for now, keep thread alive
173-
return True
174-
175158
# loop until
176-
while keep_thread_active():
159+
while (
160+
# the main thread dies
161+
threading.main_thread().is_alive()
162+
# or we're the only remaining reference to the client
163+
and sys.getrefcount(client) > num_known_refs + len(sub_threads)
164+
):
177165
for thread in sub_threads:
178166
if not thread.is_alive():
179167
sub_threads.remove(thread)

python/langsmith/_internal/_operations.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
import uuid
66
from typing import Literal, Optional, Union, cast
77

8+
import orjson
9+
810
from langsmith import schemas as ls_schemas
9-
from langsmith._internal import _orjson
1011
from langsmith._internal._multipart import MultipartPart, MultipartPartsAndContext
1112
from langsmith._internal._serde import dumps_json as _dumps_json
1213

@@ -168,12 +169,12 @@ def combine_serialized_queue_operations(
168169
if op._none is not None and op._none != create_op._none:
169170
# TODO optimize this more - this would currently be slowest
170171
# for large payloads
171-
create_op_dict = _orjson.loads(create_op._none)
172+
create_op_dict = orjson.loads(create_op._none)
172173
op_dict = {
173-
k: v for k, v in _orjson.loads(op._none).items() if v is not None
174+
k: v for k, v in orjson.loads(op._none).items() if v is not None
174175
}
175176
create_op_dict.update(op_dict)
176-
create_op._none = _orjson.dumps(create_op_dict)
177+
create_op._none = orjson.dumps(create_op_dict)
177178

178179
if op.inputs is not None:
179180
create_op.inputs = op.inputs

python/langsmith/_internal/_orjson.py

Lines changed: 0 additions & 84 deletions
This file was deleted.

python/langsmith/_internal/_serde.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import uuid
1313
from typing import Any
1414

15-
from langsmith._internal import _orjson
15+
import orjson
1616

1717
try:
1818
from zoneinfo import ZoneInfo # type: ignore[import-not-found]
@@ -133,13 +133,13 @@ def dumps_json(obj: Any) -> bytes:
133133
The JSON formatted string.
134134
"""
135135
try:
136-
return _orjson.dumps(
136+
return orjson.dumps(
137137
obj,
138138
default=_serialize_json,
139-
option=_orjson.OPT_SERIALIZE_NUMPY
140-
| _orjson.OPT_SERIALIZE_DATACLASS
141-
| _orjson.OPT_SERIALIZE_UUID
142-
| _orjson.OPT_NON_STR_KEYS,
139+
option=orjson.OPT_SERIALIZE_NUMPY
140+
| orjson.OPT_SERIALIZE_DATACLASS
141+
| orjson.OPT_SERIALIZE_UUID
142+
| orjson.OPT_NON_STR_KEYS,
143143
)
144144
except TypeError as e:
145145
# Usually caused by UTF surrogate characters
@@ -150,9 +150,9 @@ def dumps_json(obj: Any) -> bytes:
150150
ensure_ascii=True,
151151
).encode("utf-8")
152152
try:
153-
result = _orjson.dumps(
154-
_orjson.loads(result.decode("utf-8", errors="surrogateescape"))
153+
result = orjson.dumps(
154+
orjson.loads(result.decode("utf-8", errors="surrogateescape"))
155155
)
156-
except _orjson.JSONDecodeError:
156+
except orjson.JSONDecodeError:
157157
result = _elide_surrogates(result)
158158
return result

python/langsmith/_testing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from pathlib import Path
1313
from typing import Any, Callable, Optional, Sequence, Tuple, TypeVar, overload
1414

15+
import orjson
1516
from typing_extensions import TypedDict
1617

1718
from langsmith import client as ls_client
@@ -20,7 +21,6 @@
2021
from langsmith import run_trees as rt
2122
from langsmith import schemas as ls_schemas
2223
from langsmith import utils as ls_utils
23-
from langsmith._internal import _orjson
2424

2525
try:
2626
import pytest # type: ignore
@@ -374,7 +374,7 @@ def _serde_example_values(values: VT) -> VT:
374374
if values is None:
375375
return values
376376
bts = ls_client._dumps_json(values)
377-
return _orjson.loads(bts)
377+
return orjson.loads(bts)
378378

379379

380380
class _LangSmithTestSuite:

python/langsmith/client.py

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
)
5656
from urllib import parse as urllib_parse
5757

58+
import orjson
5859
import requests
5960
from requests import adapters as requests_adapters
6061
from requests_toolbelt import ( # type: ignore[import-untyped]
@@ -68,7 +69,6 @@
6869
from langsmith import env as ls_env
6970
from langsmith import schemas as ls_schemas
7071
from langsmith import utils as ls_utils
71-
from langsmith._internal import _orjson
7272
from langsmith._internal._background_thread import (
7373
TracingQueueItem,
7474
)
@@ -368,7 +368,6 @@ class Client:
368368
"_info",
369369
"_write_api_urls",
370370
"_settings",
371-
"_manual_cleanup",
372371
]
373372

374373
def __init__(
@@ -517,8 +516,6 @@ def __init__(
517516

518517
self._settings: Union[ls_schemas.LangSmithSettings, None] = None
519518

520-
self._manual_cleanup = False
521-
522519
def _repr_html_(self) -> str:
523520
"""Return an HTML representation of the instance with a link to the URL.
524521
@@ -1255,7 +1252,7 @@ def _hide_run_inputs(self, inputs: dict):
12551252
if self._hide_inputs is True:
12561253
return {}
12571254
if self._anonymizer:
1258-
json_inputs = _orjson.loads(_dumps_json(inputs))
1255+
json_inputs = orjson.loads(_dumps_json(inputs))
12591256
return self._anonymizer(json_inputs)
12601257
if self._hide_inputs is False:
12611258
return inputs
@@ -1265,7 +1262,7 @@ def _hide_run_outputs(self, outputs: dict):
12651262
if self._hide_outputs is True:
12661263
return {}
12671264
if self._anonymizer:
1268-
json_outputs = _orjson.loads(_dumps_json(outputs))
1265+
json_outputs = orjson.loads(_dumps_json(outputs))
12691266
return self._anonymizer(json_outputs)
12701267
if self._hide_outputs is False:
12711268
return outputs
@@ -1285,20 +1282,20 @@ def _batch_ingest_run_ops(
12851282
# form the partial body and ids
12861283
for op in ops:
12871284
if isinstance(op, SerializedRunOperation):
1288-
curr_dict = _orjson.loads(op._none)
1285+
curr_dict = orjson.loads(op._none)
12891286
if op.inputs:
1290-
curr_dict["inputs"] = _orjson.Fragment(op.inputs)
1287+
curr_dict["inputs"] = orjson.Fragment(op.inputs)
12911288
if op.outputs:
1292-
curr_dict["outputs"] = _orjson.Fragment(op.outputs)
1289+
curr_dict["outputs"] = orjson.Fragment(op.outputs)
12931290
if op.events:
1294-
curr_dict["events"] = _orjson.Fragment(op.events)
1291+
curr_dict["events"] = orjson.Fragment(op.events)
12951292
if op.attachments:
12961293
logger.warning(
12971294
"Attachments are not supported when use_multipart_endpoint "
12981295
"is False"
12991296
)
13001297
ids_and_partial_body[op.operation].append(
1301-
(f"trace={op.trace_id},id={op.id}", _orjson.dumps(curr_dict))
1298+
(f"trace={op.trace_id},id={op.id}", orjson.dumps(curr_dict))
13021299
)
13031300
elif isinstance(op, SerializedFeedbackOperation):
13041301
logger.warning(
@@ -1324,20 +1321,20 @@ def _batch_ingest_run_ops(
13241321
and body_size + len(body_deque[0][1]) > size_limit_bytes
13251322
):
13261323
self._post_batch_ingest_runs(
1327-
_orjson.dumps(body_chunks),
1324+
orjson.dumps(body_chunks),
13281325
_context=f"\n{key}: {'; '.join(context_ids[key])}",
13291326
)
13301327
body_size = 0
13311328
body_chunks.clear()
13321329
context_ids.clear()
13331330
curr_id, curr_body = body_deque.popleft()
13341331
body_size += len(curr_body)
1335-
body_chunks[key].append(_orjson.Fragment(curr_body))
1332+
body_chunks[key].append(orjson.Fragment(curr_body))
13361333
context_ids[key].append(curr_id)
13371334
if body_size:
13381335
context = "; ".join(f"{k}: {'; '.join(v)}" for k, v in context_ids.items())
13391336
self._post_batch_ingest_runs(
1340-
_orjson.dumps(body_chunks), _context="\n" + context
1337+
orjson.dumps(body_chunks), _context="\n" + context
13411338
)
13421339

13431340
def batch_ingest_runs(
@@ -2762,7 +2759,7 @@ def create_dataset(
27622759
"POST",
27632760
"/datasets",
27642761
headers={**self._headers, "Content-Type": "application/json"},
2765-
data=_orjson.dumps(dataset),
2762+
data=orjson.dumps(dataset),
27662763
)
27672764
ls_utils.raise_for_status_with_text(response)
27682765

@@ -5678,10 +5675,6 @@ def push_prompt(
56785675
)
56795676
return url
56805677

5681-
def cleanup(self) -> None:
5682-
"""Manually trigger cleanup of the background thread."""
5683-
self._manual_cleanup = True
5684-
56855678

56865679
def convert_prompt_to_openai_format(
56875680
messages: Any,

python/poetry.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pydantic = [
3131
{ version = "^2.7.4", python = ">=3.12.4" },
3232
]
3333
requests = "^2"
34-
orjson = { version = "^3.9.14", markers = "platform_python_implementation != 'PyPy'" }
34+
orjson = "^3.9.14"
3535
httpx = ">=0.23.0,<1"
3636
requests-toolbelt = "^1.0.0"
3737

python/tests/unit_tests/test_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from unittest.mock import MagicMock, patch
2323

2424
import dataclasses_json
25+
import orjson
2526
import pytest
2627
import requests
2728
from multipart import MultipartParser, MultipartPart, parse_options_header
@@ -32,7 +33,6 @@
3233
import langsmith.utils as ls_utils
3334
from langsmith import AsyncClient, EvaluationResult, run_trees
3435
from langsmith import schemas as ls_schemas
35-
from langsmith._internal import _orjson
3636
from langsmith._internal._serde import _serialize_json
3737
from langsmith.client import (
3838
Client,
@@ -848,7 +848,7 @@ class MyNamedTuple(NamedTuple):
848848
"set_with_class": set([MyClass(1)]),
849849
"my_mock": MagicMock(text="Hello, world"),
850850
}
851-
res = _orjson.loads(_dumps_json(to_serialize))
851+
res = orjson.loads(_dumps_json(to_serialize))
852852
assert (
853853
"model_dump" not in caplog.text
854854
), f"Unexpected error logs were emitted: {caplog.text}"
@@ -898,7 +898,7 @@ def __repr__(self) -> str:
898898
my_cyclic = CyclicClass(other=CyclicClass(other=None))
899899
my_cyclic.other.other = my_cyclic # type: ignore
900900

901-
res = _orjson.loads(_dumps_json({"cyclic": my_cyclic}))
901+
res = orjson.loads(_dumps_json({"cyclic": my_cyclic}))
902902
assert res == {"cyclic": "my_cycles..."}
903903
expected = {"foo": "foo", "bar": 1}
904904

@@ -1142,7 +1142,7 @@ def test_batch_ingest_run_splits_large_batches(
11421142
op
11431143
for call in mock_session.request.call_args_list
11441144
for reqs in (
1145-
_orjson.loads(call[1]["data"]).values() if call[0][0] == "POST" else []
1145+
orjson.loads(call[1]["data"]).values() if call[0][0] == "POST" else []
11461146
)
11471147
for op in reqs
11481148
]

0 commit comments

Comments
 (0)