Skip to content

Commit

Permalink
No dist
Browse files Browse the repository at this point in the history
  • Loading branch information
hinthornw committed Nov 6, 2024
1 parent 4fc1d31 commit fd7026f
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 53 deletions.
20 changes: 10 additions & 10 deletions .github/actions/python-integration-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ runs:
shell: bash
working-directory: python

- name: Run integration tests
env:
LANGCHAIN_TRACING_V2: "true"
LANGCHAIN_ENDPOINT: https://beta.api.smith.langchain.com
LANGCHAIN_API_KEY: ${{ inputs.langchain-api-key-beta }}
OPENAI_API_KEY: ${{ inputs.openai-api-key }}
LANGSMITH_TEST_CACHE: tests/cassettes
run: make integration_tests
shell: bash
working-directory: python
# - name: Run integration tests
# env:
# LANGCHAIN_TRACING_V2: "true"
# LANGCHAIN_ENDPOINT: https://beta.api.smith.langchain.com
# LANGCHAIN_API_KEY: ${{ inputs.langchain-api-key-beta }}
# OPENAI_API_KEY: ${{ inputs.openai-api-key }}
# LANGSMITH_TEST_CACHE: tests/cassettes
# run: make integration_tests
# shell: bash
# working-directory: python

- name: Run doctest
env:
Expand Down
5 changes: 4 additions & 1 deletion python/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@ integration_tests:
poetry run python -m pytest -v --durations=10 --cov=langsmith --cov-report=term-missing --cov-report=html --cov-config=.coveragerc tests/integration_tests

integration_tests_fast:
poetry run python -m pytest -n auto --durations=10 -v --cov=langsmith --cov-report=term-missing --cov-report=html --cov-config=.coveragerc tests/integration_tests
poetry run python -m pytest -n auto --durations=10 -v --cov=langsmith --cov-report=term-missing --cov-report=html --cov-config=.coveragerc --capture=no tests/integration_tests

doctest:
poetry run python -m pytest -vv --capture=no --durations=10 --doctest-modules langsmith/evaluation

doctest_fast:
poetry run python -m pytest -n auto --durations=10 --doctest-modules langsmith

evals:
Expand Down
11 changes: 10 additions & 1 deletion python/langsmith/_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,16 @@ async def _test():
with rh.tracing_context(
**{**current_context, "metadata": metadata}
), ls_utils.with_optional_cache(
cache_path, ignore_hosts=[test_suite.client.api_url]
cache_path,
ignore_hosts=list(
set(
(
test_suite.client.api_url,
"https://beta.api.smith.langchain.com",
"https://api.smith.langchain.com",
)
)
),
):
await _test()

Expand Down
1 change: 1 addition & 0 deletions python/langsmith/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,7 @@ def request_with_retries(
raise ls_utils.LangSmithError(
f"Failed to {method} {pathname} in LangSmith API. {emsg}"
f"{_context}"
f"{ls_utils._CACHE_HANDLES}"
) from e
except to_ignore_ as e:
if response is not None:
Expand Down
19 changes: 13 additions & 6 deletions python/langsmith/evaluation/_arunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,10 @@ async def aevaluate(
Evaluating over only a subset of the examples using an async generator:
>>> async def example_generator():
... examples = client.list_examples(dataset_name=dataset_name, limit=5)
... for example in examples:
... yield example
>>> results = asyncio.run(
... aevaluate(
... apredict,
... data=example_generator(),
... data=client.list_examples(dataset_name=dataset_name, limit=5),
... evaluators=[accuracy],
... summary_evaluators=[precision],
... experiment_prefix="My Subset Experiment",
Expand Down Expand Up @@ -405,7 +401,18 @@ async def _aevaluate(
cache_path = pathlib.Path(cache_dir) / f"{dsid}.yaml"
else:
cache_path = None
with ls_utils.with_optional_cache(cache_path, ignore_hosts=[client.api_url]):
with ls_utils.with_optional_cache(
cache_path,
ignore_hosts=list(
set(
(
client.api_url,
"https://beta.api.smith.langchain.com",
"https://api.smith.langchain.com",
)
)
),
):
if is_async_target:
manager = await manager.awith_predictions(
cast(ATARGET_T, target), max_concurrency=max_concurrency
Expand Down
13 changes: 12 additions & 1 deletion python/langsmith/evaluation/_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,18 @@ def _evaluate(
cache_path = (
pathlib.Path(cache_dir) / f"{manager.dataset_id}.yaml" if cache_dir else None
)
with ls_utils.with_optional_cache(cache_path, ignore_hosts=[client.api_url]):
with ls_utils.with_optional_cache(
cache_path,
ignore_hosts=list(
set(
(
client.api_url,
"https://beta.api.smith.langchain.com",
"https://api.smith.langchain.com",
)
)
),
):
if _is_callable(target):
# Add predictions to the experiment.
manager = manager.with_predictions(
Expand Down
81 changes: 47 additions & 34 deletions python/langsmith/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,15 +480,20 @@ def get_cache_dir(cache: Optional[str]) -> Optional[str]:
return get_env_var("TEST_CACHE", default=None)


_OPEN_CACHES = {}
_CACHE_HANDLES = {}
_CACHE_LOCK = threading.RLock()


@contextlib.contextmanager
def with_cache(
path: Union[str, pathlib.Path], ignore_hosts: Optional[Sequence[str]] = None
) -> Generator[None, None, None]:
"""Use a cache for requests."""
global _OPEN_CACHES
print(
f"FOO TRYING FOR CACHE : {path} {ignore_hosts}",
flush=True,
file=sys.stderr,
)
try:
import vcr # type: ignore[import-untyped]
except ImportError:
Expand All @@ -498,48 +503,56 @@ def with_cache(
)

def _filter_request_headers(request: Any) -> Any:
print(f"Request: {repr(request)}: {ignore_hosts}", file=sys.stderr, flush=True)
if ignore_hosts and any(request.url.startswith(host) for host in ignore_hosts):
print(f"Ignoring URL: {request.url}", file=sys.stderr, flush=True)
return None
request.headers = {}
return request

cache_dir, cache_file = os.path.split(path)
if _OPEN_CACHES:
print(
f"{len(_OPEN_CACHES)}ALREADY OPEN: {_OPEN_CACHES}",
file=sys.stderr,
flush=True,
)
else:

print(
"NEW CACHE",
file=sys.stderr,
flush=True,
)
with _CACHE_LOCK:
if path not in _CACHE_HANDLES:
ls_vcr = vcr.VCR(
serializer=(
"yaml"
if cache_file.endswith(".yaml") or cache_file.endswith(".yml")
else "json"
),
cassette_library_dir=cache_dir,
record_mode="new_episodes",
match_on=["uri", "method", "path", "body"],
filter_headers=["authorization", "Set-Cookie"],
before_record_request=_filter_request_headers,
)

ls_vcr = vcr.VCR(
serializer=(
"yaml"
if cache_file.endswith(".yaml") or cache_file.endswith(".yml")
else "json"
),
cassette_library_dir=cache_dir,
# Replay previous requests, record new ones
# TODO: Support other modes
record_mode="new_episodes",
match_on=["uri", "method", "path", "body"],
filter_headers=["authorization", "Set-Cookie"],
before_record_request=_filter_request_headers,
)
with ls_vcr.use_cassette(cache_file):
_OPEN_CACHES.setdefault(str(cache_file), 0)
_OPEN_CACHES[str(cache_file)] += 1
cassette = ls_vcr.use_cassette(cache_file)
_CACHE_HANDLES[path] = (1, cassette)
print(f"FOO ENTERING CASSETTE: {path}", file=sys.stderr, flush=True)
cassette.__enter__()
else:
existing, handle = _CACHE_HANDLES[path]
print(f"FOO ALREADY MADE: {existing} - {path}", file=sys.stderr, flush=True)
_CACHE_HANDLES[path] = (existing + 1, handle)

try:
yield
_OPEN_CACHES[str(cache_file)] -= 1
if _OPEN_CACHES[str(cache_file)] == 0:
_OPEN_CACHES.pop(str(cache_file), 0)
finally:
with _CACHE_LOCK:
count, handle = _CACHE_HANDLES[path]
count -= 1
if count == 0:
print(f"FOO EXITING HANDLE: {path}", file=sys.stderr, flush=True)
handle.__exit__(None, None, None)
del _CACHE_HANDLES[path]
else:
print(
f"FOO DECREMENTING COUNT: {count} - {path}",
file=sys.stderr,
flush=True,
)
_CACHE_HANDLES[path] = (count, handle)


@contextlib.contextmanager
Expand Down

0 comments on commit fd7026f

Please sign in to comment.