mirror of
https://github.com/langchain-ai/langserve.git
synced 2026-07-01 20:14:01 -04:00
Compare commits
87 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5bf2092bca | |||
| 12e5d8e23f | |||
| 970cbc7342 | |||
| 13cdfe0b7c | |||
| d442dbc712 | |||
| 0a2a03cc83 | |||
| 619e176fa4 | |||
| d09daaaeb2 | |||
| ff94a9248f | |||
| 73b59980e6 | |||
| 279630ca2c | |||
| ad0c8a8ce1 | |||
| 81fa67452f | |||
| 0cf1cdb692 | |||
| 1d40334f07 | |||
| ffd3ec1e4b | |||
| c7331426ad | |||
| 1f35a9186a | |||
| 3436a68908 | |||
| 671371df0f | |||
| 42696df0d2 | |||
| 57503807b7 | |||
| b19fa6640a | |||
| c4d5b8ad2a | |||
| b3cb77a649 | |||
| 58a7c24429 | |||
| c01d65ba3c | |||
| 09fd6de4aa | |||
| 81bffe199f | |||
| e2353612f8 | |||
| 9001867cc1 | |||
| 81152822bc | |||
| fa7f3b828b | |||
| 6b53d46321 | |||
| 79bf88aa7a | |||
| 2007e07a83 | |||
| ad24198ad6 | |||
| 0b1e78db0b | |||
| 5eff20817d | |||
| 5a6f73cdf6 | |||
| 243b9ed35e | |||
| 7a89867dd2 | |||
| 56e0d5dc9c | |||
| 6c255acd8f | |||
| 8aa1e86ab3 | |||
| 3fc780e472 | |||
| 404cab2506 | |||
| db4c41fcb3 | |||
| d592a8abd9 | |||
| 8721a82087 | |||
| 0c1cb7f800 | |||
| f0d86287ab | |||
| 168c9ff90e | |||
| a87125d0b8 | |||
| 1de17fa799 | |||
| 1a08f2740c | |||
| 06c3c3691e | |||
| d20eab45f2 | |||
| 321b7aa3b1 | |||
| aa4aea4a81 | |||
| 1aaec1189c | |||
| 0d7601781d | |||
| 0ad075fb67 | |||
| b007300b06 | |||
| 9df7e88bb9 | |||
| c626cde08c | |||
| c4a8925b00 | |||
| 80f949b62e | |||
| c27923a7d1 | |||
| f3b9c43106 | |||
| 6b1a0d97ef | |||
| dc04672537 | |||
| 42b61a664b | |||
| 1e24edce08 | |||
| c747e20c1e | |||
| 8b4d8dff6c | |||
| 2c957bdd78 | |||
| 36f945e494 | |||
| 43683b3671 | |||
| 59b3c81189 | |||
| 36e9919c17 | |||
| ff94f96dc8 | |||
| 8c852935e5 | |||
| 04236b0cf2 | |||
| 54eee64faf | |||
| 72c200ff81 | |||
| 21c2e3da2a |
@@ -1,4 +1,4 @@
|
||||
{
|
||||
"contributors": ["eyurtsev", "hwchase17", "nfcampos", "efriis", "jacoblee93", "dqbd", "kreneskyp", "adarsh-jha-dev", "harris", "baskaryan", "hinthornw", "bracesproul", "jakerachleff", "craigsdennis", "anhi", "169", "LarchLiu", "PaulLockett", "RCMatthias", "jwynia", "majiayu000", "mpskex", "shivachittamuru", "sinashaloudegi", "sowsan", "akira", "lucianotonet", "JGalego", "nat-n", "dirien", "donbr", "rahilvora", "WarrenTheRabbit", "StreetLamb", "ccurme", "dennisrall"],
|
||||
"contributors": ["eyurtsev", "hwchase17", "nfcampos", "efriis", "jacoblee93", "dqbd", "kreneskyp", "adarsh-jha-dev", "harris", "baskaryan", "hinthornw", "bracesproul", "jakerachleff", "craigsdennis", "anhi", "169", "LarchLiu", "PaulLockett", "RCMatthias", "jwynia", "majiayu000", "mpskex", "shivachittamuru", "sinashaloudegi", "sowsan", "akira", "lucianotonet", "JGalego", "nat-n", "dirien", "donbr", "rahilvora", "WarrenTheRabbit", "StreetLamb", "ccurme", "dennisrall", "Mingqi2", "xxsl", "joaquin-borggio-lc"],
|
||||
"message": "Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have the username {{usersWithoutCLA}} on file. In order for us to review and merge your code, please complete the Individual Contributor License Agreement here https://forms.gle/AQFbtkWRoHXUgipM6 .\n\nThis process is done manually on our side, so after signing the form one of the maintainers will add you to the contributors list.\n\nFor more details about why we have a CLA and other contribution guidelines please see: https://github.com/langchain-ai/langserve/blob/main/CONTRIBUTING.md."
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "pip" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "github-actions" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: "npm" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -1,4 +1,6 @@
|
||||
name: lint
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
@@ -31,10 +33,10 @@ jobs:
|
||||
# Starting new jobs is also relatively slow,
|
||||
# so linting on fewer versions makes CI faster.
|
||||
python-version:
|
||||
- "3.8"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
# Fetch the last FETCH_DEPTH commits, so the mtime-changing script
|
||||
# can accurately set the mtimes of files modified in the last FETCH_DEPTH commits.
|
||||
@@ -115,7 +117,7 @@ jobs:
|
||||
poetry install --with dev,lint,test,typing
|
||||
|
||||
- name: Restore black cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v5
|
||||
env:
|
||||
CACHE_BASE: black-${{ runner.os }}-${{ runner.arch }}-py${{ matrix.python-version }}-${{ inputs.working-directory }}-${{ hashFiles(format('{0}/poetry.lock', env.WORKDIR)) }}
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "1"
|
||||
@@ -128,7 +130,7 @@ jobs:
|
||||
${{ env.CACHE_BASE }}-
|
||||
|
||||
- name: Get .mypy_cache to speed up mypy
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v5
|
||||
env:
|
||||
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "2"
|
||||
with:
|
||||
|
||||
@@ -7,6 +7,12 @@ on:
|
||||
required: true
|
||||
type: string
|
||||
description: "From which folder this pipeline executes"
|
||||
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
|
||||
inputs:
|
||||
working-directory:
|
||||
required: true
|
||||
type: string
|
||||
description: "From which folder this pipeline executes"
|
||||
|
||||
env:
|
||||
POETRY_VERSION: "1.5.1"
|
||||
@@ -30,7 +36,7 @@ jobs:
|
||||
run:
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
|
||||
uses: "./.github/actions/poetry_setup"
|
||||
|
||||
@@ -20,13 +20,11 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
name: Python ${{ matrix.python-version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
|
||||
uses: "./.github/actions/poetry_setup"
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
run:
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python + Poetry ${{ env.POETRY_VERSION }}
|
||||
uses: "./.github/actions/poetry_setup"
|
||||
|
||||
@@ -18,6 +18,10 @@ on:
|
||||
- 'Makefile'
|
||||
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
|
||||
|
||||
# This workflow only needs to read the repo contents.
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
# If another push to the same PR or branch happens while this workflow is still running,
|
||||
# cancel the earlier run in favor of the next run.
|
||||
#
|
||||
@@ -48,13 +52,11 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
python-version:
|
||||
- "3.8"
|
||||
- "3.9"
|
||||
- "3.10"
|
||||
- "3.11"
|
||||
name: Python ${{ matrix.python-version }} tests
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python ${{ matrix.python-version }} + Poetry ${{ env.POETRY_VERSION }}
|
||||
uses: "./.github/actions/poetry_setup"
|
||||
|
||||
@@ -4,11 +4,18 @@ name: Release
|
||||
on:
|
||||
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
uses:
|
||||
./.github/workflows/_release.yml
|
||||
with:
|
||||
working-directory: .
|
||||
permissions: write-all
|
||||
permissions:
|
||||
# Trusted publishing to PyPI
|
||||
id-token: write
|
||||
# Creating GitHub releases
|
||||
contents: write
|
||||
secrets: inherit
|
||||
|
||||
@@ -4,10 +4,16 @@ name: Test Release
|
||||
on:
|
||||
workflow_dispatch: # Allows to trigger the workflow manually in GitHub UI
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
uses:
|
||||
./.github/workflows/_test_release.yml
|
||||
with:
|
||||
working-directory: .
|
||||
permissions:
|
||||
# Trusted publishing to TestPyPI
|
||||
id-token: write
|
||||
secrets: inherit
|
||||
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
# LangGraph Platform Migration Guide
|
||||
|
||||
We have [recently announced](https://blog.langchain.dev/langgraph-platform-announce/) LangGraph Platform, a ***significantly*** enhanced solution for deploying agentic applications at scale.
|
||||
|
||||
LangGraph Platform incorporates [key design patterns and capabilities](https://langchain-ai.github.io/langgraph/concepts/langgraph_platform/#option-2-leveraging-langgraph-platform-for-complex-deployments) essential for production-level deployment of large language model (LLM) applications.
|
||||
|
||||
In contrast to LangServe, LangGraph Platform provides comprehensive, out-of-the-box support for [persistence](https://langchain-ai.github.io/langgraph/concepts/application_structure/), [memory](https://langchain-ai.github.io/langgraph/concepts/assistants/), [double-texting handling](https://langchain-ai.github.io/langgraph/concepts/double_texting/), [human-in-the-loop workflows](https://langchain-ai.github.io/langgraph/concepts/assistants/), [cron job scheduling](https://langchain-ai.github.io/langgraph/concepts/langgraph_server/#cron-jobs), [webhooks](https://langchain-ai.github.io/langgraph/concepts/langgraph_server/#webhooks), high-load management, advanced streaming, support for long-running tasks, background task processing, and much more.
|
||||
|
||||
The LangGraph Platform ecosystem includes the following components:
|
||||
|
||||
- [LangGraph Server](https://langchain-ai.github.io/langgraph/concepts/langgraph_server/): Provides an [Assistants API](https://langchain-ai.github.io/langgraph/cloud/reference/api/api_ref.html) for LLM applications (graphs) built with [LangGraph](https://langchain-ai.github.io/langgraph/). Available in both Python and JavaScript/TypeScript.
|
||||
- [LangGraph Studio](https://langchain-ai.github.io/langgraph/concepts/langgraph_studio/): A specialized IDE for real-time visualization, debugging, and interaction via a graphical interface. Available as a web application or macOS desktop app, it's a substantial improvement over LangServe's playground.
|
||||
- [SDK](https://langchain-ai.github.io/langgraph/concepts/sdk/): Enables programmatic interaction with the server, available in Python and JavaScript/TypeScript.
|
||||
- [RemoteGraph](https://langchain-ai.github.io/langgraph/how-tos/use-remote-graph/): Allows interaction with a remote graph as if it were running locally, serving as LangGraph's equivalent to LangServe's RemoteRunnable. Available in both Python and JavaScript/TypeScript.
|
||||
|
||||
## Context
|
||||
|
||||
LangServe was built as a deployment solution for LangChain Runnables created using the [LangChain Expression Language (LCEL)](https://python.langchain.com/docs/concepts/lcel). In LangServe, the LCEL was the orchestration layer that managed the execution of the Runnable.
|
||||
|
||||
[LangGraph](https://langchain-ai.github.io/langgraph/) is an open source library created by the LangChain team that provides a more flexible orchestration layer that's better suited for creating more complex LLM applications. LangGraph Platform
|
||||
is the deployment solution for LangGraph applications.
|
||||
|
||||
## LangServe Support
|
||||
|
||||
We recommend using LangGraph Platform rather than LangServe for new projects.
|
||||
|
||||
We will continue to accept bug fixes for LangServe from the community; however, we will not be accepting new feature contributions.
|
||||
|
||||
## Migration
|
||||
|
||||
If you would like to migrate an existing LangServe application to LangGraph Platform, you have two options:
|
||||
|
||||
1. You can wrap the existing `Runnable` that you expose in the LangServe application via `add_routes` in a `LangGraph` node. This is the quickest way to migrate your application to LangGraph Platform.
|
||||
2. You can do a larger refactor to break up the existing LCEL into appropriate `LangGraph` nodes. This is recommended if you want to take advantage of more advanced features in LangGraph Platform.
|
||||
|
||||
### Option 1: Wrap Runnable in LangGraph Node
|
||||
|
||||
This option is the quickest way to migrate your application to LangGraph Platform. You can wrap the existing `Runnable` that you expose in the LangServe application via `add_routes` in a `LangGraph` node.
|
||||
|
||||
|
||||
Original LangServe code:
|
||||
|
||||
```python
|
||||
from langserve import add_routes
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
# Some input schema
|
||||
class Input(BaseModel):
|
||||
input: str
|
||||
foo: Optional[str]
|
||||
|
||||
# Some output schema
|
||||
class Output(BaseModel):
|
||||
output: Any
|
||||
|
||||
|
||||
runnable = .... # Your existing Runnable
|
||||
runnable_with_types = runnable.with_types(input_type=Input, output_type=Output)
|
||||
|
||||
# Adds routes to the app for using the chain under:
|
||||
add_routes(
|
||||
app,
|
||||
runnable_with_types,
|
||||
)
|
||||
```
|
||||
|
||||
Migrated LangGraph Platform code:
|
||||
|
||||
```python
|
||||
|
||||
@dataclass
|
||||
class InputState: # Equivalent to Input in the original code
|
||||
"""Defines the input state, representing a narrower interface to the outside world.
|
||||
|
||||
This class is used to define the initial state and structure of incoming data.
|
||||
See: https://langchain-ai.github.io/langgraph/concepts/low_level/#state
|
||||
for more information.
|
||||
"""
|
||||
|
||||
input: str
|
||||
foo: Optional[str] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class OutputState: # Equivalent to Output in the original code
|
||||
"""Defines the output state, representing a narrower interface to the outside world.
|
||||
|
||||
https://langchain-ai.github.io/langgraph/concepts/low_level/#state
|
||||
"""
|
||||
output: Any
|
||||
|
||||
@dataclass
|
||||
class SharedState:
|
||||
"""The full graph state.
|
||||
|
||||
https://langchain-ai.github.io/langgraph/concepts/low_level/#state
|
||||
"""
|
||||
input: str
|
||||
foo: Optional[str] = None
|
||||
output: Any
|
||||
|
||||
runnable = ... # Same code as before
|
||||
|
||||
async def my_node(state: InputState, config: RunnableConfig) -> OutputState:
|
||||
"""Each node does work."""
|
||||
return await runnable.ainvoke({"input": state.input, "foo": state.foo})
|
||||
|
||||
|
||||
# Define a new graph
|
||||
builder = StateGraph(
|
||||
SharedState, config_schema=Configuration, input=InputState, output=OutputState
|
||||
)
|
||||
|
||||
# Add the node to the graph
|
||||
builder.add_node("my_node", my_node)
|
||||
|
||||
# Set the entrypoint as `call_model`
|
||||
builder.add_edge("__start__", "my_node")
|
||||
|
||||
# Compile the workflow into an executable graph
|
||||
graph = builder.compile()
|
||||
graph.name = "New Graph" # This defines the custom name in LangSmith
|
||||
```
|
||||
|
||||
### 2. Refactor LCEL into LangGraph Nodes
|
||||
|
||||
This option is recommended if you want to take advantage of more advanced features in LangGraph Platform.
|
||||
|
||||
#### Memory (alternative to `RunnableWithMessageHistory`)
|
||||
|
||||
For example, LangGraph comes with built-in persistence that is more general than LangChain's `RunnableWithMessageHistory`.
|
||||
|
||||
Please refer to the guide on [upgrading to LangGraph memory](https://python.langchain.com/docs/versions/migrating_memory/) for more details.
|
||||
|
||||
#### Agents
|
||||
|
||||
If you're relying on legacy LangChain agents, you can migrate them into the pre-built
|
||||
LangGraph agents. Please refer to the guide on [migrating agents](https://python.langchain.com/docs/how_to/migrate_agent/) for more details.
|
||||
|
||||
#### Custom Chains
|
||||
|
||||
If you created a custom chain and used LCEL to orchestrate it, you will usually be able to refactor it into a LangGraph without too much difficulty.
|
||||
|
||||
There isn't a one-size-fits-all guide for this, but generally speaking, consider creating
|
||||
a separate node for any long-running step in your LCEL chain or any step that you would
|
||||
want to be able to monitor or debug separately.
|
||||
|
||||
For example, if you have a simple Retrieval Augmented Generation (RAG) pipeline, you might have a node for the retrieval step and a node for the generation step.
|
||||
|
||||
Original LCEL code:
|
||||
|
||||
```python
|
||||
...
|
||||
rag_chain = (
|
||||
{"context": retriever | format_docs, "question": RunnablePassthrough()}
|
||||
| prompt
|
||||
| llm
|
||||
| StrOutputParser()
|
||||
)
|
||||
rag_chain.with_types(input_type=Input, output_type=Output)
|
||||
```
|
||||
|
||||
Using LangGraph for the same pipeline:
|
||||
|
||||
|
||||
```python
|
||||
|
||||
@dataclass
|
||||
class InputState: # Equivalent to Input in the original code
|
||||
"""Input question from the user."""
|
||||
question: str
|
||||
|
||||
@dataclass
|
||||
class OutputState: # Equivalent to Output in the original code
|
||||
"""The output from the graph."""
|
||||
answer: str
|
||||
|
||||
@dataclass
|
||||
class SharedState:
|
||||
question: str
|
||||
docs: List[str]
|
||||
response: str
|
||||
|
||||
async def retriever_node(state: InputState) -> SharedState:
|
||||
"""Rettrieve documents based on the user's question."""
|
||||
documents = await retriever.ainvoke({"context": state.question})
|
||||
return {
|
||||
"docs": documents
|
||||
}
|
||||
|
||||
async def generator_node(state: SharedState) -> OutputState:
|
||||
"""Generate an answer using an LLM based on the retrieved documents and question."""
|
||||
context = " -- DOCUMENT -- ".join(state.docs)
|
||||
prompt = [
|
||||
SystemMessage(
|
||||
content=(
|
||||
"Answer the user's question based on the list of documents "
|
||||
"that were retrieved. Here are the documents: \n\n"
|
||||
f"{context}"
|
||||
)
|
||||
),
|
||||
HumanMessage(content=state.question),
|
||||
]
|
||||
ai_message = await llm.ainvoke(prompt)
|
||||
return {"answer": ai_message.content}
|
||||
|
||||
# Define a new graph
|
||||
builder = StateGraph(
|
||||
SharedState, config_schema=Configuration, input=InputState, output=OutputState
|
||||
)
|
||||
builder.add_node("retriever", retriever_node)
|
||||
builder.add_node("generator", generator_node)
|
||||
builder.add_edge("__start__", "retriever")
|
||||
builder.add_edge("retriever", "generator")
|
||||
graph = builder.compile()
|
||||
graph.name = "RAG Graph"
|
||||
```
|
||||
|
||||
Please see the [LangGraph tutorials](https://langchain-ai.github.io/langgraph/tutorials/)
|
||||
for tutorials and examples that will help you get started with LangGraph
|
||||
and LangGraph Platform.
|
||||
@@ -32,12 +32,12 @@ lint format: PYTHON_FILES=.
|
||||
lint_diff format_diff: PYTHON_FILES=$(shell git diff --relative=. --name-only --diff-filter=d master | grep -E '\.py$$|\.ipynb$$')
|
||||
|
||||
lint lint_diff:
|
||||
poetry run ruff .
|
||||
poetry run ruff check .
|
||||
poetry run ruff format $(PYTHON_FILES) --check
|
||||
|
||||
format format_diff:
|
||||
poetry run ruff format $(PYTHON_FILES)
|
||||
poetry run ruff --select I --fix $(PYTHON_FILES)
|
||||
poetry run ruff check --select I --fix $(PYTHON_FILES)
|
||||
|
||||
spell_check:
|
||||
poetry run codespell --toml pyproject.toml
|
||||
|
||||
@@ -5,6 +5,15 @@
|
||||
[](https://github.com/langchain-ai/langserve/issues)
|
||||
[](https://discord.com/channels/1038097195422978059/1170024642245832774)
|
||||
|
||||
> [!WARNING]
|
||||
> We recommend using LangGraph Platform rather than LangServe for new projects.
|
||||
>
|
||||
> Please see the [LangGraph Platform Migration Guide](./MIGRATION.md) for more information.
|
||||
>
|
||||
> We will continue to accept bug fixes for LangServe from the community; however, we
|
||||
> will not be accepting new feature contributions.
|
||||
|
||||
|
||||
## Overview
|
||||
|
||||
[LangServe](https://github.com/langchain-ai/langserve) helps developers
|
||||
@@ -40,7 +49,7 @@ in [LangChain.js](https://js.langchain.com/docs/ecosystem/langserve).
|
||||
|
||||
## ⚠️ LangGraph Compatibility
|
||||
|
||||
LangServe is designed to primarily deploy simple Runnables and wok with well-known primitives in langchain-core.
|
||||
LangServe is designed to primarily deploy simple Runnables and work with well-known primitives in langchain-core.
|
||||
|
||||
If you need a deployment option for LangGraph, you should instead be looking at [LangGraph Cloud (beta)](https://langchain-ai.github.io/langgraph/cloud/) which will
|
||||
be better suited for deploying LangGraph applications.
|
||||
@@ -48,9 +57,8 @@ be better suited for deploying LangGraph applications.
|
||||
## Limitations
|
||||
|
||||
- Client callbacks are not yet supported for events that originate on the server
|
||||
- OpenAPI docs will not be generated when using Pydantic V2. Fast API does not
|
||||
support [mixing pydantic v1 and v2 namespaces](https://github.com/tiangolo/fastapi/issues/10360).
|
||||
See section below for more details.
|
||||
- Versions of LangServe <= 0.2.0, will not generate OpenAPI docs properly when using Pydantic V2 as Fast API does not support [mixing pydantic v1 and v2 namespaces](https://github.com/tiangolo/fastapi/issues/10360).
|
||||
See section below for more details. Either upgrade to LangServe>=0.3.0 or downgrade Pydantic to pydantic 1.
|
||||
|
||||
## Security
|
||||
|
||||
@@ -92,7 +100,7 @@ langchain app new my-app
|
||||
add_routes(app. NotImplemented)
|
||||
```
|
||||
|
||||
### 3. Use `poetry` to add 3rd party packages (e.g., langchain-openai, langchain-anthropic, langchain-mistral etc).
|
||||
### 3. Use `poetry` to add 3rd party packages (e.g., langchain-openai, langchain-anthropic, langchain-mistral, etc).
|
||||
|
||||
```sh
|
||||
poetry add [package-name] // e.g `poetry add langchain-openai`
|
||||
@@ -112,12 +120,7 @@ poetry run langchain serve --port=8100
|
||||
|
||||
## Examples
|
||||
|
||||
Get your LangServe instance started quickly with
|
||||
[LangChain Templates](https://github.com/langchain-ai/langchain/blob/master/templates/README.md).
|
||||
|
||||
For more examples, see the templates
|
||||
[index](https://github.com/langchain-ai/langchain/blob/master/templates/docs/INDEX.md)
|
||||
or the [examples](https://github.com/langchain-ai/langserve/tree/main/examples)
|
||||
Get your LangServe instances started quickly with the [examples](https://github.com/langchain-ai/langserve/tree/main/examples)
|
||||
directory.
|
||||
|
||||
| Description | Links |
|
||||
@@ -208,8 +211,9 @@ app.add_middleware(
|
||||
|
||||
If you've deployed the server above, you can view the generated OpenAPI docs using:
|
||||
|
||||
> ⚠️ If using pydantic v2, docs will not be generated for _invoke_, _batch_, _stream_,
|
||||
> ⚠️ If using LangServe <= 0.2.0 and pydantic v2, docs will not be generated for _invoke_, _batch_, _stream_,
|
||||
> _stream_log_. See [Pydantic](#pydantic) section below for more details.
|
||||
> To resolve please upgrade to LangServe 0.3.0.
|
||||
|
||||
```sh
|
||||
curl localhost:8000/docs
|
||||
@@ -380,7 +384,7 @@ prompt = ChatPromptTemplate.from_messages(
|
||||
]
|
||||
)
|
||||
|
||||
chain = prompt | ChatAnthropic(model="claude-2")
|
||||
chain = prompt | ChatAnthropic(model="claude-2.1")
|
||||
|
||||
|
||||
class InputChat(BaseModel):
|
||||
@@ -472,7 +476,9 @@ gcloud run deploy [your-service-name] --source . --port 8001 --allow-unauthentic
|
||||
|
||||
## Pydantic
|
||||
|
||||
LangServe provides support for Pydantic 2 with some limitations.
|
||||
LangServe>=0.3 fully supports Pydantic 2.
|
||||
|
||||
If you're using an earlier version of LangServe (<= 0.2), then please note that support for Pydantic 2 has the following limitations:
|
||||
|
||||
1. OpenAPI docs will not be generated for invoke/batch/stream/stream_log when using
|
||||
Pydantic V2. Fast API does not support [mixing pydantic v1 and v2 namespaces]. To fix this, use `pip install pydantic==1.10.17`.
|
||||
@@ -772,7 +778,7 @@ prompt = ChatPromptTemplate.from_messages(
|
||||
]
|
||||
)
|
||||
|
||||
chain = prompt | ChatAnthropic(model="claude-2")
|
||||
chain = prompt | ChatAnthropic(model="claude-2.1")
|
||||
|
||||
|
||||
class MessageListInput(BaseModel):
|
||||
|
||||
@@ -35,7 +35,7 @@ from typing import Any, List, Optional, Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Request, Response, status
|
||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||
from langchain_community.vectorstores.chroma import Chroma
|
||||
from langchain_chroma import Chroma
|
||||
from langchain_core.documents import Document
|
||||
from langchain_core.runnables import (
|
||||
ConfigurableField,
|
||||
|
||||
@@ -36,7 +36,7 @@ from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from fastapi import Depends, FastAPI, HTTPException, Request, status
|
||||
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
|
||||
from langchain_community.vectorstores.chroma import Chroma
|
||||
from langchain_chroma import Chroma
|
||||
from langchain_core.documents import Document
|
||||
from langchain_core.runnables import (
|
||||
ConfigurableField,
|
||||
|
||||
@@ -28,7 +28,7 @@ prompt = ChatPromptTemplate.from_messages(
|
||||
]
|
||||
)
|
||||
|
||||
chain = prompt | ChatAnthropic(model="claude-2")
|
||||
chain = prompt | ChatAnthropic(model="claude-2.1")
|
||||
|
||||
|
||||
class InputChat(BaseModel):
|
||||
|
||||
@@ -76,7 +76,7 @@ prompt = ChatPromptTemplate.from_messages(
|
||||
]
|
||||
)
|
||||
|
||||
chain = prompt | ChatAnthropic(model="claude-2")
|
||||
chain = prompt | ChatAnthropic(model="claude-2.1")
|
||||
|
||||
|
||||
class InputChat(BaseModel):
|
||||
|
||||
@@ -23,14 +23,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import requests\n",
|
||||
"\n",
|
||||
"inputs = {\"input\": {\"topic\": \"sports\"}}\n",
|
||||
"response = requests.post(\"http://localhost:8000/configurable_temp/invoke\", json=inputs)\n",
|
||||
"\n",
|
||||
"response.json()"
|
||||
]
|
||||
"source": ["import requests\n\ninputs = {\"input\": {\"topic\": \"sports\"}}\nresponse = requests.post(\"http://localhost:8000/configurable_temp/invoke\", json=inputs)\n\nresponse.json()"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -46,11 +39,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langserve import RemoteRunnable\n",
|
||||
"\n",
|
||||
"remote_runnable = RemoteRunnable(\"http://localhost:8000/configurable_temp\")"
|
||||
]
|
||||
"source": ["from langserve import RemoteRunnable\n\nremote_runnable = RemoteRunnable(\"http://localhost:8000/configurable_temp\")"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -66,9 +55,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"response = await remote_runnable.ainvoke({\"topic\": \"sports\"})"
|
||||
]
|
||||
"source": ["response = await remote_runnable.ainvoke({\"topic\": \"sports\"})"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -84,11 +71,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain.schema.runnable.config import RunnableConfig\n",
|
||||
"\n",
|
||||
"remote_runnable.batch([{\"topic\": \"sports\"}, {\"topic\": \"cars\"}])"
|
||||
]
|
||||
"source": ["from langchain_core.runnables import RunnableConfig\n\nremote_runnable.batch([{\"topic\": \"sports\"}, {\"topic\": \"cars\"}])"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -104,10 +87,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"async for chunk in remote_runnable.astream({\"topic\": \"bears, but a bit verbose\"}):\n",
|
||||
" print(chunk, end=\"\", flush=True)"
|
||||
]
|
||||
"source": ["async for chunk in remote_runnable.astream({\"topic\": \"bears, but a bit verbose\"}):\n print(chunk, end=\"\", flush=True)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -157,14 +137,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"await remote_runnable.ainvoke(\n",
|
||||
" {\"topic\": \"sports\"},\n",
|
||||
" config={\n",
|
||||
" \"configurable\": {\"prompt\": \"how to say {topic} in french\", \"llm\": \"low_temp\"}\n",
|
||||
" },\n",
|
||||
")"
|
||||
]
|
||||
"source": ["await remote_runnable.ainvoke(\n {\"topic\": \"sports\"},\n config={\n \"configurable\": {\"prompt\": \"how to say {topic} in french\", \"llm\": \"low_temp\"}\n },\n)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -221,13 +194,7 @@
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The model will fail with an auth error\n",
|
||||
"unauthenticated_response = requests.post(\n",
|
||||
" \"http://localhost:8000/auth_from_header/invoke\", json={\"input\": \"hello\"}\n",
|
||||
")\n",
|
||||
"unauthenticated_response.json()"
|
||||
]
|
||||
"source": ["# The model will fail with an auth error\nunauthenticated_response = requests.post(\n \"http://localhost:8000/auth_from_header/invoke\", json={\"input\": \"hello\"}\n)\nunauthenticated_response.json()"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -244,25 +211,14 @@
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# The model will succeed as long as the above shell script is run previously\n",
|
||||
"import os\n",
|
||||
"\n",
|
||||
"test_key = os.environ[\"TEST_API_KEY\"]\n",
|
||||
"authenticated_response = requests.post(\n",
|
||||
" \"http://localhost:8000/auth_from_header/invoke\",\n",
|
||||
" json={\"input\": \"hello\"},\n",
|
||||
" headers={\"x-api-key\": test_key},\n",
|
||||
")\n",
|
||||
"authenticated_response.json()"
|
||||
]
|
||||
"source": ["# The model will succeed as long as the above shell script is run previously\nimport os\n\ntest_key = os.environ[\"TEST_API_KEY\"]\nauthenticated_response = requests.post(\n \"http://localhost:8000/auth_from_header/invoke\",\n json={\"input\": \"hello\"},\n headers={\"x-api-key\": test_key},\n)\nauthenticated_response.json()"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
"source": [""]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
+13
-81
@@ -16,9 +16,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain.prompts.chat import ChatPromptTemplate"
|
||||
]
|
||||
"source": ["from langchain_core.prompts import ChatPromptTemplate"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -27,12 +25,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langserve import RemoteRunnable\n",
|
||||
"\n",
|
||||
"openai_llm = RemoteRunnable(\"http://localhost:8000/openai/\")\n",
|
||||
"anthropic = RemoteRunnable(\"http://localhost:8000/anthropic/\")"
|
||||
]
|
||||
"source": ["from langserve import RemoteRunnable\n\nopenai_llm = RemoteRunnable(\"http://localhost:8000/openai/\")\nanthropic = RemoteRunnable(\"http://localhost:8000/anthropic/\")"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -48,18 +41,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"prompt = ChatPromptTemplate.from_messages(\n",
|
||||
" [\n",
|
||||
" (\n",
|
||||
" \"system\",\n",
|
||||
" \"You are a highly educated person who loves to use big words. \"\n",
|
||||
" + \"You are also concise. Never answer in more than three sentences.\",\n",
|
||||
" ),\n",
|
||||
" (\"human\", \"Tell me about your favorite novel\"),\n",
|
||||
" ]\n",
|
||||
").format_messages()"
|
||||
]
|
||||
"source": ["prompt = ChatPromptTemplate.from_messages(\n [\n (\n \"system\",\n \"You are a highly educated person who loves to use big words. \"\n + \"You are also concise. Never answer in more than three sentences.\",\n ),\n (\"human\", \"Tell me about your favorite novel\"),\n ]\n).format_messages()"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -86,9 +68,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"anthropic.invoke(prompt)"
|
||||
]
|
||||
"source": ["anthropic.invoke(prompt)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -97,9 +77,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"openai_llm.invoke(prompt)"
|
||||
]
|
||||
"source": ["openai_llm.invoke(prompt)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -126,9 +104,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"await openai_llm.ainvoke(prompt)"
|
||||
]
|
||||
"source": ["await openai_llm.ainvoke(prompt)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -149,9 +125,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"anthropic.batch([prompt, prompt])"
|
||||
]
|
||||
"source": ["anthropic.batch([prompt, prompt])"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -172,9 +146,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"await anthropic.abatch([prompt, prompt])"
|
||||
]
|
||||
"source": ["await anthropic.abatch([prompt, prompt])"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -198,10 +170,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for chunk in anthropic.stream(prompt):\n",
|
||||
" print(chunk.content, end=\"\", flush=True)"
|
||||
]
|
||||
"source": ["for chunk in anthropic.stream(prompt):\n print(chunk.content, end=\"\", flush=True)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -218,19 +187,14 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"async for chunk in anthropic.astream(prompt):\n",
|
||||
" print(chunk.content, end=\"\", flush=True)"
|
||||
]
|
||||
"source": ["async for chunk in anthropic.astream(prompt):\n print(chunk.content, end=\"\", flush=True)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain.schema.runnable import RunnablePassthrough"
|
||||
]
|
||||
"source": ["from langchain_core.runnables import RunnablePassthrough"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -239,37 +203,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"comedian_chain = (\n",
|
||||
" ChatPromptTemplate.from_messages(\n",
|
||||
" [\n",
|
||||
" (\n",
|
||||
" \"system\",\n",
|
||||
" \"You are a comedian that sometimes tells funny jokes and other times you just state facts that are not funny. Please either tell a joke or state fact now but only output one.\",\n",
|
||||
" ),\n",
|
||||
" ]\n",
|
||||
" )\n",
|
||||
" | openai_llm\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"joke_classifier_chain = (\n",
|
||||
" ChatPromptTemplate.from_messages(\n",
|
||||
" [\n",
|
||||
" (\n",
|
||||
" \"system\",\n",
|
||||
" \"Please determine if the joke is funny. Say `funny` if it's funny and `not funny` if not funny. Then repeat the first five words of the joke for reference...\",\n",
|
||||
" ),\n",
|
||||
" (\"human\", \"{joke}\"),\n",
|
||||
" ]\n",
|
||||
" )\n",
|
||||
" | anthropic\n",
|
||||
")\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"chain = {\"joke\": comedian_chain} | RunnablePassthrough.assign(\n",
|
||||
" classification=joke_classifier_chain\n",
|
||||
")"
|
||||
]
|
||||
"source": ["comedian_chain = (\n ChatPromptTemplate.from_messages(\n [\n (\n \"system\",\n \"You are a comedian that sometimes tells funny jokes and other times you just state facts that are not funny. Please either tell a joke or state fact now but only output one.\",\n ),\n ]\n )\n | openai_llm\n)\n\njoke_classifier_chain = (\n ChatPromptTemplate.from_messages(\n [\n (\n \"system\",\n \"Please determine if the joke is funny. Say `funny` if it's funny and `not funny` if not funny. Then repeat the first five words of the joke for reference...\",\n ),\n (\"human\", \"{joke}\"),\n ]\n )\n | anthropic\n)\n\n\nchain = {\"joke\": comedian_chain} | RunnablePassthrough.assign(\n classification=joke_classifier_chain\n)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -290,9 +224,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"chain.invoke({})"
|
||||
]
|
||||
"source": ["chain.invoke({})"]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain.prompts.chat import ChatPromptTemplate"
|
||||
]
|
||||
"source": ["from langchain_core.prompts import ChatPromptTemplate"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -29,11 +27,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langserve import RemoteRunnable\n",
|
||||
"\n",
|
||||
"model = RemoteRunnable(\"http://localhost:8000/ollama/\")"
|
||||
]
|
||||
"source": ["from langserve import RemoteRunnable\n\nmodel = RemoteRunnable(\"http://localhost:8000/ollama/\")"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -49,9 +43,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"prompt = \"Tell me a 3 sentence story about a cat.\""
|
||||
]
|
||||
"source": ["prompt = \"Tell me a 3 sentence story about a cat.\""]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -71,9 +63,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"model.invoke(prompt)"
|
||||
]
|
||||
"source": ["model.invoke(prompt)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -93,9 +83,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"await model.ainvoke(prompt)"
|
||||
]
|
||||
"source": ["await model.ainvoke(prompt)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -131,10 +119,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%time\n",
|
||||
"model.batch([prompt, prompt])"
|
||||
]
|
||||
"source": ["%%time\nmodel.batch([prompt, prompt])"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -152,11 +137,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"%%time\n",
|
||||
"for _ in range(2):\n",
|
||||
" model.invoke(prompt)"
|
||||
]
|
||||
"source": ["%%time\nfor _ in range(2):\n model.invoke(prompt)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -177,9 +158,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"await model.abatch([prompt, prompt])"
|
||||
]
|
||||
"source": ["await model.abatch([prompt, prompt])"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -206,10 +185,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for chunk in model.stream(prompt):\n",
|
||||
" print(chunk.content, end=\"|\", flush=True)"
|
||||
]
|
||||
"source": ["for chunk in model.stream(prompt):\n print(chunk.content, end=\"|\", flush=True)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -227,10 +203,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"async for chunk in model.astream(prompt):\n",
|
||||
" print(chunk.content, end=\"|\", flush=True)"
|
||||
]
|
||||
"source": ["async for chunk in model.astream(prompt):\n print(chunk.content, end=\"|\", flush=True)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -266,15 +239,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"i = 0\n",
|
||||
"async for event in model.astream_events(prompt, version='v1'):\n",
|
||||
" print(event)\n",
|
||||
" if i > 10:\n",
|
||||
" print('...')\n",
|
||||
" break\n",
|
||||
" i += 1"
|
||||
]
|
||||
"source": ["i = 0\nasync for event in model.astream_events(prompt, version='v1'):\n print(event)\n if i > 10:\n print('...')\n break\n i += 1"]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain.prompts.chat import ChatPromptTemplate"
|
||||
]
|
||||
"source": ["from langchain_core.prompts import ChatPromptTemplate"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -27,11 +25,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langserve import RemoteRunnable\n",
|
||||
"\n",
|
||||
"chain = RemoteRunnable(\"http://localhost:8000/v1/\")"
|
||||
]
|
||||
"source": ["from langserve import RemoteRunnable\n\nchain = RemoteRunnable(\"http://localhost:8000/v1/\")"]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
@@ -59,9 +53,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"chain.invoke({'thing': 'apple', 'language': 'italian', 'info': {\"user_id\": 42, \"user_info\": {\"address\": 42}}})"
|
||||
]
|
||||
"source": ["chain.invoke({'thing': 'apple', 'language': 'italian', 'info': {\"user_id\": 42, \"user_info\": {\"address\": 42}}})"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -82,10 +74,7 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"for chunk in chain.stream({'thing': 'apple', 'language': 'italian', 'info': {\"user_id\": 42, \"user_info\": {\"address\": 42}}}):\n",
|
||||
" print(chunk)"
|
||||
]
|
||||
"source": ["for chunk in chain.stream({'thing': 'apple', 'language': 'italian', 'info': {\"user_id\": 42, \"user_info\": {\"address\": 42}}}):\n print(chunk)"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -94,11 +83,7 @@
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langserve import RemoteRunnable\n",
|
||||
"\n",
|
||||
"chain = RemoteRunnable(\"http://localhost:8000/v2/\")"
|
||||
]
|
||||
"source": ["from langserve import RemoteRunnable\n\nchain = RemoteRunnable(\"http://localhost:8000/v2/\")"]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
@@ -119,9 +104,7 @@
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"chain.invoke({'thing': 'apple', 'language': 'italian', 'info': {\"user_id\": 42, \"user_info\": {\"address\": 42}}})"
|
||||
]
|
||||
"source": ["chain.invoke({'thing': 'apple', 'language': 'italian', 'info': {\"user_id\": 42, \"user_info\": {\"address\": 42}}})"]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
@@ -40,7 +40,7 @@ prompt = ChatPromptTemplate.from_messages(
|
||||
]
|
||||
)
|
||||
|
||||
chain = prompt | ChatAnthropic(model="claude-2") | StrOutputParser()
|
||||
chain = prompt | ChatAnthropic(model="claude-2.1") | StrOutputParser()
|
||||
|
||||
|
||||
class InputChat(BaseModel):
|
||||
|
||||
+85
-24
@@ -42,6 +42,7 @@ from langsmith import client as ls_client
|
||||
from langsmith.schemas import FeedbackIngestToken
|
||||
from langsmith.utils import tracing_is_enabled
|
||||
from pydantic import BaseModel, Field, RootModel, ValidationError, create_model
|
||||
from pydantic.v1 import BaseModel as BaseModelV1
|
||||
from starlette.requests import Request
|
||||
from starlette.responses import JSONResponse, Response
|
||||
from typing_extensions import TypedDict
|
||||
@@ -61,7 +62,7 @@ from langserve.schema import (
|
||||
PublicTraceLink,
|
||||
PublicTraceLinkCreateRequest,
|
||||
)
|
||||
from langserve.serialization import WellKnownLCSerializer
|
||||
from langserve.serialization import Serializer, WellKnownLCSerializer
|
||||
from langserve.validation import (
|
||||
BatchBaseResponse,
|
||||
BatchRequestShallowValidator,
|
||||
@@ -186,11 +187,11 @@ async def _unpack_request_config(
|
||||
config_dicts = []
|
||||
for config in client_sent_configs:
|
||||
if isinstance(config, str):
|
||||
config_dicts.append(model(**_config_from_hash(config)).dict())
|
||||
config_dicts.append(model(**_config_from_hash(config)).model_dump())
|
||||
elif isinstance(config, BaseModel):
|
||||
config_dicts.append(config.dict())
|
||||
config_dicts.append(config.model_dump())
|
||||
elif isinstance(config, Mapping):
|
||||
config_dicts.append(model(**config).dict())
|
||||
config_dicts.append(model(**config).model_dump())
|
||||
else:
|
||||
raise TypeError(f"Expected a string, dict or BaseModel got {type(config)}")
|
||||
config = merge_configs(*config_dicts)
|
||||
@@ -298,7 +299,7 @@ def _unpack_input(validated_model: BaseModel) -> Any:
|
||||
# This logic should be applied recursively to nested models.
|
||||
return {
|
||||
fieldname: _unpack_input(getattr(model, fieldname))
|
||||
for fieldname in model.__fields__.keys()
|
||||
for fieldname in model.model_fields.keys()
|
||||
}
|
||||
|
||||
return model
|
||||
@@ -330,6 +331,11 @@ def _replace_non_alphanumeric_with_underscores(s: str) -> str:
|
||||
return re.sub(r"[^a-zA-Z0-9]", "_", s)
|
||||
|
||||
|
||||
def _schema_json(model: Type[BaseModel]) -> str:
|
||||
"""Return the JSON representation of the model schema."""
|
||||
return json.dumps(model.model_json_schema(), sort_keys=True, indent=False)
|
||||
|
||||
|
||||
def _resolve_model(
|
||||
type_: Union[Type, BaseModel], default_name: str, namespace: str
|
||||
) -> Type[BaseModel]:
|
||||
@@ -339,13 +345,13 @@ def _resolve_model(
|
||||
else:
|
||||
model = _create_root_model(default_name, type_)
|
||||
|
||||
hash_ = model.schema_json()
|
||||
hash_ = _schema_json(model)
|
||||
|
||||
if model.__name__ in _SEEN_NAMES and hash_ not in _MODEL_REGISTRY:
|
||||
# If the model name has been seen before, but the model itself is different
|
||||
# generate a new name for the model.
|
||||
model_to_use = _rename_pydantic_model(model, namespace)
|
||||
hash_ = model_to_use.schema_json()
|
||||
hash_ = _schema_json(model_to_use)
|
||||
else:
|
||||
model_to_use = model
|
||||
|
||||
@@ -529,6 +535,8 @@ class APIHandler:
|
||||
per_req_config_modifier: Optional[PerRequestConfigModifier] = None,
|
||||
stream_log_name_allow_list: Optional[Sequence[str]] = None,
|
||||
playground_type: Literal["default", "chat"] = "default",
|
||||
astream_events_version: Literal["v1", "v2"] = "v2",
|
||||
serializer: Optional[Serializer] = None,
|
||||
) -> None:
|
||||
"""Create an API handler for the given runnable.
|
||||
|
||||
@@ -563,6 +571,7 @@ class APIHandler:
|
||||
If true, the client will be able to show trace information
|
||||
including events that occurred on the server side.
|
||||
Be sure not to include any sensitive information in the callback events.
|
||||
This is a **beta** API.
|
||||
enable_feedback_endpoint: Whether to enable an endpoint for logging feedback
|
||||
to LangSmith. Disabled by default. If this flag is disabled or LangSmith
|
||||
tracing is not enabled for the runnable, then 4xx errors will be thrown
|
||||
@@ -590,6 +599,10 @@ class APIHandler:
|
||||
If not provided, then all logs will be allowed to be streamed.
|
||||
Use to also limit the events that can be streamed by the stream_events.
|
||||
TODO: Introduce deprecation for this parameter to rename it
|
||||
astream_events_version: version of the stream events endpoint to use.
|
||||
By default "v2".
|
||||
serializer: optional serializer to use for serializing the output.
|
||||
If not provided, the default serializer will be used.
|
||||
"""
|
||||
if importlib.util.find_spec("sse_starlette") is None:
|
||||
raise ImportError(
|
||||
@@ -621,12 +634,18 @@ class APIHandler:
|
||||
# and when tracing information is logged, we'll be able to see
|
||||
# traces for the path /foo/bar.
|
||||
self._run_name = self._base_url
|
||||
if include_callback_events:
|
||||
warn_beta(
|
||||
message="Including callback events in the response is in beta. "
|
||||
"This API may change in the future."
|
||||
)
|
||||
self._include_callback_events = include_callback_events
|
||||
self._per_req_config_modifier = per_req_config_modifier
|
||||
self._serializer = WellKnownLCSerializer()
|
||||
self._serializer = serializer or WellKnownLCSerializer()
|
||||
self._enable_feedback_endpoint = enable_feedback_endpoint
|
||||
self._enable_public_trace_link_endpoint = enable_public_trace_link_endpoint
|
||||
self._names_in_stream_allow_list = stream_log_name_allow_list
|
||||
self._astream_events_version = astream_events_version
|
||||
|
||||
if token_feedback_config:
|
||||
if len(token_feedback_config["key_configs"]) != 1:
|
||||
@@ -666,15 +685,57 @@ class APIHandler:
|
||||
|
||||
model_namespace = _replace_non_alphanumeric_with_underscores(path.strip("/"))
|
||||
|
||||
input_type_ = _resolve_model(
|
||||
runnable.get_input_schema(), "Input", model_namespace
|
||||
)
|
||||
try:
|
||||
input_type_ = _resolve_model(
|
||||
runnable.get_input_schema(), "Input", model_namespace
|
||||
)
|
||||
except Exception as e:
|
||||
# Attempt to surface a more informative user facing error
|
||||
raise_original_error = True
|
||||
try:
|
||||
if isinstance(runnable.get_input_schema(), BaseModelV1):
|
||||
raise_original_error = False
|
||||
raise ValueError(
|
||||
"Found an input type which is a pydantic v1 model."
|
||||
"Please use pydantic.BaseModel rather than "
|
||||
"pydantic.v1.BaseModel."
|
||||
)
|
||||
finally: # noqa
|
||||
if raise_original_error:
|
||||
print(
|
||||
"Encountered an error while resolving the inputs of "
|
||||
"the Runnable. Try specifying the input type explicitly "
|
||||
"using the `with_types` method on the runnable.\n"
|
||||
"See https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.base.Runnable.html " # noqa: E501
|
||||
)
|
||||
raise e
|
||||
|
||||
output_type_ = _resolve_model(
|
||||
runnable.get_output_schema(),
|
||||
"Output",
|
||||
model_namespace,
|
||||
)
|
||||
try:
|
||||
output_type_ = _resolve_model(
|
||||
runnable.get_output_schema(),
|
||||
"Output",
|
||||
model_namespace,
|
||||
)
|
||||
except Exception as e:
|
||||
# Attempt to surface a more informative user facing error
|
||||
raise_original_error = True
|
||||
try:
|
||||
if isinstance(runnable.get_output_schema(), BaseModelV1):
|
||||
raise_original_error = False
|
||||
raise ValueError(
|
||||
"Found an output type which is a pydantic v1 model."
|
||||
"Please use pydantic.BaseModel rather than "
|
||||
"pydantic.v1.BaseModel."
|
||||
)
|
||||
finally: # noqa
|
||||
if raise_original_error:
|
||||
print(
|
||||
"Encountered an error while resolving the inputs of "
|
||||
"the Runnable. Try specifying the output type explicitly "
|
||||
"using the `with_types` method on the runnable.\n"
|
||||
"See https://api.python.langchain.com/en/latest/runnables/langchain_core.runnables.base.Runnable.html " # noqa: E501
|
||||
)
|
||||
raise e
|
||||
|
||||
self._ConfigPayload = _add_namespace_to_model(
|
||||
model_namespace, runnable.config_schema(include=config_keys)
|
||||
@@ -755,7 +816,7 @@ class APIHandler:
|
||||
except json.JSONDecodeError:
|
||||
raise RequestValidationError(errors=["Invalid JSON body"])
|
||||
try:
|
||||
body = InvokeRequestShallowValidator.validate(body)
|
||||
body = InvokeRequestShallowValidator.model_validate(body)
|
||||
|
||||
# Merge the config from the path with the config from the body.
|
||||
user_provided_config = await _unpack_request_config(
|
||||
@@ -777,7 +838,7 @@ class APIHandler:
|
||||
# This takes into account changes in the input type when
|
||||
# using configuration.
|
||||
schema = self._runnable.with_config(config).input_schema
|
||||
input_ = schema.validate(body.input)
|
||||
input_ = schema.model_validate(body.input)
|
||||
return config, _unpack_input(input_)
|
||||
except ValidationError as e:
|
||||
raise RequestValidationError(e.errors(), body=body)
|
||||
@@ -887,7 +948,7 @@ class APIHandler:
|
||||
raise RequestValidationError(errors=["Invalid JSON body"])
|
||||
|
||||
with _with_validation_error_translation():
|
||||
body = BatchRequestShallowValidator.validate(body)
|
||||
body = BatchRequestShallowValidator.model_validate(body)
|
||||
config = body.config
|
||||
|
||||
# First unpack the config
|
||||
@@ -938,7 +999,7 @@ class APIHandler:
|
||||
|
||||
inputs = [
|
||||
_unpack_input(
|
||||
self._runnable.with_config(config_).input_schema.validate(input_)
|
||||
self._runnable.with_config(config_).input_schema.model_validate(input_)
|
||||
)
|
||||
for config_, input_ in zip(configs_, inputs_)
|
||||
]
|
||||
@@ -1338,7 +1399,7 @@ class APIHandler:
|
||||
exclude_names=stream_events_request.exclude_names,
|
||||
exclude_types=stream_events_request.exclude_types,
|
||||
exclude_tags=stream_events_request.exclude_tags,
|
||||
version="v1",
|
||||
version=self._astream_events_version,
|
||||
):
|
||||
if (
|
||||
self._names_in_stream_allow_list is None
|
||||
@@ -1407,7 +1468,7 @@ class APIHandler:
|
||||
self._run_name, user_provided_config, request
|
||||
)
|
||||
|
||||
return self._runnable.get_input_schema(config).schema()
|
||||
return self._runnable.get_input_schema(config).model_json_schema()
|
||||
|
||||
async def output_schema(
|
||||
self,
|
||||
@@ -1434,7 +1495,7 @@ class APIHandler:
|
||||
config = _update_config_with_defaults(
|
||||
self._run_name, user_provided_config, request
|
||||
)
|
||||
return self._runnable.get_output_schema(config).schema()
|
||||
return self._runnable.get_output_schema(config).model_json_schema()
|
||||
|
||||
async def config_schema(
|
||||
self,
|
||||
@@ -1464,7 +1525,7 @@ class APIHandler:
|
||||
return (
|
||||
self._runnable.with_config(config)
|
||||
.config_schema(include=self._config_keys)
|
||||
.schema()
|
||||
.model_json_schema()
|
||||
)
|
||||
|
||||
async def playground(
|
||||
|
||||
+21
-7
@@ -48,7 +48,7 @@ class AsyncEventAggregatorCallback(AsyncCallbackHandler):
|
||||
|
||||
async def on_chat_model_start(
|
||||
self,
|
||||
serialized: Dict[str, Any],
|
||||
serialized: Optional[Dict[str, Any]],
|
||||
messages: List[List[BaseMessage]],
|
||||
*,
|
||||
run_id: UUID,
|
||||
@@ -73,7 +73,7 @@ class AsyncEventAggregatorCallback(AsyncCallbackHandler):
|
||||
|
||||
async def on_chain_start(
|
||||
self,
|
||||
serialized: Dict[str, Any],
|
||||
serialized: Optional[Dict[str, Any]],
|
||||
inputs: Dict[str, Any],
|
||||
*,
|
||||
run_id: UUID,
|
||||
@@ -138,7 +138,7 @@ class AsyncEventAggregatorCallback(AsyncCallbackHandler):
|
||||
|
||||
async def on_retriever_start(
|
||||
self,
|
||||
serialized: Dict[str, Any],
|
||||
serialized: Optional[Dict[str, Any]],
|
||||
query: str,
|
||||
*,
|
||||
run_id: UUID,
|
||||
@@ -202,7 +202,7 @@ class AsyncEventAggregatorCallback(AsyncCallbackHandler):
|
||||
|
||||
async def on_tool_start(
|
||||
self,
|
||||
serialized: Dict[str, Any],
|
||||
serialized: Optional[Dict[str, Any]],
|
||||
input_str: str,
|
||||
*,
|
||||
run_id: UUID,
|
||||
@@ -306,7 +306,7 @@ class AsyncEventAggregatorCallback(AsyncCallbackHandler):
|
||||
|
||||
async def on_llm_start(
|
||||
self,
|
||||
serialized: Dict[str, Any],
|
||||
serialized: Optional[Dict[str, Any]],
|
||||
prompts: List[str],
|
||||
*,
|
||||
run_id: UUID,
|
||||
@@ -445,7 +445,14 @@ async def ahandle_callbacks(
|
||||
if event["parent_run_id"] is None: # How do we make sure it's None!?
|
||||
event["parent_run_id"] = callback_manager.run_id
|
||||
|
||||
event_data = {key: value for key, value in event.items() if key != "type"}
|
||||
event_data = {
|
||||
key: value
|
||||
for key, value in event.items()
|
||||
if key != "type" and key != "kwargs"
|
||||
}
|
||||
|
||||
if "kwargs" in event:
|
||||
event_data.update(event["kwargs"])
|
||||
|
||||
await ahandle_event(
|
||||
# Unpacking like this may not work
|
||||
@@ -467,7 +474,14 @@ def handle_callbacks(
|
||||
if event["parent_run_id"] is None: # How do we make sure it's None!?
|
||||
event["parent_run_id"] = callback_manager.run_id
|
||||
|
||||
event_data = {key: value for key, value in event.items() if key != "type"}
|
||||
event_data = {
|
||||
key: value
|
||||
for key, value in event.items()
|
||||
if key != "type" and key != "kwargs"
|
||||
}
|
||||
|
||||
if "kwargs" in event:
|
||||
event_data.update(event["kwargs"])
|
||||
|
||||
handle_event(
|
||||
# Unpacking like this may not work
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"clsx": "^2.0.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"fast-json-patch": "^3.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash": "^4.18.1",
|
||||
"lz-string": "^1.5.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@@ -46,7 +46,14 @@
|
||||
"postcss": "^8.4.31",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.5",
|
||||
"vite": "^6.4.2",
|
||||
"vite-plugin-svgr": "^4.1.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"braces": "^3.0.3",
|
||||
"cross-spawn": "^7.0.5",
|
||||
"rollup": "^3.30.0",
|
||||
"ajv": "^8.18.0",
|
||||
"esbuild": "0.25.0"
|
||||
}
|
||||
}
|
||||
|
||||
+291
-239
@@ -28,6 +28,15 @@
|
||||
"@babel/highlight" "^7.22.13"
|
||||
chalk "^2.4.2"
|
||||
|
||||
"@babel/code-frame@^7.28.6":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c"
|
||||
integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.28.5"
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.1.1"
|
||||
|
||||
"@babel/compat-data@^7.22.9":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.2.tgz#6a12ced93455827037bfb5ed8492820d60fc32cc"
|
||||
@@ -137,24 +146,33 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
|
||||
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
|
||||
|
||||
"@babel/helper-string-parser@^7.27.1":
|
||||
version "7.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687"
|
||||
integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.22.20":
|
||||
version "7.22.20"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
||||
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.28.5":
|
||||
version "7.28.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4"
|
||||
integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==
|
||||
|
||||
"@babel/helper-validator-option@^7.22.15":
|
||||
version "7.22.15"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
|
||||
integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==
|
||||
|
||||
"@babel/helpers@^7.23.2":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767"
|
||||
integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7"
|
||||
integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==
|
||||
dependencies:
|
||||
"@babel/template" "^7.22.15"
|
||||
"@babel/traverse" "^7.23.2"
|
||||
"@babel/types" "^7.23.0"
|
||||
"@babel/template" "^7.28.6"
|
||||
"@babel/types" "^7.28.6"
|
||||
|
||||
"@babel/highlight@^7.22.13":
|
||||
version "7.22.20"
|
||||
@@ -170,6 +188,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
|
||||
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
|
||||
|
||||
"@babel/parser@^7.28.6":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.0.tgz#669ef345add7d057e92b7ed15f0bac07611831b6"
|
||||
integrity sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==
|
||||
dependencies:
|
||||
"@babel/types" "^7.29.0"
|
||||
|
||||
"@babel/plugin-transform-react-jsx-self@^7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz#ca2fdc11bc20d4d46de01137318b13d04e481d8e"
|
||||
@@ -185,11 +210,9 @@
|
||||
"@babel/helper-plugin-utils" "^7.22.5"
|
||||
|
||||
"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885"
|
||||
integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.6.tgz#d267a43cb1836dc4d182cce93ae75ba954ef6d2b"
|
||||
integrity sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==
|
||||
|
||||
"@babel/template@^7.22.15":
|
||||
version "7.22.15"
|
||||
@@ -200,6 +223,15 @@
|
||||
"@babel/parser" "^7.22.15"
|
||||
"@babel/types" "^7.22.15"
|
||||
|
||||
"@babel/template@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57"
|
||||
integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.28.6"
|
||||
"@babel/parser" "^7.28.6"
|
||||
"@babel/types" "^7.28.6"
|
||||
|
||||
"@babel/traverse@^7.23.2":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
|
||||
@@ -225,6 +257,14 @@
|
||||
"@babel/helper-validator-identifier" "^7.22.20"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.28.6", "@babel/types@^7.29.0":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.0.tgz#9f5b1e838c446e72cf3cd4b918152b8c605e37c7"
|
||||
integrity sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.27.1"
|
||||
"@babel/helper-validator-identifier" "^7.28.5"
|
||||
|
||||
"@emotion/babel-plugin@^11.11.0":
|
||||
version "11.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c"
|
||||
@@ -332,115 +372,130 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
|
||||
integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
|
||||
|
||||
"@esbuild/android-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
|
||||
integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==
|
||||
"@esbuild/aix-ppc64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64"
|
||||
integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==
|
||||
|
||||
"@esbuild/android-arm@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682"
|
||||
integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==
|
||||
"@esbuild/android-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f"
|
||||
integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==
|
||||
|
||||
"@esbuild/android-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2"
|
||||
integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==
|
||||
"@esbuild/android-arm@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b"
|
||||
integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==
|
||||
|
||||
"@esbuild/darwin-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1"
|
||||
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
|
||||
"@esbuild/android-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163"
|
||||
integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==
|
||||
|
||||
"@esbuild/darwin-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d"
|
||||
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==
|
||||
"@esbuild/darwin-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c"
|
||||
integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54"
|
||||
integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==
|
||||
"@esbuild/darwin-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a"
|
||||
integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==
|
||||
|
||||
"@esbuild/freebsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e"
|
||||
integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==
|
||||
"@esbuild/freebsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce"
|
||||
integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==
|
||||
|
||||
"@esbuild/linux-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0"
|
||||
integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==
|
||||
"@esbuild/freebsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7"
|
||||
integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==
|
||||
|
||||
"@esbuild/linux-arm@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0"
|
||||
integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==
|
||||
"@esbuild/linux-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73"
|
||||
integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==
|
||||
|
||||
"@esbuild/linux-ia32@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7"
|
||||
integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==
|
||||
"@esbuild/linux-arm@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3"
|
||||
integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==
|
||||
|
||||
"@esbuild/linux-loong64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d"
|
||||
integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==
|
||||
"@esbuild/linux-ia32@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19"
|
||||
integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==
|
||||
|
||||
"@esbuild/linux-mips64el@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231"
|
||||
integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==
|
||||
"@esbuild/linux-loong64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7"
|
||||
integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==
|
||||
|
||||
"@esbuild/linux-ppc64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb"
|
||||
integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==
|
||||
"@esbuild/linux-mips64el@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1"
|
||||
integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6"
|
||||
integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==
|
||||
"@esbuild/linux-ppc64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951"
|
||||
integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==
|
||||
|
||||
"@esbuild/linux-s390x@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071"
|
||||
integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==
|
||||
"@esbuild/linux-riscv64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987"
|
||||
integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==
|
||||
|
||||
"@esbuild/linux-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338"
|
||||
integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==
|
||||
"@esbuild/linux-s390x@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4"
|
||||
integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==
|
||||
|
||||
"@esbuild/netbsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1"
|
||||
integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==
|
||||
"@esbuild/linux-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a"
|
||||
integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==
|
||||
|
||||
"@esbuild/openbsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae"
|
||||
integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==
|
||||
"@esbuild/netbsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b"
|
||||
integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==
|
||||
|
||||
"@esbuild/sunos-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d"
|
||||
integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==
|
||||
"@esbuild/netbsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b"
|
||||
integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==
|
||||
|
||||
"@esbuild/win32-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9"
|
||||
integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==
|
||||
"@esbuild/openbsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7"
|
||||
integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==
|
||||
|
||||
"@esbuild/win32-ia32@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102"
|
||||
integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==
|
||||
"@esbuild/openbsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde"
|
||||
integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==
|
||||
|
||||
"@esbuild/win32-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d"
|
||||
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
|
||||
"@esbuild/sunos-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92"
|
||||
integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==
|
||||
|
||||
"@esbuild/win32-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c"
|
||||
integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==
|
||||
|
||||
"@esbuild/win32-ia32@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079"
|
||||
integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==
|
||||
|
||||
"@esbuild/win32-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b"
|
||||
integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
||||
version "4.4.0"
|
||||
@@ -1198,25 +1253,15 @@ ajv-formats@^2.1.0:
|
||||
dependencies:
|
||||
ajv "^8.0.0"
|
||||
|
||||
ajv@^6.12.4:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||
ajv@^6.12.4, ajv@^8.0.0, ajv@^8.18.0, ajv@^8.6.1:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc"
|
||||
integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@^8.0.0, ajv@^8.6.1:
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
|
||||
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-deep-equal "^3.1.3"
|
||||
fast-uri "^3.0.1"
|
||||
json-schema-traverse "^1.0.0"
|
||||
require-from-string "^2.0.2"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
@@ -1304,19 +1349,19 @@ binary-extensions@^2.0.0:
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.13.tgz#d37875c01dc9eff988dd49d112a57cb67b54efe6"
|
||||
integrity sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
braces@^3.0.3, braces@~3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
|
||||
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
fill-range "^7.1.1"
|
||||
|
||||
browserslist@^4.21.10, browserslist@^4.21.9:
|
||||
version "4.22.1"
|
||||
@@ -1460,10 +1505,10 @@ cosmiconfig@^8.1.3:
|
||||
parse-json "^5.2.0"
|
||||
path-type "^4.0.0"
|
||||
|
||||
cross-spawn@^7.0.2:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
cross-spawn@^7.0.2, cross-spawn@^7.0.5:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
@@ -1558,33 +1603,36 @@ error-ex@^1.3.1:
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
esbuild@^0.18.10:
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6"
|
||||
integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==
|
||||
esbuild@0.25.0, esbuild@^0.25.0:
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92"
|
||||
integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.18.20"
|
||||
"@esbuild/android-arm64" "0.18.20"
|
||||
"@esbuild/android-x64" "0.18.20"
|
||||
"@esbuild/darwin-arm64" "0.18.20"
|
||||
"@esbuild/darwin-x64" "0.18.20"
|
||||
"@esbuild/freebsd-arm64" "0.18.20"
|
||||
"@esbuild/freebsd-x64" "0.18.20"
|
||||
"@esbuild/linux-arm" "0.18.20"
|
||||
"@esbuild/linux-arm64" "0.18.20"
|
||||
"@esbuild/linux-ia32" "0.18.20"
|
||||
"@esbuild/linux-loong64" "0.18.20"
|
||||
"@esbuild/linux-mips64el" "0.18.20"
|
||||
"@esbuild/linux-ppc64" "0.18.20"
|
||||
"@esbuild/linux-riscv64" "0.18.20"
|
||||
"@esbuild/linux-s390x" "0.18.20"
|
||||
"@esbuild/linux-x64" "0.18.20"
|
||||
"@esbuild/netbsd-x64" "0.18.20"
|
||||
"@esbuild/openbsd-x64" "0.18.20"
|
||||
"@esbuild/sunos-x64" "0.18.20"
|
||||
"@esbuild/win32-arm64" "0.18.20"
|
||||
"@esbuild/win32-ia32" "0.18.20"
|
||||
"@esbuild/win32-x64" "0.18.20"
|
||||
"@esbuild/aix-ppc64" "0.25.0"
|
||||
"@esbuild/android-arm" "0.25.0"
|
||||
"@esbuild/android-arm64" "0.25.0"
|
||||
"@esbuild/android-x64" "0.25.0"
|
||||
"@esbuild/darwin-arm64" "0.25.0"
|
||||
"@esbuild/darwin-x64" "0.25.0"
|
||||
"@esbuild/freebsd-arm64" "0.25.0"
|
||||
"@esbuild/freebsd-x64" "0.25.0"
|
||||
"@esbuild/linux-arm" "0.25.0"
|
||||
"@esbuild/linux-arm64" "0.25.0"
|
||||
"@esbuild/linux-ia32" "0.25.0"
|
||||
"@esbuild/linux-loong64" "0.25.0"
|
||||
"@esbuild/linux-mips64el" "0.25.0"
|
||||
"@esbuild/linux-ppc64" "0.25.0"
|
||||
"@esbuild/linux-riscv64" "0.25.0"
|
||||
"@esbuild/linux-s390x" "0.25.0"
|
||||
"@esbuild/linux-x64" "0.25.0"
|
||||
"@esbuild/netbsd-arm64" "0.25.0"
|
||||
"@esbuild/netbsd-x64" "0.25.0"
|
||||
"@esbuild/openbsd-arm64" "0.25.0"
|
||||
"@esbuild/openbsd-x64" "0.25.0"
|
||||
"@esbuild/sunos-x64" "0.25.0"
|
||||
"@esbuild/win32-arm64" "0.25.0"
|
||||
"@esbuild/win32-ia32" "0.25.0"
|
||||
"@esbuild/win32-x64" "0.25.0"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
@@ -1705,7 +1753,7 @@ esutils@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
@@ -1726,16 +1774,16 @@ fast-json-patch@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz#85064ea1b1ebf97a3f7ad01e23f9337e72c66947"
|
||||
integrity sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
|
||||
fast-levenshtein@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||
|
||||
fast-uri@^3.0.1:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa"
|
||||
integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
|
||||
@@ -1743,6 +1791,11 @@ fastq@^1.6.0:
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fdir@^6.4.4, fdir@^6.5.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
|
||||
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
|
||||
|
||||
file-entry-cache@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
||||
@@ -1750,10 +1803,10 @@ file-entry-cache@^6.0.1:
|
||||
dependencies:
|
||||
flat-cache "^3.0.4"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
@@ -1780,9 +1833,9 @@ flat-cache@^3.0.4:
|
||||
rimraf "^3.0.2"
|
||||
|
||||
flatted@^3.2.9:
|
||||
version "3.2.9"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
|
||||
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726"
|
||||
integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==
|
||||
|
||||
fraction.js@^4.3.6:
|
||||
version "4.3.7"
|
||||
@@ -1794,7 +1847,7 @@ fs.realpath@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
@@ -1993,9 +2046,9 @@ jiti@^1.18.2:
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b"
|
||||
integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
@@ -2014,11 +2067,6 @@ json-parse-even-better-errors@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||
|
||||
json-schema-traverse@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
|
||||
@@ -2071,10 +2119,10 @@ lodash.merge@^4.6.2:
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
lodash@^4.17.21, lodash@^4.18.1:
|
||||
version "4.18.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c"
|
||||
integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
@@ -2115,17 +2163,17 @@ merge2@^1.3.0, merge2@^1.4.1:
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
|
||||
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
|
||||
dependencies:
|
||||
braces "^3.0.2"
|
||||
braces "^3.0.3"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
version "3.1.5"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e"
|
||||
integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
@@ -2143,10 +2191,10 @@ mz@^2.7.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nanoid@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
nanoid@^3.3.11:
|
||||
version "3.3.11"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
|
||||
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
@@ -2266,10 +2314,20 @@ picocolors@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picocolors@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
||||
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601"
|
||||
integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==
|
||||
|
||||
picomatch@^4.0.2, picomatch@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589"
|
||||
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==
|
||||
|
||||
pify@^2.3.0:
|
||||
version "2.3.0"
|
||||
@@ -2325,14 +2383,14 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.4.23, postcss@^8.4.27, postcss@^8.4.31:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
||||
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
||||
postcss@^8.4.23, postcss@^8.4.31, postcss@^8.5.3:
|
||||
version "8.5.9"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.9.tgz#f6ee9e0b94f0f19c97d2f172bfbd7fc71fe1cca4"
|
||||
integrity sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==
|
||||
dependencies:
|
||||
nanoid "^3.3.6"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
nanoid "^3.3.11"
|
||||
picocolors "^1.1.1"
|
||||
source-map-js "^1.2.1"
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
@@ -2348,11 +2406,6 @@ prop-types@^15.6.2, prop-types@^15.8.1:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
@@ -2447,11 +2500,6 @@ readdirp@~3.6.0:
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
regenerator-runtime@^0.14.0:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45"
|
||||
integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==
|
||||
|
||||
require-from-string@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||
@@ -2483,10 +2531,10 @@ rimraf@^3.0.2:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rollup@^3.27.1:
|
||||
version "3.29.4"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981"
|
||||
integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==
|
||||
rollup@^3.30.0, rollup@^4.34.9:
|
||||
version "3.30.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.30.0.tgz#3fa506fee2c5ba9d540a38da87067376cd55966d"
|
||||
integrity sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
@@ -2541,10 +2589,10 @@ snake-case@^3.0.4:
|
||||
dot-case "^3.0.4"
|
||||
tslib "^2.0.3"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
source-map-js@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
|
||||
source-map@^0.5.7:
|
||||
version "0.5.7"
|
||||
@@ -2665,6 +2713,14 @@ thenify-all@^1.0.0:
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
tinyglobby@^0.2.13:
|
||||
version "0.2.16"
|
||||
resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.16.tgz#1c3b7eb953fce42b226bc5a1ee06428281aff3d6"
|
||||
integrity sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==
|
||||
dependencies:
|
||||
fdir "^6.5.0"
|
||||
picomatch "^4.0.4"
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
@@ -2717,13 +2773,6 @@ update-browserslist-db@^1.0.13:
|
||||
escalade "^3.1.1"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
use-callback-ref@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5"
|
||||
@@ -2770,16 +2819,19 @@ vite-plugin-svgr@^4.1.0:
|
||||
"@svgr/core" "^8.1.0"
|
||||
"@svgr/plugin-jsx" "^8.1.0"
|
||||
|
||||
vite@^4.4.5:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.0.tgz#ec406295b4167ac3bc23e26f9c8ff559287cff26"
|
||||
integrity sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==
|
||||
vite@^6.4.2:
|
||||
version "6.4.2"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-6.4.2.tgz#a4e548ca3a90ca9f3724582cab35e1ba15efc6f2"
|
||||
integrity sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==
|
||||
dependencies:
|
||||
esbuild "^0.18.10"
|
||||
postcss "^8.4.27"
|
||||
rollup "^3.27.1"
|
||||
esbuild "^0.25.0"
|
||||
fdir "^6.4.4"
|
||||
picomatch "^4.0.2"
|
||||
postcss "^8.5.3"
|
||||
rollup "^4.34.9"
|
||||
tinyglobby "^0.2.13"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
fsevents "~2.3.3"
|
||||
|
||||
which@^2.0.1:
|
||||
version "2.0.2"
|
||||
@@ -2804,14 +2856,14 @@ yallist@^4.0.0:
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@^1.10.0:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
version "1.10.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.3.tgz#76e407ed95c42684fb8e14641e5de62fe65bbcb3"
|
||||
integrity sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==
|
||||
|
||||
yaml@^2.1.1:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.3.tgz#01f6d18ef036446340007db8e016810e5d64aad9"
|
||||
integrity sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.3.tgz#a0d6bd2efb3dd03c59370223701834e60409bd7d"
|
||||
integrity sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==
|
||||
|
||||
yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
|
||||
+28
-8
@@ -8,6 +8,7 @@ import weakref
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from functools import lru_cache
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
AsyncIterator,
|
||||
Dict,
|
||||
@@ -21,7 +22,7 @@ from typing import (
|
||||
from urllib.parse import urljoin
|
||||
|
||||
import httpx
|
||||
from httpx._types import AuthTypes, CertTypes, CookieTypes, HeaderTypes, VerifyTypes
|
||||
from httpx._types import AuthTypes, CertTypes, CookieTypes, HeaderTypes
|
||||
from langchain_core.callbacks import (
|
||||
AsyncCallbackManagerForChainRun,
|
||||
CallbackManagerForChainRun,
|
||||
@@ -49,6 +50,10 @@ from langserve.server_sent_events import aconnect_sse, connect_sse
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# For type checking httpx types
|
||||
import ssl
|
||||
|
||||
|
||||
def _is_json_serializable(obj: Any) -> bool:
|
||||
"""Return True if the object is json serializable."""
|
||||
@@ -120,6 +125,12 @@ def _log_error_message_once(error_message: str) -> None:
|
||||
logger.error(error_message)
|
||||
|
||||
|
||||
@lru_cache(maxsize=1_000) # Will accommodate up to 1_000 different error messages
|
||||
def _log_info_message_once(error_message: str) -> None:
|
||||
"""Log an error message once."""
|
||||
logger.info(error_message)
|
||||
|
||||
|
||||
def _sanitize_request(request: httpx.Request) -> httpx.Request:
|
||||
"""Remove sensitive headers from the request."""
|
||||
accept_headers = {
|
||||
@@ -275,10 +286,11 @@ class RemoteRunnable(Runnable[Input, Output]):
|
||||
auth: Optional[AuthTypes] = None,
|
||||
headers: Optional[HeaderTypes] = None,
|
||||
cookies: Optional[CookieTypes] = None,
|
||||
verify: VerifyTypes = True,
|
||||
verify: ssl.SSLContext | str | bool = True,
|
||||
cert: Optional[CertTypes] = None,
|
||||
client_kwargs: Optional[Dict[str, Any]] = None,
|
||||
use_server_callback_events: bool = True,
|
||||
serializer: Optional[Serializer] = None,
|
||||
) -> None:
|
||||
"""Initialize the client.
|
||||
|
||||
@@ -294,6 +306,8 @@ class RemoteRunnable(Runnable[Input, Output]):
|
||||
and async httpx clients
|
||||
use_server_callback_events: Whether to invoke callbacks on any
|
||||
callback events returned by the server.
|
||||
serializer: The serializer to use for serializing and deserializing
|
||||
data. If not provided, a default serializer will be used.
|
||||
"""
|
||||
_client_kwargs = client_kwargs or {}
|
||||
# Enforce trailing slash
|
||||
@@ -321,7 +335,7 @@ class RemoteRunnable(Runnable[Input, Output]):
|
||||
|
||||
# Register cleanup handler once RemoteRunnable is garbage collected
|
||||
weakref.finalize(self, _close_clients, self.sync_client, self.async_client)
|
||||
self._lc_serializer = WellKnownLCSerializer()
|
||||
self._lc_serializer = serializer or WellKnownLCSerializer()
|
||||
self._use_server_callback_events = use_server_callback_events
|
||||
|
||||
def _invoke(
|
||||
@@ -752,7 +766,7 @@ class RemoteRunnable(Runnable[Input, Output]):
|
||||
input: Any,
|
||||
config: Optional[RunnableConfig] = None,
|
||||
*,
|
||||
version: Literal["v1"],
|
||||
version: Literal["v1", "v2", None] = None,
|
||||
include_names: Optional[Sequence[str]] = None,
|
||||
include_types: Optional[Sequence[str]] = None,
|
||||
include_tags: Optional[Sequence[str]] = None,
|
||||
@@ -775,7 +789,8 @@ class RemoteRunnable(Runnable[Input, Output]):
|
||||
input: The input to the runnable
|
||||
config: The config to use for the runnable
|
||||
version: The version of the astream_events to use.
|
||||
Currently only "v1" is supported.
|
||||
Currently, this input is IGNORED on the client.
|
||||
The server will return whatever format it's configured with.
|
||||
include_names: The names of the events to include
|
||||
include_types: The types of the events to include
|
||||
include_tags: The tags of the events to include
|
||||
@@ -783,13 +798,18 @@ class RemoteRunnable(Runnable[Input, Output]):
|
||||
exclude_types: The types of the events to exclude
|
||||
exclude_tags: The tags of the events to exclude
|
||||
"""
|
||||
if version != "v1":
|
||||
raise ValueError(f"Unsupported version: {version}. Use 'v1'")
|
||||
|
||||
# Create a stream handler that will emit Log objects
|
||||
config = ensure_config(config)
|
||||
callback_manager = get_async_callback_manager_for_config(config)
|
||||
|
||||
if version is not None:
|
||||
_log_info_message_once(
|
||||
"Versioning of the astream_events API is not supported on the client "
|
||||
"side currently. The server will return events in whatever format "
|
||||
"it was configured with in add_routes or APIHandler. "
|
||||
"To stop seeing this message, remove the `version` argument."
|
||||
)
|
||||
|
||||
events = []
|
||||
|
||||
run_manager = await callback_manager.on_chain_start(
|
||||
|
||||
@@ -89,10 +89,12 @@ async def serve_playground(
|
||||
if base_url.startswith("/")
|
||||
else base_url,
|
||||
LANGSERVE_CONFIG_SCHEMA=json.dumps(
|
||||
runnable.config_schema(include=config_keys).schema()
|
||||
runnable.config_schema(include=config_keys).model_json_schema()
|
||||
),
|
||||
LANGSERVE_INPUT_SCHEMA=json.dumps(input_schema.model_json_schema()),
|
||||
LANGSERVE_OUTPUT_SCHEMA=json.dumps(
|
||||
output_schema.model_json_schema()
|
||||
),
|
||||
LANGSERVE_INPUT_SCHEMA=json.dumps(input_schema.schema()),
|
||||
LANGSERVE_OUTPUT_SCHEMA=json.dumps(output_schema.schema()),
|
||||
LANGSERVE_FEEDBACK_ENABLED=json.dumps(
|
||||
"true" if feedback_enabled else "false"
|
||||
),
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"clsx": "^2.0.0",
|
||||
"dayjs": "^1.11.10",
|
||||
"fast-json-patch": "^3.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash": "^4.18.1",
|
||||
"lz-string": "^1.5.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
@@ -48,7 +48,14 @@
|
||||
"postcss": "^8.4.31",
|
||||
"tailwindcss": "^3.3.3",
|
||||
"typescript": "^5.0.2",
|
||||
"vite": "^4.4.5",
|
||||
"vite": "^6.4.2",
|
||||
"vite-plugin-svgr": "^4.1.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"braces": "^3.0.3",
|
||||
"cross-spawn": "^7.0.5",
|
||||
"rollup": "^3.30.0",
|
||||
"ajv": "^8.18.0",
|
||||
"esbuild": "0.25.0"
|
||||
}
|
||||
}
|
||||
|
||||
+291
-239
@@ -28,6 +28,15 @@
|
||||
"@babel/highlight" "^7.22.13"
|
||||
chalk "^2.4.2"
|
||||
|
||||
"@babel/code-frame@^7.28.6":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.29.0.tgz#7cd7a59f15b3cc0dcd803038f7792712a7d0b15c"
|
||||
integrity sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier" "^7.28.5"
|
||||
js-tokens "^4.0.0"
|
||||
picocolors "^1.1.1"
|
||||
|
||||
"@babel/compat-data@^7.22.9":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.2.tgz#6a12ced93455827037bfb5ed8492820d60fc32cc"
|
||||
@@ -137,24 +146,33 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
|
||||
integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
|
||||
|
||||
"@babel/helper-string-parser@^7.27.1":
|
||||
version "7.27.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687"
|
||||
integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.22.20":
|
||||
version "7.22.20"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
|
||||
integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==
|
||||
|
||||
"@babel/helper-validator-identifier@^7.28.5":
|
||||
version "7.28.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4"
|
||||
integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==
|
||||
|
||||
"@babel/helper-validator-option@^7.22.15":
|
||||
version "7.22.15"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz#694c30dfa1d09a6534cdfcafbe56789d36aba040"
|
||||
integrity sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==
|
||||
|
||||
"@babel/helpers@^7.23.2":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.2.tgz#2832549a6e37d484286e15ba36a5330483cac767"
|
||||
integrity sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.6.tgz#fca903a313ae675617936e8998b814c415cbf5d7"
|
||||
integrity sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==
|
||||
dependencies:
|
||||
"@babel/template" "^7.22.15"
|
||||
"@babel/traverse" "^7.23.2"
|
||||
"@babel/types" "^7.23.0"
|
||||
"@babel/template" "^7.28.6"
|
||||
"@babel/types" "^7.28.6"
|
||||
|
||||
"@babel/highlight@^7.22.13":
|
||||
version "7.22.20"
|
||||
@@ -170,6 +188,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.0.tgz#da950e622420bf96ca0d0f2909cdddac3acd8719"
|
||||
integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==
|
||||
|
||||
"@babel/parser@^7.28.6":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.0.tgz#669ef345add7d057e92b7ed15f0bac07611831b6"
|
||||
integrity sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==
|
||||
dependencies:
|
||||
"@babel/types" "^7.29.0"
|
||||
|
||||
"@babel/plugin-transform-react-jsx-self@^7.22.5":
|
||||
version "7.22.5"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz#ca2fdc11bc20d4d46de01137318b13d04e481d8e"
|
||||
@@ -185,11 +210,9 @@
|
||||
"@babel/helper-plugin-utils" "^7.22.5"
|
||||
|
||||
"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.2.tgz#062b0ac103261d68a966c4c7baf2ae3e62ec3885"
|
||||
integrity sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.14.0"
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.6.tgz#d267a43cb1836dc4d182cce93ae75ba954ef6d2b"
|
||||
integrity sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==
|
||||
|
||||
"@babel/template@^7.22.15":
|
||||
version "7.22.15"
|
||||
@@ -200,6 +223,15 @@
|
||||
"@babel/parser" "^7.22.15"
|
||||
"@babel/types" "^7.22.15"
|
||||
|
||||
"@babel/template@^7.28.6":
|
||||
version "7.28.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.28.6.tgz#0e7e56ecedb78aeef66ce7972b082fce76a23e57"
|
||||
integrity sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.28.6"
|
||||
"@babel/parser" "^7.28.6"
|
||||
"@babel/types" "^7.28.6"
|
||||
|
||||
"@babel/traverse@^7.23.2":
|
||||
version "7.23.2"
|
||||
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.2.tgz#329c7a06735e144a506bdb2cad0268b7f46f4ad8"
|
||||
@@ -225,6 +257,14 @@
|
||||
"@babel/helper-validator-identifier" "^7.22.20"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@babel/types@^7.28.6", "@babel/types@^7.29.0":
|
||||
version "7.29.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.0.tgz#9f5b1e838c446e72cf3cd4b918152b8c605e37c7"
|
||||
integrity sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==
|
||||
dependencies:
|
||||
"@babel/helper-string-parser" "^7.27.1"
|
||||
"@babel/helper-validator-identifier" "^7.28.5"
|
||||
|
||||
"@date-io/core@^1.3.13":
|
||||
version "1.3.13"
|
||||
resolved "https://registry.yarnpkg.com/@date-io/core/-/core-1.3.13.tgz#90c71da493f20204b7a972929cc5c482d078b3fa"
|
||||
@@ -344,115 +384,130 @@
|
||||
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
|
||||
integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
|
||||
|
||||
"@esbuild/android-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz#984b4f9c8d0377443cc2dfcef266d02244593622"
|
||||
integrity sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==
|
||||
"@esbuild/aix-ppc64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64"
|
||||
integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==
|
||||
|
||||
"@esbuild/android-arm@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.18.20.tgz#fedb265bc3a589c84cc11f810804f234947c3682"
|
||||
integrity sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==
|
||||
"@esbuild/android-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f"
|
||||
integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==
|
||||
|
||||
"@esbuild/android-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.18.20.tgz#35cf419c4cfc8babe8893d296cd990e9e9f756f2"
|
||||
integrity sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==
|
||||
"@esbuild/android-arm@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b"
|
||||
integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==
|
||||
|
||||
"@esbuild/darwin-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz#08172cbeccf95fbc383399a7f39cfbddaeb0d7c1"
|
||||
integrity sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==
|
||||
"@esbuild/android-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163"
|
||||
integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==
|
||||
|
||||
"@esbuild/darwin-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz#d70d5790d8bf475556b67d0f8b7c5bdff053d85d"
|
||||
integrity sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==
|
||||
"@esbuild/darwin-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c"
|
||||
integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz#98755cd12707f93f210e2494d6a4b51b96977f54"
|
||||
integrity sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==
|
||||
"@esbuild/darwin-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a"
|
||||
integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==
|
||||
|
||||
"@esbuild/freebsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz#c1eb2bff03915f87c29cece4c1a7fa1f423b066e"
|
||||
integrity sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==
|
||||
"@esbuild/freebsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce"
|
||||
integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==
|
||||
|
||||
"@esbuild/linux-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz#bad4238bd8f4fc25b5a021280c770ab5fc3a02a0"
|
||||
integrity sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==
|
||||
"@esbuild/freebsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7"
|
||||
integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==
|
||||
|
||||
"@esbuild/linux-arm@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz#3e617c61f33508a27150ee417543c8ab5acc73b0"
|
||||
integrity sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==
|
||||
"@esbuild/linux-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73"
|
||||
integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==
|
||||
|
||||
"@esbuild/linux-ia32@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz#699391cccba9aee6019b7f9892eb99219f1570a7"
|
||||
integrity sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==
|
||||
"@esbuild/linux-arm@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3"
|
||||
integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==
|
||||
|
||||
"@esbuild/linux-loong64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz#e6fccb7aac178dd2ffb9860465ac89d7f23b977d"
|
||||
integrity sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==
|
||||
"@esbuild/linux-ia32@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19"
|
||||
integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==
|
||||
|
||||
"@esbuild/linux-mips64el@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz#eeff3a937de9c2310de30622a957ad1bd9183231"
|
||||
integrity sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==
|
||||
"@esbuild/linux-loong64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7"
|
||||
integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==
|
||||
|
||||
"@esbuild/linux-ppc64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz#2f7156bde20b01527993e6881435ad79ba9599fb"
|
||||
integrity sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==
|
||||
"@esbuild/linux-mips64el@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1"
|
||||
integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz#6628389f210123d8b4743045af8caa7d4ddfc7a6"
|
||||
integrity sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==
|
||||
"@esbuild/linux-ppc64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951"
|
||||
integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==
|
||||
|
||||
"@esbuild/linux-s390x@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz#255e81fb289b101026131858ab99fba63dcf0071"
|
||||
integrity sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==
|
||||
"@esbuild/linux-riscv64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987"
|
||||
integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==
|
||||
|
||||
"@esbuild/linux-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz#c7690b3417af318a9b6f96df3031a8865176d338"
|
||||
integrity sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==
|
||||
"@esbuild/linux-s390x@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4"
|
||||
integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==
|
||||
|
||||
"@esbuild/netbsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz#30e8cd8a3dded63975e2df2438ca109601ebe0d1"
|
||||
integrity sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==
|
||||
"@esbuild/linux-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a"
|
||||
integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==
|
||||
|
||||
"@esbuild/openbsd-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz#7812af31b205055874c8082ea9cf9ab0da6217ae"
|
||||
integrity sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==
|
||||
"@esbuild/netbsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b"
|
||||
integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==
|
||||
|
||||
"@esbuild/sunos-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz#d5c275c3b4e73c9b0ecd38d1ca62c020f887ab9d"
|
||||
integrity sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==
|
||||
"@esbuild/netbsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b"
|
||||
integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==
|
||||
|
||||
"@esbuild/win32-arm64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz#73bc7f5a9f8a77805f357fab97f290d0e4820ac9"
|
||||
integrity sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==
|
||||
"@esbuild/openbsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7"
|
||||
integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==
|
||||
|
||||
"@esbuild/win32-ia32@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz#ec93cbf0ef1085cc12e71e0d661d20569ff42102"
|
||||
integrity sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==
|
||||
"@esbuild/openbsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde"
|
||||
integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==
|
||||
|
||||
"@esbuild/win32-x64@0.18.20":
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz#786c5f41f043b07afb1af37683d7c33668858f6d"
|
||||
integrity sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==
|
||||
"@esbuild/sunos-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92"
|
||||
integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==
|
||||
|
||||
"@esbuild/win32-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c"
|
||||
integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==
|
||||
|
||||
"@esbuild/win32-ia32@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079"
|
||||
integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==
|
||||
|
||||
"@esbuild/win32-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b"
|
||||
integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
||||
version "4.4.0"
|
||||
@@ -1225,25 +1280,15 @@ ajv-formats@^2.1.0:
|
||||
dependencies:
|
||||
ajv "^8.0.0"
|
||||
|
||||
ajv@^6.12.4:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||
ajv@^6.12.4, ajv@^8.0.0, ajv@^8.18.0, ajv@^8.6.1:
|
||||
version "8.18.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc"
|
||||
integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ajv@^8.0.0, ajv@^8.6.1:
|
||||
version "8.12.0"
|
||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
|
||||
integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-deep-equal "^3.1.3"
|
||||
fast-uri "^3.0.1"
|
||||
json-schema-traverse "^1.0.0"
|
||||
require-from-string "^2.0.2"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
@@ -1331,19 +1376,19 @@ binary-extensions@^2.0.0:
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
version "1.1.13"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.13.tgz#d37875c01dc9eff988dd49d112a57cb67b54efe6"
|
||||
integrity sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
braces@^3.0.3, braces@~3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
|
||||
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
fill-range "^7.1.1"
|
||||
|
||||
browserslist@^4.21.10, browserslist@^4.21.9:
|
||||
version "4.22.1"
|
||||
@@ -1482,10 +1527,10 @@ cosmiconfig@^8.1.3:
|
||||
parse-json "^5.2.0"
|
||||
path-type "^4.0.0"
|
||||
|
||||
cross-spawn@^7.0.2:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
cross-spawn@^7.0.2, cross-spawn@^7.0.5:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
@@ -1585,33 +1630,36 @@ error-ex@^1.3.1:
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
esbuild@^0.18.10:
|
||||
version "0.18.20"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.18.20.tgz#4709f5a34801b43b799ab7d6d82f7284a9b7a7a6"
|
||||
integrity sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==
|
||||
esbuild@0.25.0, esbuild@^0.25.0:
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92"
|
||||
integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==
|
||||
optionalDependencies:
|
||||
"@esbuild/android-arm" "0.18.20"
|
||||
"@esbuild/android-arm64" "0.18.20"
|
||||
"@esbuild/android-x64" "0.18.20"
|
||||
"@esbuild/darwin-arm64" "0.18.20"
|
||||
"@esbuild/darwin-x64" "0.18.20"
|
||||
"@esbuild/freebsd-arm64" "0.18.20"
|
||||
"@esbuild/freebsd-x64" "0.18.20"
|
||||
"@esbuild/linux-arm" "0.18.20"
|
||||
"@esbuild/linux-arm64" "0.18.20"
|
||||
"@esbuild/linux-ia32" "0.18.20"
|
||||
"@esbuild/linux-loong64" "0.18.20"
|
||||
"@esbuild/linux-mips64el" "0.18.20"
|
||||
"@esbuild/linux-ppc64" "0.18.20"
|
||||
"@esbuild/linux-riscv64" "0.18.20"
|
||||
"@esbuild/linux-s390x" "0.18.20"
|
||||
"@esbuild/linux-x64" "0.18.20"
|
||||
"@esbuild/netbsd-x64" "0.18.20"
|
||||
"@esbuild/openbsd-x64" "0.18.20"
|
||||
"@esbuild/sunos-x64" "0.18.20"
|
||||
"@esbuild/win32-arm64" "0.18.20"
|
||||
"@esbuild/win32-ia32" "0.18.20"
|
||||
"@esbuild/win32-x64" "0.18.20"
|
||||
"@esbuild/aix-ppc64" "0.25.0"
|
||||
"@esbuild/android-arm" "0.25.0"
|
||||
"@esbuild/android-arm64" "0.25.0"
|
||||
"@esbuild/android-x64" "0.25.0"
|
||||
"@esbuild/darwin-arm64" "0.25.0"
|
||||
"@esbuild/darwin-x64" "0.25.0"
|
||||
"@esbuild/freebsd-arm64" "0.25.0"
|
||||
"@esbuild/freebsd-x64" "0.25.0"
|
||||
"@esbuild/linux-arm" "0.25.0"
|
||||
"@esbuild/linux-arm64" "0.25.0"
|
||||
"@esbuild/linux-ia32" "0.25.0"
|
||||
"@esbuild/linux-loong64" "0.25.0"
|
||||
"@esbuild/linux-mips64el" "0.25.0"
|
||||
"@esbuild/linux-ppc64" "0.25.0"
|
||||
"@esbuild/linux-riscv64" "0.25.0"
|
||||
"@esbuild/linux-s390x" "0.25.0"
|
||||
"@esbuild/linux-x64" "0.25.0"
|
||||
"@esbuild/netbsd-arm64" "0.25.0"
|
||||
"@esbuild/netbsd-x64" "0.25.0"
|
||||
"@esbuild/openbsd-arm64" "0.25.0"
|
||||
"@esbuild/openbsd-x64" "0.25.0"
|
||||
"@esbuild/sunos-x64" "0.25.0"
|
||||
"@esbuild/win32-arm64" "0.25.0"
|
||||
"@esbuild/win32-ia32" "0.25.0"
|
||||
"@esbuild/win32-x64" "0.25.0"
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
@@ -1732,7 +1780,7 @@ esutils@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
@@ -1753,16 +1801,16 @@ fast-json-patch@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/fast-json-patch/-/fast-json-patch-3.1.1.tgz#85064ea1b1ebf97a3f7ad01e23f9337e72c66947"
|
||||
integrity sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
|
||||
fast-levenshtein@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||
|
||||
fast-uri@^3.0.1:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa"
|
||||
integrity sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
|
||||
@@ -1770,6 +1818,11 @@ fastq@^1.6.0:
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
fdir@^6.4.4, fdir@^6.5.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
|
||||
integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
|
||||
|
||||
file-entry-cache@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
|
||||
@@ -1777,10 +1830,10 @@ file-entry-cache@^6.0.1:
|
||||
dependencies:
|
||||
flat-cache "^3.0.4"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
@@ -1807,9 +1860,9 @@ flat-cache@^3.0.4:
|
||||
rimraf "^3.0.2"
|
||||
|
||||
flatted@^3.2.9:
|
||||
version "3.2.9"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
|
||||
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.2.tgz#f5c23c107f0f37de8dbdf24f13722b3b98d52726"
|
||||
integrity sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==
|
||||
|
||||
fraction.js@^4.3.6:
|
||||
version "4.3.7"
|
||||
@@ -1821,7 +1874,7 @@ fs.realpath@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
fsevents@~2.3.2:
|
||||
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||
@@ -2020,9 +2073,9 @@ jiti@^1.18.2:
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b"
|
||||
integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
@@ -2041,11 +2094,6 @@ json-parse-even-better-errors@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
|
||||
integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||
|
||||
json-schema-traverse@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
|
||||
@@ -2098,10 +2146,10 @@ lodash.merge@^4.6.2:
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash@^4.17.15, lodash@^4.17.21:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
lodash@^4.17.15, lodash@^4.18.1:
|
||||
version "4.18.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c"
|
||||
integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==
|
||||
|
||||
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
|
||||
version "1.4.0"
|
||||
@@ -2142,17 +2190,17 @@ merge2@^1.3.0, merge2@^1.4.1:
|
||||
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
|
||||
|
||||
micromatch@^4.0.4, micromatch@^4.0.5:
|
||||
version "4.0.5"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
|
||||
integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202"
|
||||
integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==
|
||||
dependencies:
|
||||
braces "^3.0.2"
|
||||
braces "^3.0.3"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
version "3.1.5"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e"
|
||||
integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
@@ -2170,10 +2218,10 @@ mz@^2.7.0:
|
||||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nanoid@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
nanoid@^3.3.11:
|
||||
version "3.3.11"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
|
||||
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
@@ -2293,10 +2341,20 @@ picocolors@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picocolors@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
|
||||
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.2.tgz#5a942915e26b372dc0f0e6753149a16e6b1c5601"
|
||||
integrity sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==
|
||||
|
||||
picomatch@^4.0.2, picomatch@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.4.tgz#fd6f5e00a143086e074dffe4c924b8fb293b0589"
|
||||
integrity sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==
|
||||
|
||||
pify@^2.3.0:
|
||||
version "2.3.0"
|
||||
@@ -2352,14 +2410,14 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.4.23, postcss@^8.4.27, postcss@^8.4.31:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
||||
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
||||
postcss@^8.4.23, postcss@^8.4.31, postcss@^8.5.3:
|
||||
version "8.5.9"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.9.tgz#f6ee9e0b94f0f19c97d2f172bfbd7fc71fe1cca4"
|
||||
integrity sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==
|
||||
dependencies:
|
||||
nanoid "^3.3.6"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
nanoid "^3.3.11"
|
||||
picocolors "^1.1.1"
|
||||
source-map-js "^1.2.1"
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
@@ -2375,11 +2433,6 @@ prop-types@^15.6.2, prop-types@^15.8.1:
|
||||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
|
||||
integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
@@ -2467,11 +2520,6 @@ readdirp@~3.6.0:
|
||||
dependencies:
|
||||
picomatch "^2.2.1"
|
||||
|
||||
regenerator-runtime@^0.14.0:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45"
|
||||
integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==
|
||||
|
||||
require-from-string@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||
@@ -2503,10 +2551,10 @@ rimraf@^3.0.2:
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rollup@^3.27.1:
|
||||
version "3.29.4"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.29.4.tgz#4d70c0f9834146df8705bfb69a9a19c9e1109981"
|
||||
integrity sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==
|
||||
rollup@^3.30.0, rollup@^4.34.9:
|
||||
version "3.30.0"
|
||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.30.0.tgz#3fa506fee2c5ba9d540a38da87067376cd55966d"
|
||||
integrity sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA==
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
@@ -2561,10 +2609,10 @@ snake-case@^3.0.4:
|
||||
dot-case "^3.0.4"
|
||||
tslib "^2.0.3"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
source-map-js@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
|
||||
source-map@^0.5.7:
|
||||
version "0.5.7"
|
||||
@@ -2685,6 +2733,14 @@ thenify-all@^1.0.0:
|
||||
dependencies:
|
||||
any-promise "^1.0.0"
|
||||
|
||||
tinyglobby@^0.2.13:
|
||||
version "0.2.16"
|
||||
resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.16.tgz#1c3b7eb953fce42b226bc5a1ee06428281aff3d6"
|
||||
integrity sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==
|
||||
dependencies:
|
||||
fdir "^6.5.0"
|
||||
picomatch "^4.0.4"
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
@@ -2737,13 +2793,6 @@ update-browserslist-db@^1.0.13:
|
||||
escalade "^3.1.1"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
use-callback-ref@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5"
|
||||
@@ -2790,16 +2839,19 @@ vite-plugin-svgr@^4.1.0:
|
||||
"@svgr/core" "^8.1.0"
|
||||
"@svgr/plugin-jsx" "^8.1.0"
|
||||
|
||||
vite@^4.4.5:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-4.5.0.tgz#ec406295b4167ac3bc23e26f9c8ff559287cff26"
|
||||
integrity sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==
|
||||
vite@^6.4.2:
|
||||
version "6.4.2"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-6.4.2.tgz#a4e548ca3a90ca9f3724582cab35e1ba15efc6f2"
|
||||
integrity sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==
|
||||
dependencies:
|
||||
esbuild "^0.18.10"
|
||||
postcss "^8.4.27"
|
||||
rollup "^3.27.1"
|
||||
esbuild "^0.25.0"
|
||||
fdir "^6.4.4"
|
||||
picomatch "^4.0.2"
|
||||
postcss "^8.5.3"
|
||||
rollup "^4.34.9"
|
||||
tinyglobby "^0.2.13"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
fsevents "~2.3.3"
|
||||
|
||||
which@^2.0.1:
|
||||
version "2.0.2"
|
||||
@@ -2824,14 +2876,14 @@ yallist@^4.0.0:
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yaml@^1.10.0:
|
||||
version "1.10.2"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
|
||||
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
|
||||
version "1.10.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.3.tgz#76e407ed95c42684fb8e14641e5de62fe65bbcb3"
|
||||
integrity sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==
|
||||
|
||||
yaml@^2.1.1:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.3.tgz#01f6d18ef036446340007db8e016810e5d64aad9"
|
||||
integrity sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==
|
||||
version "2.8.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.3.tgz#a0d6bd2efb3dd03c59370223701834e60409bd7d"
|
||||
integrity sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==
|
||||
|
||||
yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
|
||||
+85
-56
@@ -10,6 +10,7 @@ By default, exceptions are serialized as a generic exception without
|
||||
any information about the exception. This is done to prevent leaking
|
||||
sensitive information from the server to the client.
|
||||
"""
|
||||
|
||||
import abc
|
||||
import logging
|
||||
from functools import lru_cache
|
||||
@@ -29,15 +30,18 @@ from langchain_core.messages import (
|
||||
HumanMessageChunk,
|
||||
SystemMessage,
|
||||
SystemMessageChunk,
|
||||
ToolMessage,
|
||||
ToolMessageChunk,
|
||||
)
|
||||
from langchain_core.outputs import (
|
||||
ChatGeneration,
|
||||
ChatGenerationChunk,
|
||||
Generation,
|
||||
LLMResult,
|
||||
)
|
||||
from langchain_core.prompt_values import ChatPromptValueConcrete
|
||||
from langchain_core.prompts.base import StringPromptValue
|
||||
from pydantic import BaseModel, Field, RootModel, ValidationError
|
||||
from pydantic import BaseModel, Discriminator, Field, RootModel, Tag, ValidationError
|
||||
|
||||
from langserve.validation import CallbackEvent
|
||||
|
||||
@@ -50,33 +54,50 @@ def _log_error_message_once(error_message: str) -> None:
|
||||
logger.error(error_message)
|
||||
|
||||
|
||||
def _get_type(v: Any) -> str:
|
||||
"""Get the type associated with the object for serialization purposes."""
|
||||
if isinstance(v, dict) and "type" in v:
|
||||
return v["type"]
|
||||
elif hasattr(v, "type"):
|
||||
return v.type
|
||||
else:
|
||||
raise TypeError(
|
||||
f"Expected either a dictionary with a 'type' key or an object "
|
||||
f"with a 'type' attribute. Instead got type {type(v)}."
|
||||
)
|
||||
|
||||
|
||||
# A well known LangChain object.
|
||||
# A pydantic model that defines what constitutes a well known LangChain object.
|
||||
# All well-known objects are allowed to be serialized and de-serialized.
|
||||
|
||||
WellKnownLCObject = RootModel[
|
||||
Annotated[
|
||||
Union[
|
||||
Document,
|
||||
HumanMessage,
|
||||
SystemMessage,
|
||||
ChatMessage,
|
||||
FunctionMessage,
|
||||
AIMessage,
|
||||
HumanMessageChunk,
|
||||
SystemMessageChunk,
|
||||
ChatMessageChunk,
|
||||
FunctionMessageChunk,
|
||||
AIMessageChunk,
|
||||
StringPromptValue,
|
||||
ChatPromptValueConcrete,
|
||||
AgentAction,
|
||||
AgentFinish,
|
||||
AgentActionMessageLog,
|
||||
ChatGeneration,
|
||||
Generation,
|
||||
ChatGenerationChunk,
|
||||
Annotated[AIMessage, Tag(tag="ai")],
|
||||
Annotated[HumanMessage, Tag(tag="human")],
|
||||
Annotated[ChatMessage, Tag(tag="chat")],
|
||||
Annotated[SystemMessage, Tag(tag="system")],
|
||||
Annotated[FunctionMessage, Tag(tag="function")],
|
||||
Annotated[ToolMessage, Tag(tag="tool")],
|
||||
Annotated[AIMessageChunk, Tag(tag="AIMessageChunk")],
|
||||
Annotated[HumanMessageChunk, Tag(tag="HumanMessageChunk")],
|
||||
Annotated[ChatMessageChunk, Tag(tag="ChatMessageChunk")],
|
||||
Annotated[SystemMessageChunk, Tag(tag="SystemMessageChunk")],
|
||||
Annotated[FunctionMessageChunk, Tag(tag="FunctionMessageChunk")],
|
||||
Annotated[ToolMessageChunk, Tag(tag="ToolMessageChunk")],
|
||||
Annotated[Document, Tag(tag="Document")],
|
||||
Annotated[StringPromptValue, Tag(tag="StringPromptValue")],
|
||||
Annotated[ChatPromptValueConcrete, Tag(tag="ChatPromptValueConcrete")],
|
||||
Annotated[AgentAction, Tag(tag="AgentAction")],
|
||||
Annotated[AgentFinish, Tag(tag="AgentFinish")],
|
||||
Annotated[AgentActionMessageLog, Tag(tag="AgentActionMessageLog")],
|
||||
Annotated[ChatGeneration, Tag(tag="ChatGeneration")],
|
||||
Annotated[Generation, Tag(tag="Generation")],
|
||||
Annotated[ChatGenerationChunk, Tag(tag="ChatGenerationChunk")],
|
||||
Annotated[LLMResult, Tag(tag="LLMResult")],
|
||||
],
|
||||
Field(discriminator="type"),
|
||||
Field(discriminator=Discriminator(_get_type)),
|
||||
]
|
||||
]
|
||||
|
||||
@@ -84,7 +105,7 @@ WellKnownLCObject = RootModel[
|
||||
def default(obj) -> Any:
|
||||
"""Default serialization for well known objects."""
|
||||
if isinstance(obj, BaseModel):
|
||||
return obj.dict()
|
||||
return obj.model_dump()
|
||||
return super().default(obj)
|
||||
|
||||
|
||||
@@ -96,8 +117,6 @@ def _decode_lc_objects(value: Any) -> Any:
|
||||
try:
|
||||
obj = WellKnownLCObject.model_validate(v)
|
||||
parsed = obj.root
|
||||
if set(parsed.dict()) != set(value):
|
||||
raise ValueError("Invalid object")
|
||||
return parsed
|
||||
except (ValidationError, ValueError, TypeError):
|
||||
return v
|
||||
@@ -121,11 +140,11 @@ def _decode_event_data(value: Any) -> Any:
|
||||
"""Decode the event data from a JSON object representation."""
|
||||
if isinstance(value, dict):
|
||||
try:
|
||||
obj = CallbackEvent.parse_obj(value)
|
||||
obj = CallbackEvent.model_validate(value)
|
||||
return obj.root
|
||||
except ValidationError:
|
||||
try:
|
||||
obj = WellKnownLCObject.parse_obj(value)
|
||||
obj = WellKnownLCObject.model_validate(value)
|
||||
return obj.root
|
||||
except ValidationError:
|
||||
return {key: _decode_event_data(v) for key, v in value.items()}
|
||||
@@ -139,44 +158,54 @@ def _decode_event_data(value: Any) -> Any:
|
||||
|
||||
|
||||
class Serializer(abc.ABC):
|
||||
@abc.abstractmethod
|
||||
def dumpd(self, obj: Any) -> Any:
|
||||
"""Convert the given object to a JSON serializable object."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
"""Dump the given object as a JSON string."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def loads(self, s: bytes) -> Any:
|
||||
"""Load the given JSON string."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def loadd(self, obj: Any) -> Any:
|
||||
"""Load the given object."""
|
||||
|
||||
|
||||
class WellKnownLCSerializer(Serializer):
|
||||
def dumpd(self, obj: Any) -> Any:
|
||||
"""Convert the given object to a JSON serializable object."""
|
||||
return orjson.loads(orjson.dumps(obj, default=default))
|
||||
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
"""Dump the given object as a JSON string."""
|
||||
return orjson.dumps(obj, default=default)
|
||||
|
||||
def loadd(self, obj: Any) -> Any:
|
||||
"""Load the given object."""
|
||||
return _decode_lc_objects(obj)
|
||||
return orjson.loads(self.dumps(obj))
|
||||
|
||||
def loads(self, s: bytes) -> Any:
|
||||
"""Load the given JSON string."""
|
||||
return self.loadd(orjson.loads(s))
|
||||
|
||||
@abc.abstractmethod
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
"""Dump the given object to a JSON byte string."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def loadd(self, s: bytes) -> Any:
|
||||
"""Given a python object, load it into a well known object.
|
||||
|
||||
The obj represents content that was json loaded from a string, but
|
||||
not yet validated or converted into a well known object.
|
||||
"""
|
||||
|
||||
|
||||
class WellKnownLCSerializer(Serializer):
|
||||
"""A pre-defined serializer for well known LangChain objects.
|
||||
|
||||
This is the default serialized used by LangServe for serializing and
|
||||
de-serializing well known LangChain objects.
|
||||
|
||||
If you need to extend the serialization capabilities for your own application,
|
||||
feel free to create a new instance of the Serializer class and implement
|
||||
the abstract methods dumps and loadd.
|
||||
"""
|
||||
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
"""Dump the given object to a JSON byte string."""
|
||||
return orjson.dumps(obj, default=default)
|
||||
|
||||
def loadd(self, obj: Any) -> Any:
|
||||
"""Given a python object, load it into a well known object.
|
||||
|
||||
The obj represents content that was json loaded from a string, but
|
||||
not yet validated or converted into a well known object.
|
||||
"""
|
||||
return _decode_lc_objects(obj)
|
||||
|
||||
|
||||
def _project_top_level(model: BaseModel) -> Dict[str, Any]:
|
||||
"""Project the top level of the model as dict."""
|
||||
return {key: getattr(model, key) for key in model.__fields__}
|
||||
return {key: getattr(model, key) for key in model.model_fields}
|
||||
|
||||
|
||||
def load_events(events: Any) -> List[Dict[str, Any]]:
|
||||
@@ -207,11 +236,11 @@ def load_events(events: Any) -> List[Dict[str, Any]]:
|
||||
|
||||
# Then validate the event
|
||||
try:
|
||||
full_event = CallbackEvent.parse_obj(decoded_event_data)
|
||||
full_event = CallbackEvent.model_validate(decoded_event_data)
|
||||
except ValidationError as e:
|
||||
msg = f"Encountered an invalid event: {e}"
|
||||
if "type" in decoded_event_data:
|
||||
msg += f' of type {repr(decoded_event_data["type"])}'
|
||||
msg += f" of type {repr(decoded_event_data['type'])}"
|
||||
_log_error_message_once(msg)
|
||||
continue
|
||||
|
||||
|
||||
+59
-42
@@ -5,6 +5,8 @@ This code contains integration for langchain runnables with FastAPI.
|
||||
The main entry point is the `add_routes` function which adds the routes to an existing
|
||||
FastAPI app or APIRouter.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
import weakref
|
||||
from typing import (
|
||||
Any,
|
||||
@@ -25,12 +27,13 @@ from langserve.api_handler import (
|
||||
TokenFeedbackConfig,
|
||||
_is_hosted,
|
||||
)
|
||||
from langserve.serialization import Serializer
|
||||
|
||||
try:
|
||||
from fastapi import APIRouter, Depends, FastAPI, Request, Response
|
||||
from fastapi import APIRouter, Body, Depends, FastAPI, Request, Response
|
||||
except ImportError:
|
||||
# [server] extra not installed
|
||||
APIRouter = Depends = FastAPI = Request = Response = Any
|
||||
APIRouter = Body = Depends = FastAPI = Request = Response = Any
|
||||
|
||||
# A function that that takes a config and a raw request
|
||||
# and updates the config based on the request.
|
||||
@@ -149,9 +152,8 @@ class _EndpointConfiguration:
|
||||
else:
|
||||
enabled_endpoints_ = set(name.lower() for name in enabled_endpoints)
|
||||
if enabled_endpoints_ - KNOWN_ENDPOINTS:
|
||||
raise ValueError(
|
||||
f"Got unknown endpoint names: {enabled_endpoints_- KNOWN_ENDPOINTS}"
|
||||
)
|
||||
unknown = enabled_endpoints_ - KNOWN_ENDPOINTS
|
||||
raise ValueError(f"Got unknown endpoint names: {unknown}")
|
||||
is_invoke_enabled = "invoke" in enabled_endpoints_
|
||||
is_batch_enabled = "batch" in enabled_endpoints_
|
||||
is_stream_enabled = "stream" in enabled_endpoints_
|
||||
@@ -201,37 +203,43 @@ def _register_path_for_app(
|
||||
def _setup_global_app_handlers(
|
||||
app: Union[FastAPI, APIRouter], endpoint_configuration: _EndpointConfiguration
|
||||
) -> None:
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
LANGSERVE = r"""
|
||||
__ ___ .__ __. _______ _______. _______ .______ ____ ____ _______
|
||||
| | / \ | \ | | / _____| / || ____|| _ \ \ \ / / | ____|
|
||||
| | / ^ \ | \| | | | __ | (----`| |__ | |_) | \ \/ / | |__
|
||||
| | / /_\ \ | . ` | | | |_ | \ \ | __| | / \ / | __|
|
||||
| `----./ _____ \ | |\ | | |__| | .----) | | |____ | |\ \----. \ / | |____
|
||||
|_______/__/ \__\ |__| \__| \______| |_______/ |_______|| _| `._____| \__/ |_______|
|
||||
""" # noqa: E501
|
||||
with warnings.catch_warnings():
|
||||
# We are using deprecated functionality here.
|
||||
# We should re-write to use lifetime events at some point, and yielding
|
||||
# an APIRouter instance to the caller.
|
||||
warnings.filterwarnings(
|
||||
"ignore",
|
||||
"[\\s.]*on_event is deprecated[\\s.]*",
|
||||
category=DeprecationWarning,
|
||||
)
|
||||
|
||||
def green(text: str) -> str:
|
||||
"""Return the given text in green."""
|
||||
return "\x1b[1;32;40m" + text + "\x1b[0m"
|
||||
@app.on_event("startup")
|
||||
async def startup_event():
|
||||
LANGSERVE = r"""
|
||||
__ ___ .__ __. _______ _______. _______ .______ ____ ____ _______
|
||||
| | / \ | \ | | / _____| / || ____|| _ \ \ \ / / | ____|
|
||||
| | / ^ \ | \| | | | __ | (----`| |__ | |_) | \ \/ / | |__
|
||||
| | / /_\ \ | . ` | | | |_ | \ \ | __| | / \ / | __|
|
||||
| `----./ _____ \ | |\ | | |__| | .----) | | |____ | |\ \----. \ / | |____
|
||||
|_______/__/ \__\ |__| \__| \______| |_______/ |_______|| _| `._____| \__/ |_______|
|
||||
""" # noqa: E501
|
||||
|
||||
def orange(text: str) -> str:
|
||||
"""Return the given text in orange."""
|
||||
return "\x1b[1;31;40m" + text + "\x1b[0m"
|
||||
def green(text: str) -> str:
|
||||
"""Return the given text in green."""
|
||||
return "\x1b[1;32;40m" + text + "\x1b[0m"
|
||||
|
||||
paths = _APP_TO_PATHS[app]
|
||||
print(LANGSERVE)
|
||||
for path in paths:
|
||||
if endpoint_configuration.is_playground_enabled:
|
||||
print(
|
||||
f'{green("LANGSERVE:")} Playground for chain "{path or ""}/" is '
|
||||
f"live at:"
|
||||
)
|
||||
print(f'{green("LANGSERVE:")} │')
|
||||
print(f'{green("LANGSERVE:")} └──> {path}/playground/')
|
||||
print(f'{green("LANGSERVE:")}')
|
||||
print(f'{green("LANGSERVE:")} See all available routes at {app.docs_url}/')
|
||||
paths = _APP_TO_PATHS[app]
|
||||
print(LANGSERVE)
|
||||
for path in paths:
|
||||
if endpoint_configuration.is_playground_enabled:
|
||||
print(
|
||||
f'{green("LANGSERVE:")} Playground for chain "{path or ""}/" '
|
||||
f"is live at:"
|
||||
)
|
||||
print(f"{green('LANGSERVE:')} │")
|
||||
print(f"{green('LANGSERVE:')} └──> {path}/playground/")
|
||||
print(f"{green('LANGSERVE:')}")
|
||||
print(f"{green('LANGSERVE:')} See all available routes at {app.docs_url}/")
|
||||
|
||||
|
||||
# PUBLIC API
|
||||
@@ -255,6 +263,8 @@ def add_routes(
|
||||
enabled_endpoints: Optional[Sequence[EndpointName]] = None,
|
||||
dependencies: Optional[Sequence[Depends]] = None,
|
||||
playground_type: Literal["default", "chat"] = "default",
|
||||
astream_events_version: Literal["v1", "v2"] = "v2",
|
||||
serializer: Optional[Serializer] = None,
|
||||
) -> None:
|
||||
"""Register the routes on the given FastAPI app or APIRouter.
|
||||
|
||||
@@ -373,14 +383,18 @@ def add_routes(
|
||||
- chat: UX is optimized for chat-like interactions. Please review
|
||||
the README in langserve for more details about constraints (e.g.,
|
||||
which message types are supported etc.)
|
||||
astream_events_version: version of the stream events endpoint to use.
|
||||
By default "v2".
|
||||
serializer: The serializer to use for serializing the output. If not provided,
|
||||
the default serializer will be used.
|
||||
""" # noqa: E501
|
||||
if not isinstance(runnable, Runnable):
|
||||
raise TypeError(
|
||||
f"Expected a Runnable, got {type(runnable)}. "
|
||||
f"The second argument to add_routes should be a Runnable instance."
|
||||
f"add_route(app, runnable, ...) is the correct usage."
|
||||
f"Please make sure that you are using a runnable which is an instance of "
|
||||
f"langchain_core.runnables.Runnable."
|
||||
"The second argument to add_routes should be a Runnable instance."
|
||||
"add_route(app, runnable, ...) is the correct usage."
|
||||
"Please make sure that you are using a runnable which is an instance of "
|
||||
"langchain_core.runnables.Runnable."
|
||||
)
|
||||
|
||||
endpoint_configuration = _EndpointConfiguration(
|
||||
@@ -436,7 +450,10 @@ def add_routes(
|
||||
per_req_config_modifier=per_req_config_modifier,
|
||||
stream_log_name_allow_list=stream_log_name_allow_list,
|
||||
playground_type=playground_type,
|
||||
astream_events_version=astream_events_version,
|
||||
serializer=serializer,
|
||||
)
|
||||
|
||||
namespace = path or ""
|
||||
|
||||
route_tags = [path.strip("/")] if path else None
|
||||
@@ -745,7 +762,7 @@ def add_routes(
|
||||
if endpoint_configuration.is_invoke_enabled:
|
||||
|
||||
async def _invoke_docs(
|
||||
invoke_request: Annotated[InvokeRequest, InvokeRequest],
|
||||
invoke_request: Annotated[InvokeRequest, Body()],
|
||||
config_hash: str = "",
|
||||
) -> InvokeResponse:
|
||||
"""Invoke the runnable with the given input and config."""
|
||||
@@ -778,7 +795,7 @@ def add_routes(
|
||||
if endpoint_configuration.is_batch_enabled:
|
||||
|
||||
async def _batch_docs(
|
||||
batch_request: Annotated[BatchRequest, BatchRequest],
|
||||
batch_request: Annotated[BatchRequest, Body()],
|
||||
config_hash: str = "",
|
||||
) -> BatchResponse:
|
||||
"""Batch invoke the runnable with the given inputs and config."""
|
||||
@@ -811,7 +828,7 @@ def add_routes(
|
||||
if endpoint_configuration.is_stream_enabled:
|
||||
|
||||
async def _stream_docs(
|
||||
stream_request: Annotated[StreamRequest, StreamRequest],
|
||||
stream_request: Annotated[StreamRequest, Body()],
|
||||
config_hash: str = "",
|
||||
) -> EventSourceResponse:
|
||||
"""Invoke the runnable stream the output.
|
||||
@@ -895,7 +912,7 @@ def add_routes(
|
||||
if endpoint_configuration.is_stream_log_enabled:
|
||||
|
||||
async def _stream_log_docs(
|
||||
stream_log_request: Annotated[StreamLogRequest, StreamLogRequest],
|
||||
stream_log_request: Annotated[StreamLogRequest, Body()],
|
||||
config_hash: str = "",
|
||||
) -> EventSourceResponse:
|
||||
"""Invoke the runnable stream_log the output.
|
||||
@@ -969,7 +986,7 @@ def add_routes(
|
||||
if has_astream_events and endpoint_configuration.is_stream_events_enabled:
|
||||
|
||||
async def _stream_events_docs(
|
||||
stream_events_request: Annotated[StreamEventsRequest, StreamEventsRequest],
|
||||
stream_events_request: Annotated[StreamEventsRequest, Body()],
|
||||
config_hash: str = "",
|
||||
) -> EventSourceResponse:
|
||||
"""Stream events from the given runnable.
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"""Adapted from https://github.com/florimondmanca/httpx-sse"""
|
||||
|
||||
from contextlib import asynccontextmanager, contextmanager
|
||||
from typing import Any, AsyncIterator, Iterator, List, Optional, TypedDict
|
||||
from typing import Any, AsyncIterator, Iterator, List, Optional
|
||||
|
||||
import httpx
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
|
||||
class ServerSentEvent(TypedDict):
|
||||
|
||||
+37
-55
@@ -16,6 +16,7 @@ Models are created with a namespace to avoid name collisions when hosting
|
||||
multiple runnables. When present the name collisions prevent fastapi from
|
||||
generating OpenAPI specs.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, List, Literal, Optional, Sequence, Union
|
||||
from uuid import UUID
|
||||
|
||||
@@ -271,8 +272,7 @@ def create_invoke_response_model(
|
||||
Field(
|
||||
...,
|
||||
description=(
|
||||
"Metadata about the response that may be useful to "
|
||||
"specific clients"
|
||||
"Metadata about the response that may be useful to specific clients"
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -396,27 +396,29 @@ class StreamEventsParameters(BaseModel):
|
||||
# status code and a message.
|
||||
|
||||
|
||||
class OnChainStart(BaseModel):
|
||||
"""On Chain Start Callback Event."""
|
||||
class BaseCallback(BaseModel):
|
||||
"""Base class for all callback events."""
|
||||
|
||||
serialized: Dict[str, Any]
|
||||
inputs: Any
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
kwargs: Any = None
|
||||
|
||||
|
||||
class OnChainStart(BaseCallback):
|
||||
"""On Chain Start Callback Event."""
|
||||
|
||||
serialized: Optional[Dict[str, Any]] = None
|
||||
inputs: Any
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_chain_start"] = "on_chain_start"
|
||||
|
||||
|
||||
class OnChainEnd(BaseModel):
|
||||
class OnChainEnd(BaseCallback):
|
||||
"""On Chain End Callback Event."""
|
||||
|
||||
outputs: Any
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_chain_end"] = "on_chain_end"
|
||||
|
||||
|
||||
@@ -428,38 +430,35 @@ class Error(BaseModel):
|
||||
type: Literal["error"] = "error"
|
||||
|
||||
|
||||
class OnChainError(BaseModel):
|
||||
class OnChainError(BaseCallback):
|
||||
"""On Chain Error Callback Event."""
|
||||
|
||||
error: Error
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_chain_error"] = "on_chain_error"
|
||||
|
||||
|
||||
class OnToolStart(BaseModel):
|
||||
class OnToolStart(BaseCallback):
|
||||
"""On Tool Start Callback Event."""
|
||||
|
||||
serialized: Dict[str, Any]
|
||||
serialized: Optional[Dict[str, Any]] = None
|
||||
input_str: str
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_tool_start"] = "on_tool_start"
|
||||
|
||||
|
||||
class OnToolEnd(BaseModel):
|
||||
class OnToolEnd(BaseCallback):
|
||||
"""On Tool End Callback Event."""
|
||||
|
||||
output: str
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_tool_end"] = "on_tool_end"
|
||||
|
||||
|
||||
@@ -467,36 +466,29 @@ class OnToolError(BaseModel):
|
||||
"""On Tool Error Callback Event."""
|
||||
|
||||
error: Error
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_tool_error"] = "on_tool_error"
|
||||
|
||||
|
||||
class OnChatModelStart(BaseModel):
|
||||
class OnChatModelStart(BaseCallback):
|
||||
"""On Chat Model Start Callback Event."""
|
||||
|
||||
serialized: Dict[str, Any]
|
||||
serialized: Optional[Dict[str, Any]] = None
|
||||
messages: List[List[BaseMessage]]
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_chat_model_start"] = "on_chat_model_start"
|
||||
|
||||
|
||||
class OnLLMStart(BaseModel):
|
||||
class OnLLMStart(BaseCallback):
|
||||
"""On LLM Start Callback Event."""
|
||||
|
||||
serialized: Dict[str, Any]
|
||||
serialized: Optional[Dict[str, Any]] = None
|
||||
prompts: List[str]
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_llm_start"] = "on_llm_start"
|
||||
|
||||
|
||||
@@ -515,49 +507,39 @@ class LLMResult(BaseModel):
|
||||
"""List of metadata info for model call for each input."""
|
||||
|
||||
|
||||
class OnLLMEnd(BaseModel):
|
||||
class OnLLMEnd(BaseCallback):
|
||||
"""On LLM End Callback Event."""
|
||||
|
||||
response: LLMResult
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_llm_end"] = "on_llm_end"
|
||||
|
||||
|
||||
class OnRetrieverStart(BaseModel):
|
||||
class OnRetrieverStart(BaseCallback):
|
||||
"""On Retriever Start Callback Event."""
|
||||
|
||||
serialized: Dict[str, Any]
|
||||
serialized: Optional[Dict[str, Any]] = None
|
||||
query: str
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_retriever_start"] = "on_retriever_start"
|
||||
|
||||
|
||||
class OnRetrieverError(BaseModel):
|
||||
class OnRetrieverError(BaseCallback):
|
||||
"""On Retriever Error Callback Event."""
|
||||
|
||||
error: Error
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_retriever_error"] = "on_retriever_error"
|
||||
|
||||
|
||||
class OnRetrieverEnd(BaseModel):
|
||||
class OnRetrieverEnd(BaseCallback):
|
||||
"""On Retriever End Callback Event."""
|
||||
|
||||
documents: Sequence[Document]
|
||||
run_id: UUID
|
||||
parent_run_id: Optional[UUID] = None
|
||||
tags: Optional[List[str]] = None
|
||||
kwargs: Any = None
|
||||
kwargs: Optional[Dict[str, Any]] = None
|
||||
type: Literal["on_retriever_end"] = "on_retriever_end"
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Main entrypoint into package."""
|
||||
|
||||
from importlib import metadata
|
||||
|
||||
try:
|
||||
|
||||
@@ -20,11 +20,14 @@
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.2.29",
|
||||
"prettier": "^3.0.3",
|
||||
"tsup": "^7.2.0",
|
||||
"tsup": "^8.3.5",
|
||||
"typescript": "^5.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0 || ^18.0",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"esbuild": "0.25.0"
|
||||
}
|
||||
}
|
||||
|
||||
+372
-535
File diff suppressed because it is too large
Load Diff
Generated
+2462
-2268
File diff suppressed because it is too large
Load Diff
+27
-21
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "langserve"
|
||||
version = "0.3.0dev1"
|
||||
version = "0.3.3"
|
||||
description = ""
|
||||
readme = "README.md"
|
||||
authors = ["LangChain"]
|
||||
@@ -10,38 +10,38 @@ exclude = ["langserve/playground,langserve/chat_playground"]
|
||||
include = ["langserve/playground/dist/**/*", "langserve/chat_playground/dist/**/*"]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.9"
|
||||
httpx = ">=0.23.0" # May be able to decrease this version
|
||||
fastapi = {version = ">=0.90.1,<1", optional = true}
|
||||
python = "^3.10"
|
||||
httpx = ">=0.23.0,<1.0"
|
||||
fastapi = {version = ">=0.136.0,<1", optional = true}
|
||||
sse-starlette = {version = "^1.3.0", optional = true}
|
||||
langchain-core = "0.3.0dev4"
|
||||
orjson = ">=2"
|
||||
pyproject-toml = "^0.0.10"
|
||||
langchain-core = ">=0.3,<2"
|
||||
orjson = ">=2,<4"
|
||||
pydantic = "^2.13"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
jupyterlab = "^3.6.1"
|
||||
fastapi = ">=0.90.1"
|
||||
jupyterlab = "^4.5.3"
|
||||
fastapi = ">=0.136.0"
|
||||
sse-starlette = "^1.3.0"
|
||||
|
||||
[tool.poetry.group.typing.dependencies]
|
||||
|
||||
[tool.poetry.group.lint.dependencies]
|
||||
ruff = "^0.1.4"
|
||||
codespell = "^2.2.0"
|
||||
ruff = "^0.15.10"
|
||||
codespell = "^2.4.2"
|
||||
|
||||
[tool.poetry.group.test.dependencies]
|
||||
pytest = "^7.2.1"
|
||||
pytest-cov = "^4.0.0"
|
||||
pytest = "^9.0.3"
|
||||
pytest-cov = "^7.1.0"
|
||||
pytest-asyncio = "^0.21.1"
|
||||
pytest-mock = "^3.11.1"
|
||||
pytest-socket = "^0.6.0"
|
||||
pytest-socket = "^0.7.0"
|
||||
pytest-watch = "^4.2.0"
|
||||
pytest-timeout = "^2.2.0"
|
||||
|
||||
[tool.poetry.group.examples.dependencies]
|
||||
openai = "^0.28.0"
|
||||
uvicorn = {extras = ["standard"], version = "^0.23.2"}
|
||||
fastapi = ">=0.90.1"
|
||||
openai = "^2.30.0"
|
||||
uvicorn = {extras = ["standard"], version = "^0.44.0"}
|
||||
fastapi = ">=0.136.0"
|
||||
sse-starlette = "^1.3.0"
|
||||
|
||||
[tool.poetry.extras]
|
||||
@@ -53,16 +53,18 @@ server = ["sse-starlette", "fastapi"]
|
||||
all = ["sse-starlette", "fastapi"]
|
||||
|
||||
[tool.ruff]
|
||||
# Same as Black.
|
||||
line-length = 88
|
||||
extend-exclude = ["examples"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
"E", # pycodestyle
|
||||
"F", # pyflakes
|
||||
"I", # isort
|
||||
]
|
||||
|
||||
# Same as Black.
|
||||
line-length = 88
|
||||
|
||||
[tool.ruff.isort]
|
||||
[tool.ruff.lint.isort]
|
||||
# TODO(Team): Temporary to make isort work with examples.
|
||||
# examples assume langserve is available as a 3rd party package
|
||||
# For simplicity we'll define it as first party for now can update later.
|
||||
@@ -94,3 +96,7 @@ addopts = "--strict-markers --strict-config --durations=5 -vv"
|
||||
# take more than 5 seconds
|
||||
timeout = 5
|
||||
asyncio_mode = "auto"
|
||||
filterwarnings = [
|
||||
"ignore::langchain_core._api.beta_decorator.LangChainBetaWarning",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Test the playground API."""
|
||||
|
||||
import httpx
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from httpx import AsyncClient
|
||||
from langchain_core.runnables import RunnableLambda
|
||||
@@ -15,7 +16,9 @@ async def test_serve_playground() -> None:
|
||||
RunnableLambda(lambda foo: "hello"),
|
||||
)
|
||||
|
||||
async with AsyncClient(app=app, base_url="http://localhost:9999") as client:
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as client:
|
||||
response = await client.get("/playground/index.html")
|
||||
assert response.status_code == 200
|
||||
# Test that we can't access files that do not exist.
|
||||
@@ -42,7 +45,9 @@ async def test_serve_playground_with_api_router() -> None:
|
||||
|
||||
app.include_router(router)
|
||||
|
||||
async with AsyncClient(app=app, base_url="http://localhost:9999") as client:
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as client:
|
||||
response = await client.get("/langserve_runnables/chat/playground/index.html")
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -64,7 +69,9 @@ async def test_serve_playground_with_api_router_in_api_router() -> None:
|
||||
# Now add parent router to the app
|
||||
app.include_router(parent_router)
|
||||
|
||||
async with AsyncClient(app=app, base_url="http://localhost:9999") as client:
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as client:
|
||||
response = await client.get("/parent/bar/foo/playground/index.html")
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -88,7 +95,9 @@ async def test_root_path_on_playground() -> None:
|
||||
)
|
||||
app.include_router(router)
|
||||
|
||||
async_client = AsyncClient(app=app, base_url="http://localhost:9999")
|
||||
async_client = AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
)
|
||||
|
||||
response = await async_client.get("/chat/playground/index.html")
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import Any
|
||||
import pytest
|
||||
from langchain_core.documents.base import Document
|
||||
from langchain_core.messages import HumanMessage, HumanMessageChunk, SystemMessage
|
||||
from langchain_core.outputs import ChatGeneration
|
||||
from pydantic import BaseModel
|
||||
|
||||
from langserve.serialization import (
|
||||
@@ -18,7 +19,7 @@ from langserve.serialization import (
|
||||
def test_document_serialization() -> None:
|
||||
"""Simple test. Exhaustive tests follow below."""
|
||||
doc = Document(page_content="hello")
|
||||
d = doc.dict()
|
||||
d = doc.model_dump()
|
||||
WellKnownLCObject.model_validate(d)
|
||||
|
||||
|
||||
@@ -48,8 +49,7 @@ def test_document_serialization() -> None:
|
||||
"numbers": [1, 2, 3],
|
||||
"boom": "Hello, world!",
|
||||
},
|
||||
# Requires typing ChatGeneration with Anymessage
|
||||
# [ChatGeneration(message=HumanMessage(content="Hello"))],
|
||||
[ChatGeneration(message=HumanMessage(content="Hello"))],
|
||||
],
|
||||
)
|
||||
def test_serialization(data: Any) -> None:
|
||||
@@ -87,7 +87,7 @@ def _get_full_representation(data: Any) -> Any:
|
||||
elif isinstance(data, list):
|
||||
return [_get_full_representation(value) for value in data]
|
||||
elif isinstance(data, BaseModel):
|
||||
return data.schema()
|
||||
return data.model_json_schema()
|
||||
else:
|
||||
return data
|
||||
|
||||
@@ -189,10 +189,3 @@ def test_encoding_of_well_known_types(obj: Any, expected: str) -> None:
|
||||
"""
|
||||
lc_serializer = WellKnownLCSerializer()
|
||||
assert lc_serializer.dumpd(obj) == expected
|
||||
|
||||
|
||||
@pytest.mark.xfail(reason="0.3")
|
||||
def test_fail_03() -> None:
|
||||
"""This test will fail on purposes. It contains a TODO list for 0.3 release."""
|
||||
assert "LLMResult" == "WellKnocnLCOBject contains it" # Requires type
|
||||
assert "CHatGeneration_Deserialized correct" == "UNcomment test above"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Test the server and client together."""
|
||||
|
||||
import asyncio
|
||||
import datetime
|
||||
import json
|
||||
import sys
|
||||
import uuid
|
||||
from asyncio import AbstractEventLoop
|
||||
from contextlib import asynccontextmanager, contextmanager
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
@@ -57,6 +57,7 @@ from langchain_core.tracers import RunLog, RunLogPatch
|
||||
from langsmith import schemas as ls_schemas
|
||||
from langsmith.client import Client
|
||||
from langsmith.schemas import FeedbackIngestToken
|
||||
from orjson import orjson
|
||||
from pydantic import BaseModel, Field, __version__
|
||||
from pytest import MonkeyPatch
|
||||
from pytest_mock import MockerFixture
|
||||
@@ -123,7 +124,20 @@ def _replace_run_id_in_stream_resp(streamed_resp: str) -> str:
|
||||
return streamed_resp.replace(uuid, "<REPLACED>")
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def _null_run_id_and_metadata_recursively(decoded_response: Any) -> None:
|
||||
"""Recursively traverse the object and delete any keys called run_id"""
|
||||
if isinstance(decoded_response, dict):
|
||||
for key, value in decoded_response.items():
|
||||
if key in {"run_id", "__langserve_version", "__useragent"}:
|
||||
decoded_response[key] = None
|
||||
else:
|
||||
_null_run_id_and_metadata_recursively(value)
|
||||
elif isinstance(decoded_response, list):
|
||||
for item in decoded_response:
|
||||
_null_run_id_and_metadata_recursively(item)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def event_loop():
|
||||
"""Create an instance of the default event loop for each test case."""
|
||||
loop = asyncio.get_event_loop()
|
||||
@@ -134,7 +148,7 @@ def event_loop():
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def app(event_loop: AbstractEventLoop) -> FastAPI:
|
||||
def app() -> FastAPI:
|
||||
"""A simple server that wraps a Runnable and exposes it as an API."""
|
||||
|
||||
async def add_one_or_passthrough(
|
||||
@@ -158,7 +172,7 @@ def app(event_loop: AbstractEventLoop) -> FastAPI:
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def app_for_config(event_loop: AbstractEventLoop) -> FastAPI:
|
||||
def app_for_config() -> FastAPI:
|
||||
"""A simple server that wraps a Runnable and exposes it as an API."""
|
||||
|
||||
async def return_config(
|
||||
@@ -223,7 +237,7 @@ async def get_async_test_client(
|
||||
app=server,
|
||||
raise_app_exceptions=raise_app_exceptions,
|
||||
)
|
||||
async_client = AsyncClient(app=server, base_url=url, transport=transport)
|
||||
async_client = AsyncClient(base_url=url, transport=transport)
|
||||
try:
|
||||
yield async_client
|
||||
finally:
|
||||
@@ -232,13 +246,17 @@ async def get_async_test_client(
|
||||
|
||||
@asynccontextmanager
|
||||
async def get_async_remote_runnable(
|
||||
server: FastAPI, *, path: Optional[str] = None, raise_app_exceptions: bool = True
|
||||
server: FastAPI,
|
||||
*,
|
||||
path: Optional[str] = None,
|
||||
raise_app_exceptions: bool = True,
|
||||
**kwargs: Any,
|
||||
) -> RemoteRunnable:
|
||||
"""Get an async client."""
|
||||
url = "http://localhost:9999"
|
||||
if path:
|
||||
url += path
|
||||
remote_runnable_client = RemoteRunnable(url=url)
|
||||
remote_runnable_client = RemoteRunnable(url=url, **kwargs)
|
||||
|
||||
async with get_async_test_client(
|
||||
server, path=path, raise_app_exceptions=raise_app_exceptions
|
||||
@@ -333,7 +351,7 @@ async def test_server_async(app: FastAPI) -> None:
|
||||
# test bad requests
|
||||
async with get_async_test_client(app, raise_app_exceptions=True) as async_client:
|
||||
# Test invoke
|
||||
response = await async_client.post("/invoke", data="bad json []")
|
||||
response = await async_client.post("/invoke", content="bad json []")
|
||||
# Client side error bad json.
|
||||
assert response.status_code == 422
|
||||
|
||||
@@ -353,7 +371,7 @@ async def test_server_async(app: FastAPI) -> None:
|
||||
async with get_async_test_client(app, raise_app_exceptions=True) as async_client:
|
||||
# Test invoke
|
||||
# Test bad batch requests
|
||||
response = await async_client.post("/batch", data="bad json []")
|
||||
response = await async_client.post("/batch", content="bad json []")
|
||||
# Client side error bad json.
|
||||
assert response.status_code == 422
|
||||
|
||||
@@ -378,7 +396,7 @@ async def test_server_async(app: FastAPI) -> None:
|
||||
# test stream bad requests
|
||||
async with get_async_test_client(app, raise_app_exceptions=True) as async_client:
|
||||
# Test bad stream requests
|
||||
response = await async_client.post("/stream", data="bad json []")
|
||||
response = await async_client.post("/stream", content="bad json []")
|
||||
assert response.status_code == 422
|
||||
|
||||
response = await async_client.post("/stream", json={})
|
||||
@@ -386,7 +404,7 @@ async def test_server_async(app: FastAPI) -> None:
|
||||
|
||||
# test stream_log bad requests
|
||||
async with get_async_test_client(app, raise_app_exceptions=True) as async_client:
|
||||
response = await async_client.post("/stream_log", data="bad json []")
|
||||
response = await async_client.post("/stream_log", content="bad json []")
|
||||
assert response.status_code == 422
|
||||
|
||||
response = await async_client.post("/stream_log", json={})
|
||||
@@ -448,7 +466,7 @@ async def test_server_astream_events(app: FastAPI) -> None:
|
||||
|
||||
# test stream_events with bad requests
|
||||
async with get_async_test_client(app, raise_app_exceptions=True) as async_client:
|
||||
response = await async_client.post("/stream_events", data="bad json []")
|
||||
response = await async_client.post("/stream_events", content="bad json []")
|
||||
assert response.status_code == 422
|
||||
|
||||
response = await async_client.post("/stream_events", json={})
|
||||
@@ -457,7 +475,10 @@ async def test_server_astream_events(app: FastAPI) -> None:
|
||||
|
||||
async def test_server_bound_async(app_for_config: FastAPI) -> None:
|
||||
"""Test the server directly via HTTP requests."""
|
||||
async_client = AsyncClient(app=app_for_config, base_url="http://localhost:9999")
|
||||
async_client = AsyncClient(
|
||||
base_url="http://localhost:9999",
|
||||
transport=httpx.ASGITransport(app=app_for_config),
|
||||
)
|
||||
config_hash = LZString.compressToEncodedURIComponent(json.dumps({"tags": ["test"]}))
|
||||
|
||||
# Test invoke
|
||||
@@ -521,6 +542,15 @@ def test_invoke(sync_remote_runnable: RemoteRunnable) -> None:
|
||||
assert remote_runnable_run.child_runs[0].name == "add_one_or_passthrough"
|
||||
|
||||
|
||||
def test_batch_tracer_with_single_input(sync_remote_runnable: RemoteRunnable) -> None:
|
||||
"""Test passing a single tracer to batch."""
|
||||
tracer = FakeTracer()
|
||||
assert sync_remote_runnable.batch([1], config={"callbacks": [tracer]}) == [2]
|
||||
assert len(tracer.runs) == 1
|
||||
assert len(tracer.runs[0].child_runs) == 1
|
||||
assert tracer.runs[0].child_runs[0].name == "add_one_or_passthrough"
|
||||
|
||||
|
||||
def test_batch(sync_remote_runnable: RemoteRunnable) -> None:
|
||||
"""Test sync batch."""
|
||||
assert sync_remote_runnable.batch([]) == []
|
||||
@@ -534,17 +564,9 @@ def test_batch(sync_remote_runnable: RemoteRunnable) -> None:
|
||||
tracer = FakeTracer()
|
||||
assert sync_remote_runnable.batch([1, 2], config={"callbacks": [tracer]}) == [2, 3]
|
||||
assert len(tracer.runs) == 2
|
||||
# Light test to verify that we're picking up information about the server side
|
||||
# function being invoked via a callback.
|
||||
assert tracer.runs[0].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer.runs[0].child_runs[0].extra["kwargs"]["name"] == "add_one_or_passthrough"
|
||||
)
|
||||
|
||||
assert tracer.runs[1].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer.runs[1].child_runs[0].extra["kwargs"]["name"] == "add_one_or_passthrough"
|
||||
)
|
||||
assert tracer.runs[0].child_runs[0].name == "add_one_or_passthrough"
|
||||
assert tracer.runs[1].child_runs[0].name == "add_one_or_passthrough"
|
||||
|
||||
# Verify that each tracer gets its own run
|
||||
tracer1 = FakeTracer()
|
||||
@@ -556,17 +578,8 @@ def test_batch(sync_remote_runnable: RemoteRunnable) -> None:
|
||||
assert len(tracer2.runs) == 1
|
||||
# Light test to verify that we're picking up information about the server side
|
||||
# function being invoked via a callback.
|
||||
assert tracer1.runs[0].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer1.runs[0].child_runs[0].extra["kwargs"]["name"]
|
||||
== "add_one_or_passthrough"
|
||||
)
|
||||
|
||||
assert tracer2.runs[0].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer2.runs[0].child_runs[0].extra["kwargs"]["name"]
|
||||
== "add_one_or_passthrough"
|
||||
)
|
||||
assert tracer1.runs[0].child_runs[0].name == "add_one_or_passthrough"
|
||||
assert tracer2.runs[0].child_runs[0].name == "add_one_or_passthrough"
|
||||
|
||||
|
||||
async def test_ainvoke(async_remote_runnable: RemoteRunnable) -> None:
|
||||
@@ -599,10 +612,7 @@ async def test_ainvoke(async_remote_runnable: RemoteRunnable) -> None:
|
||||
elif sys.version_info < (3, 11):
|
||||
assert len(tracer.runs) == 1, "Failed for python < 3.11"
|
||||
remote_runnable = tracer.runs[0]
|
||||
assert (
|
||||
remote_runnable.child_runs[0].extra["kwargs"]["name"]
|
||||
== "add_one_or_passthrough"
|
||||
)
|
||||
assert remote_runnable.name == "RemoteRunnable"
|
||||
else:
|
||||
raise AssertionError(f"Unsupported python version {sys.version_info}")
|
||||
|
||||
@@ -622,17 +632,9 @@ async def test_abatch(async_remote_runnable: RemoteRunnable) -> None:
|
||||
[1, 2], config={"callbacks": [tracer]}
|
||||
) == [2, 3]
|
||||
assert len(tracer.runs) == 2
|
||||
# Light test to verify that we're picking up information about the server side
|
||||
# function being invoked via a callback.
|
||||
assert tracer.runs[0].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer.runs[0].child_runs[0].extra["kwargs"]["name"] == "add_one_or_passthrough"
|
||||
)
|
||||
|
||||
assert tracer.runs[1].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer.runs[1].child_runs[0].extra["kwargs"]["name"] == "add_one_or_passthrough"
|
||||
)
|
||||
assert tracer.runs[0].child_runs[0].name == "add_one_or_passthrough"
|
||||
assert tracer.runs[1].child_runs[0].name == "add_one_or_passthrough"
|
||||
|
||||
# Verify that each tracer gets its own run
|
||||
tracer1 = FakeTracer()
|
||||
@@ -642,19 +644,9 @@ async def test_abatch(async_remote_runnable: RemoteRunnable) -> None:
|
||||
) == [2, 3]
|
||||
assert len(tracer1.runs) == 1
|
||||
assert len(tracer2.runs) == 1
|
||||
# Light test to verify that we're picking up information about the server side
|
||||
# function being invoked via a callback.
|
||||
assert tracer1.runs[0].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer1.runs[0].child_runs[0].extra["kwargs"]["name"]
|
||||
== "add_one_or_passthrough"
|
||||
)
|
||||
|
||||
assert tracer2.runs[0].child_runs[0].name == "RunnableLambda"
|
||||
assert (
|
||||
tracer2.runs[0].child_runs[0].extra["kwargs"]["name"]
|
||||
== "add_one_or_passthrough"
|
||||
)
|
||||
assert tracer1.runs[0].child_runs[0].name == "add_one_or_passthrough"
|
||||
assert tracer2.runs[0].child_runs[0].name == "add_one_or_passthrough"
|
||||
|
||||
|
||||
async def test_astream(async_remote_runnable: RemoteRunnable) -> None:
|
||||
@@ -851,7 +843,7 @@ async def test_streaming_with_errors() -> None:
|
||||
assert e.value.response.status_code == 500
|
||||
|
||||
|
||||
async def test_astream_log_allowlist(event_loop: AbstractEventLoop) -> None:
|
||||
async def test_astream_log_allowlist() -> None:
|
||||
"""Test async stream with an allowlist."""
|
||||
|
||||
async def add_one(x: int) -> int:
|
||||
@@ -1032,7 +1024,7 @@ async def test_invoke_as_part_of_sequence_async(
|
||||
}
|
||||
|
||||
|
||||
async def test_multiple_runnables(event_loop: AbstractEventLoop) -> None:
|
||||
async def test_multiple_runnables() -> None:
|
||||
"""Test serving multiple runnables."""
|
||||
|
||||
async def add_one(x: int) -> int:
|
||||
@@ -1105,7 +1097,9 @@ async def test_config_keys_validation(mocker: MockerFixture) -> None:
|
||||
input_type=int,
|
||||
config_keys=["metadata"],
|
||||
)
|
||||
async with AsyncClient(app=app, base_url="http://localhost:9999") as async_client:
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as async_client:
|
||||
server_runnable_spy = mocker.spy(server_runnable, "ainvoke")
|
||||
response = await async_client.post(
|
||||
"/invoke",
|
||||
@@ -1124,6 +1118,156 @@ async def test_config_keys_validation(mocker: MockerFixture) -> None:
|
||||
assert config_seen["metadata"]["__langserve_endpoint"] == "invoke"
|
||||
|
||||
|
||||
async def test_include_callback_events(mocker: MockerFixture) -> None:
|
||||
"""This test should not use a RemoteRunnable.
|
||||
|
||||
Check if callback events are being sent back from the server.
|
||||
|
||||
Do so using the raw client.
|
||||
"""
|
||||
|
||||
async def add_one(x: int) -> int:
|
||||
"""Add one to simulate a valid function"""
|
||||
return x + 1
|
||||
|
||||
server_runnable = RunnableLambda(func=add_one)
|
||||
|
||||
app = FastAPI()
|
||||
add_routes(app, server_runnable, input_type=int, include_callback_events=True)
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as async_client:
|
||||
response = await async_client.post("/invoke", json={"input": 1})
|
||||
# Config should be ignored but default debug information
|
||||
# will still be added
|
||||
assert response.status_code == 200
|
||||
decoded_response = response.json()
|
||||
# Remove any run_id from the response recursively
|
||||
_null_run_id_and_metadata_recursively(decoded_response)
|
||||
assert decoded_response == {
|
||||
"callback_events": [
|
||||
{
|
||||
"inputs": 1,
|
||||
"kwargs": {"name": "add_one", "run_type": None},
|
||||
"metadata": {
|
||||
"__langserve_endpoint": "invoke",
|
||||
"__langserve_version": None,
|
||||
"__useragent": None,
|
||||
},
|
||||
"parent_run_id": None,
|
||||
"serialized": None,
|
||||
"run_id": None,
|
||||
"tags": [],
|
||||
"type": "on_chain_start",
|
||||
},
|
||||
{
|
||||
"kwargs": {},
|
||||
"outputs": 2,
|
||||
"metadata": None,
|
||||
"parent_run_id": None,
|
||||
"tags": [],
|
||||
"run_id": None,
|
||||
"type": "on_chain_end",
|
||||
},
|
||||
],
|
||||
"metadata": {
|
||||
"feedback_tokens": [],
|
||||
"run_id": None,
|
||||
},
|
||||
"output": 2,
|
||||
}
|
||||
|
||||
|
||||
async def test_include_callback_events_batch() -> None:
|
||||
"""This test should not use a RemoteRunnable.
|
||||
|
||||
Check if callback events are being sent back from the server.
|
||||
|
||||
Do so using the raw client.
|
||||
"""
|
||||
|
||||
async def add_one(x: int) -> int:
|
||||
"""Add one to simulate a valid function"""
|
||||
return x + 1
|
||||
|
||||
server_runnable = RunnableLambda(func=add_one)
|
||||
|
||||
app = FastAPI()
|
||||
add_routes(app, server_runnable, input_type=int, include_callback_events=True)
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as async_client:
|
||||
response = await async_client.post("/batch", json={"inputs": [1, 2]})
|
||||
# Config should be ignored but default debug information
|
||||
# will still be added
|
||||
assert response.status_code == 200
|
||||
decoded_response = response.json()
|
||||
# Remove any run_id from the response recursively
|
||||
_null_run_id_and_metadata_recursively(decoded_response)
|
||||
del decoded_response["metadata"]["run_ids"]
|
||||
assert decoded_response == {
|
||||
"callback_events": [
|
||||
[
|
||||
{
|
||||
"inputs": 1,
|
||||
"kwargs": {"name": "add_one", "run_type": None},
|
||||
"metadata": {
|
||||
"__langserve_endpoint": "batch",
|
||||
"__langserve_version": None,
|
||||
"__useragent": None,
|
||||
},
|
||||
"parent_run_id": None,
|
||||
"run_id": None,
|
||||
"serialized": None,
|
||||
"tags": [],
|
||||
"type": "on_chain_start",
|
||||
},
|
||||
{
|
||||
"kwargs": {},
|
||||
"outputs": 2,
|
||||
"parent_run_id": None,
|
||||
"metadata": None,
|
||||
"run_id": None,
|
||||
"tags": [],
|
||||
"type": "on_chain_end",
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
"inputs": 2,
|
||||
"kwargs": {"name": "add_one", "run_type": None},
|
||||
"metadata": {
|
||||
"__langserve_endpoint": "batch",
|
||||
"__langserve_version": None,
|
||||
"__useragent": None,
|
||||
},
|
||||
"parent_run_id": None,
|
||||
"run_id": None,
|
||||
"serialized": None,
|
||||
"tags": [],
|
||||
"type": "on_chain_start",
|
||||
},
|
||||
{
|
||||
"kwargs": {},
|
||||
"outputs": 3,
|
||||
"parent_run_id": None,
|
||||
"metadata": None,
|
||||
"run_id": None,
|
||||
"tags": [],
|
||||
"type": "on_chain_end",
|
||||
},
|
||||
],
|
||||
],
|
||||
"metadata": {
|
||||
"responses": [
|
||||
{"feedback_tokens": [], "run_id": None},
|
||||
{"feedback_tokens": [], "run_id": None},
|
||||
],
|
||||
},
|
||||
"output": [2, 3],
|
||||
}
|
||||
|
||||
|
||||
async def test_input_validation(mocker: MockerFixture) -> None:
|
||||
"""Test client side and server side exceptions."""
|
||||
|
||||
@@ -1154,7 +1298,7 @@ async def test_input_validation(mocker: MockerFixture) -> None:
|
||||
await runnable.abatch(["hello"])
|
||||
|
||||
|
||||
async def test_input_validation_with_lc_types(event_loop: AbstractEventLoop) -> None:
|
||||
async def test_input_validation_with_lc_types() -> None:
|
||||
"""Test client side and server side exceptions."""
|
||||
|
||||
app = FastAPI()
|
||||
@@ -1247,9 +1391,7 @@ async def test_async_client_close() -> None:
|
||||
assert async_client.is_closed is True
|
||||
|
||||
|
||||
async def test_openapi_docs_with_identical_runnables(
|
||||
event_loop: AbstractEventLoop, mocker: MockerFixture
|
||||
) -> None:
|
||||
async def test_openapi_docs_with_identical_runnables(mocker: MockerFixture) -> None:
|
||||
"""Test client side and server side exceptions."""
|
||||
|
||||
async def add_one(x: int) -> int:
|
||||
@@ -1289,12 +1431,14 @@ async def test_openapi_docs_with_identical_runnables(
|
||||
config_keys=["tags"],
|
||||
)
|
||||
|
||||
async with AsyncClient(app=app, base_url="http://localhost:9999") as async_client:
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as async_client:
|
||||
response = await async_client.get("/openapi.json")
|
||||
assert response.status_code == 200
|
||||
|
||||
|
||||
async def test_configurable_runnables(event_loop: AbstractEventLoop) -> None:
|
||||
async def test_configurable_runnables() -> None:
|
||||
"""Add tests for using langchain's configurable runnables"""
|
||||
|
||||
template = PromptTemplate.from_template("say {name}").configurable_fields(
|
||||
@@ -1384,7 +1528,7 @@ def test_rename_pydantic_model() -> None:
|
||||
assert Model.__name__ == "BarFoo"
|
||||
|
||||
|
||||
async def test_input_config_output_schemas(event_loop: AbstractEventLoop) -> None:
|
||||
async def test_input_config_output_schemas() -> None:
|
||||
"""Test schemas returned for different configurations."""
|
||||
# TODO(Fix me): need to fix handling of global state -- we get problems
|
||||
# gives inconsistent results when running multiple tests / results
|
||||
@@ -1423,7 +1567,9 @@ async def test_input_config_output_schemas(event_loop: AbstractEventLoop) -> Non
|
||||
)
|
||||
add_routes(app, template, path="/prompt_2", config_keys=["tags", "configurable"])
|
||||
|
||||
async with AsyncClient(app=app, base_url="http://localhost:9999") as async_client:
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as async_client:
|
||||
# input schema
|
||||
response = await async_client.get("/add_one/input_schema")
|
||||
assert response.json() == {"title": "add_one_input", "type": "integer"}
|
||||
@@ -1495,12 +1641,7 @@ async def test_input_config_output_schemas(event_loop: AbstractEventLoop) -> Non
|
||||
"properties": {
|
||||
"template": {
|
||||
"default": "say {name}",
|
||||
"description": "The "
|
||||
"template "
|
||||
"to use "
|
||||
"for "
|
||||
"the "
|
||||
"prompt",
|
||||
"description": "The template to use for the prompt",
|
||||
"title": "Template",
|
||||
"type": "string",
|
||||
}
|
||||
@@ -1531,12 +1672,7 @@ async def test_input_config_output_schemas(event_loop: AbstractEventLoop) -> Non
|
||||
"properties": {
|
||||
"template": {
|
||||
"default": "say {name}",
|
||||
"description": "The "
|
||||
"template "
|
||||
"to use "
|
||||
"for "
|
||||
"the "
|
||||
"prompt",
|
||||
"description": "The template to use for the prompt",
|
||||
"title": "Template",
|
||||
"type": "string",
|
||||
}
|
||||
@@ -1574,7 +1710,9 @@ async def test_input_schema_typed_dict() -> None:
|
||||
app = FastAPI()
|
||||
add_routes(app, runnable_lambda, input_type=InputType, config_keys=["tags"])
|
||||
|
||||
async with AsyncClient(app=app, base_url="http://localhost:9999") as client:
|
||||
async with AsyncClient(
|
||||
base_url="http://localhost:9999", transport=httpx.ASGITransport(app=app)
|
||||
) as client:
|
||||
res = await client.get("/input_schema")
|
||||
if PYDANTIC_VERSION < (2, 9):
|
||||
assert res.json() == {
|
||||
@@ -1742,7 +1880,7 @@ async def test_server_side_error() -> None:
|
||||
# assert e.response.text == "Internal Server Error"
|
||||
|
||||
|
||||
def test_server_side_error_sync(event_loop: AbstractEventLoop) -> None:
|
||||
def test_server_side_error_sync() -> None:
|
||||
"""Test server side error handling."""
|
||||
|
||||
app = FastAPI()
|
||||
@@ -1876,6 +2014,7 @@ async def test_feedback_succeeds_when_langsmith_enabled() -> None:
|
||||
created_at=datetime.datetime(1994, 9, 19, 9, 19),
|
||||
modified_at=datetime.datetime(1994, 9, 19, 9, 19),
|
||||
run_id="f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||
trace_id="f47ac10b-58cc-4372-a567-0e02b2c3d479",
|
||||
key="silliness",
|
||||
score=1000,
|
||||
)
|
||||
@@ -1971,7 +2110,7 @@ async def test_enforce_trailing_slash_in_client() -> None:
|
||||
assert r.url == "nosuchurl/"
|
||||
|
||||
|
||||
async def test_per_request_config_modifier(event_loop: AbstractEventLoop) -> None:
|
||||
async def test_per_request_config_modifier() -> None:
|
||||
"""Test updating the config based on the raw request object."""
|
||||
|
||||
async def add_one(x: int) -> int:
|
||||
@@ -2014,9 +2153,7 @@ async def test_per_request_config_modifier(event_loop: AbstractEventLoop) -> Non
|
||||
assert response.json()["output"] == 2
|
||||
|
||||
|
||||
async def test_per_request_config_modifier_endpoints(
|
||||
event_loop: AbstractEventLoop,
|
||||
) -> None:
|
||||
async def test_per_request_config_modifier_endpoints() -> None:
|
||||
"""Verify that per request modifier is only applied for the expected endpoints."""
|
||||
|
||||
# this test verifies that per request modifier is only
|
||||
@@ -2086,7 +2223,7 @@ async def test_per_request_config_modifier_endpoints(
|
||||
assert response.status_code != 500
|
||||
|
||||
|
||||
async def test_uuid_serialization(event_loop: AbstractEventLoop) -> None:
|
||||
async def test_uuid_serialization() -> None:
|
||||
"""Test updating the config based on the raw request object."""
|
||||
import datetime
|
||||
|
||||
@@ -2140,6 +2277,49 @@ async def test_uuid_serialization(event_loop: AbstractEventLoop) -> None:
|
||||
)
|
||||
|
||||
|
||||
async def test_custom_serialization() -> None:
|
||||
"""Test updating the config based on the raw request object."""
|
||||
from langserve.serialization import Serializer
|
||||
|
||||
class CustomObject:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
return self.x == other.x
|
||||
|
||||
class CustomSerializer(Serializer):
|
||||
def dumps(self, obj: Any) -> bytes:
|
||||
"""Dump the given object as a JSON string."""
|
||||
if isinstance(obj, CustomObject):
|
||||
return orjson.dumps({"x": obj.x})
|
||||
else:
|
||||
return orjson.dumps(obj)
|
||||
|
||||
def loadd(self, obj: Any) -> Any:
|
||||
"""Load the given object."""
|
||||
if isinstance(obj, bytes):
|
||||
obj = obj.decode("utf-8")
|
||||
if obj.get("x"):
|
||||
return CustomObject(x=obj["x"])
|
||||
return obj
|
||||
|
||||
def foo(x: int) -> Any:
|
||||
"""Add one to simulate a valid function."""
|
||||
return CustomObject(x=5)
|
||||
|
||||
app = FastAPI()
|
||||
server_runnable = RunnableLambda(foo)
|
||||
add_routes(app, server_runnable, serializer=CustomSerializer())
|
||||
|
||||
async with get_async_remote_runnable(
|
||||
app, raise_app_exceptions=True, serializer=CustomSerializer()
|
||||
) as runnable:
|
||||
result = await runnable.ainvoke(5)
|
||||
assert isinstance(result, CustomObject)
|
||||
assert result == CustomObject(x=5)
|
||||
|
||||
|
||||
async def test_endpoint_configurations() -> None:
|
||||
"""Test enabling/disabling endpoints."""
|
||||
app = FastAPI()
|
||||
@@ -2241,9 +2421,9 @@ async def test_endpoint_configurations() -> None:
|
||||
error_codes = {404}
|
||||
else:
|
||||
error_codes = {404, 405}
|
||||
assert (
|
||||
response.status_code not in error_codes
|
||||
), f"endpoint {endpoint} should be on"
|
||||
assert response.status_code not in error_codes, (
|
||||
f"endpoint {endpoint} should be on"
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
# Passing "invoke" instead of ["invoke"]
|
||||
@@ -2300,7 +2480,7 @@ async def test_astream_events_simple(async_remote_runnable: RemoteRunnable) -> N
|
||||
# test client side error
|
||||
with pytest.raises(httpx.HTTPStatusError) as cb:
|
||||
# Invalid input type (expected string but got int)
|
||||
async for _ in runnable.astream_events("foo", version="v1"):
|
||||
async for _ in runnable.astream_events("foo", version="v2"):
|
||||
pass
|
||||
|
||||
# Verify that this is a 422 error
|
||||
@@ -2309,7 +2489,7 @@ async def test_astream_events_simple(async_remote_runnable: RemoteRunnable) -> N
|
||||
with pytest.raises(httpx.HTTPStatusError) as cb:
|
||||
# Invalid input type (expected string but got int)
|
||||
# include names should not be a list of lists
|
||||
async for _ in runnable.astream_events(1, include_names=[[]], version="v1"):
|
||||
async for _ in runnable.astream_events(1, include_names=[[]], version="v2"):
|
||||
pass
|
||||
|
||||
# Verify that this is a 422 error
|
||||
@@ -2318,7 +2498,7 @@ async def test_astream_events_simple(async_remote_runnable: RemoteRunnable) -> N
|
||||
# Test good requests
|
||||
events = []
|
||||
|
||||
async for event in runnable.astream_events(1, version="v1"):
|
||||
async for event in runnable.astream_events(1, version="v2"):
|
||||
events.append(event)
|
||||
|
||||
# validate events
|
||||
@@ -2331,6 +2511,7 @@ async def test_astream_events_simple(async_remote_runnable: RemoteRunnable) -> N
|
||||
assert not k.startswith("__")
|
||||
assert "metadata" in event
|
||||
del event["metadata"]
|
||||
event["parent_ids"] = []
|
||||
|
||||
assert events == [
|
||||
{
|
||||
@@ -2410,6 +2591,7 @@ def _clean_up_events(events: List[Dict[str, Any]]) -> None:
|
||||
assert not k.startswith("__")
|
||||
assert "metadata" in event
|
||||
del event["metadata"]
|
||||
event["parent_ids"] = []
|
||||
|
||||
|
||||
async def test_astream_events_with_serialization(
|
||||
@@ -2482,7 +2664,7 @@ async def test_astream_events_with_serialization(
|
||||
app, raise_app_exceptions=False, path="/doc_types"
|
||||
) as runnable:
|
||||
# Test good requests
|
||||
events = [event async for event in runnable.astream_events("foo", version="v1")]
|
||||
events = [event async for event in runnable.astream_events("foo", version="v2")]
|
||||
_clean_up_events(events)
|
||||
|
||||
assert events == [
|
||||
@@ -2572,7 +2754,7 @@ async def test_astream_events_with_serialization(
|
||||
app, raise_app_exceptions=False, path="/get_pets"
|
||||
) as runnable:
|
||||
# Test good requests
|
||||
events = [event async for event in runnable.astream_events("foo", version="v1")]
|
||||
events = [event async for event in runnable.astream_events("foo", version="v2")]
|
||||
_clean_up_events(events)
|
||||
assert events == [
|
||||
{
|
||||
@@ -2607,7 +2789,7 @@ async def test_astream_events_with_serialization(
|
||||
) as runnable:
|
||||
# Test good requests
|
||||
with pytest.raises(httpx.HTTPStatusError) as cb:
|
||||
async for event in runnable.astream_events("foo", version="v1"):
|
||||
async for event in runnable.astream_events("foo", version="v2"):
|
||||
pass
|
||||
assert cb.value.response.status_code == 500
|
||||
|
||||
@@ -2635,268 +2817,48 @@ async def test_astream_events_with_prompt_model_parser_chain(
|
||||
events = [
|
||||
event
|
||||
async for event in runnable.astream_events(
|
||||
{"question": "hello"}, version="v1"
|
||||
{"question": "hello"}, version="v2"
|
||||
)
|
||||
]
|
||||
_clean_up_events(events)
|
||||
assert recursive_dump(events) == [
|
||||
{
|
||||
"data": {"input": {"question": "hello"}},
|
||||
"event": "on_chain_start",
|
||||
"name": "RunnableSequence",
|
||||
"parent_ids": [],
|
||||
"tags": [],
|
||||
},
|
||||
{
|
||||
"data": {"input": {"question": "hello"}},
|
||||
"event": "on_prompt_start",
|
||||
"name": "ChatPromptTemplate",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:1"],
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"input": {"question": "hello"},
|
||||
"output": {
|
||||
"messages": [
|
||||
{
|
||||
"additional_kwargs": {},
|
||||
"content": "You are a cat.",
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"type": "system",
|
||||
},
|
||||
{
|
||||
"additional_kwargs": {},
|
||||
"content": "hello",
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"type": "human",
|
||||
},
|
||||
]
|
||||
},
|
||||
},
|
||||
"event": "on_prompt_end",
|
||||
"name": "ChatPromptTemplate",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:1"],
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"input": {
|
||||
"messages": [
|
||||
[
|
||||
{
|
||||
"additional_kwargs": {},
|
||||
"content": "You are a cat.",
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"type": "system",
|
||||
},
|
||||
{
|
||||
"additional_kwargs": {},
|
||||
"content": "hello",
|
||||
"example": False,
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"type": "human",
|
||||
},
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"event": "on_chat_model_start",
|
||||
"name": "GenericFakeChatModel",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:2"],
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"chunk": {
|
||||
"additional_kwargs": {},
|
||||
"content": "Hello",
|
||||
"example": False,
|
||||
"invalid_tool_calls": [],
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"tool_call_chunks": [],
|
||||
"tool_calls": [],
|
||||
"type": "AIMessageChunk",
|
||||
"usage_metadata": None,
|
||||
}
|
||||
},
|
||||
"event": "on_chat_model_stream",
|
||||
"name": "GenericFakeChatModel",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:2"],
|
||||
},
|
||||
{
|
||||
"data": {},
|
||||
"event": "on_parser_start",
|
||||
"name": "StrOutputParser",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:3"],
|
||||
},
|
||||
{
|
||||
"data": {"chunk": "Hello"},
|
||||
"event": "on_parser_stream",
|
||||
"name": "StrOutputParser",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:3"],
|
||||
},
|
||||
{
|
||||
"data": {"chunk": "Hello"},
|
||||
"event": "on_chain_stream",
|
||||
"name": "RunnableSequence",
|
||||
"parent_ids": [],
|
||||
"tags": [],
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"chunk": {
|
||||
"additional_kwargs": {},
|
||||
"content": " ",
|
||||
"example": False,
|
||||
"invalid_tool_calls": [],
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"tool_call_chunks": [],
|
||||
"tool_calls": [],
|
||||
"type": "AIMessageChunk",
|
||||
"usage_metadata": None,
|
||||
}
|
||||
},
|
||||
"event": "on_chat_model_stream",
|
||||
"name": "GenericFakeChatModel",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:2"],
|
||||
},
|
||||
{
|
||||
"data": {"chunk": " "},
|
||||
"event": "on_parser_stream",
|
||||
"name": "StrOutputParser",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:3"],
|
||||
},
|
||||
{
|
||||
"data": {"chunk": " "},
|
||||
"event": "on_chain_stream",
|
||||
"name": "RunnableSequence",
|
||||
"parent_ids": [],
|
||||
"tags": [],
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"chunk": {
|
||||
"additional_kwargs": {},
|
||||
"content": "World!",
|
||||
"example": False,
|
||||
"invalid_tool_calls": [],
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"tool_call_chunks": [],
|
||||
"tool_calls": [],
|
||||
"type": "AIMessageChunk",
|
||||
"usage_metadata": None,
|
||||
}
|
||||
},
|
||||
"event": "on_chat_model_stream",
|
||||
"name": "GenericFakeChatModel",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:2"],
|
||||
},
|
||||
{
|
||||
"data": {"chunk": "World!"},
|
||||
"event": "on_parser_stream",
|
||||
"name": "StrOutputParser",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:3"],
|
||||
},
|
||||
{
|
||||
"data": {"chunk": "World!"},
|
||||
"event": "on_chain_stream",
|
||||
"name": "RunnableSequence",
|
||||
"parent_ids": [],
|
||||
"tags": [],
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"input": {
|
||||
"messages": [
|
||||
[
|
||||
{
|
||||
"additional_kwargs": {},
|
||||
"content": "You are a cat.",
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"type": "system",
|
||||
},
|
||||
{
|
||||
"additional_kwargs": {},
|
||||
"content": "hello",
|
||||
"example": False,
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"type": "human",
|
||||
},
|
||||
]
|
||||
]
|
||||
},
|
||||
"output": {
|
||||
"generations": [
|
||||
[
|
||||
{
|
||||
"generation_info": None,
|
||||
"message": {
|
||||
"additional_kwargs": {},
|
||||
"content": "Hello World!",
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"type": "AIMessageChunk",
|
||||
},
|
||||
"text": "Hello World!",
|
||||
"type": "ChatGenerationChunk",
|
||||
}
|
||||
]
|
||||
],
|
||||
"llm_output": None,
|
||||
"run": None,
|
||||
},
|
||||
},
|
||||
"event": "on_chat_model_end",
|
||||
"name": "GenericFakeChatModel",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:2"],
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"input": {
|
||||
"additional_kwargs": {},
|
||||
"content": "Hello World!",
|
||||
"example": False,
|
||||
"invalid_tool_calls": [],
|
||||
"name": None,
|
||||
"response_metadata": {},
|
||||
"tool_call_chunks": [],
|
||||
"tool_calls": [],
|
||||
"type": "AIMessageChunk",
|
||||
"usage_metadata": None,
|
||||
},
|
||||
"output": "Hello World!",
|
||||
},
|
||||
"event": "on_parser_end",
|
||||
"name": "StrOutputParser",
|
||||
"parent_ids": [],
|
||||
"tags": ["seq:step:3"],
|
||||
},
|
||||
{
|
||||
"data": {"output": "Hello World!"},
|
||||
"event": "on_chain_end",
|
||||
"name": "RunnableSequence",
|
||||
"parent_ids": [],
|
||||
"tags": [],
|
||||
},
|
||||
dumped = recursive_dump(events)
|
||||
|
||||
# Verify event sequence by checking event types in order.
|
||||
# The exact serialization of messages varies across langchain-core
|
||||
# versions (e.g. `example` field, `chunk_position` field), so we
|
||||
# validate the structural sequence rather than exact dict equality.
|
||||
event_sequence = [(e["event"], e["name"]) for e in dumped]
|
||||
|
||||
# Core events that must be present in order
|
||||
expected_core_events = [
|
||||
("on_chain_start", "RunnableSequence"),
|
||||
("on_prompt_start", "ChatPromptTemplate"),
|
||||
("on_prompt_end", "ChatPromptTemplate"),
|
||||
("on_chat_model_start", "GenericFakeChatModel"),
|
||||
("on_chat_model_stream", "GenericFakeChatModel"),
|
||||
("on_parser_start", "StrOutputParser"),
|
||||
("on_parser_stream", "StrOutputParser"),
|
||||
("on_chain_stream", "RunnableSequence"),
|
||||
]
|
||||
for event_type, name in expected_core_events:
|
||||
assert (event_type, name) in event_sequence, (
|
||||
f"Missing event ({event_type}, {name})"
|
||||
)
|
||||
|
||||
# Verify terminal events
|
||||
assert event_sequence[-1] == ("on_chain_end", "RunnableSequence")
|
||||
|
||||
# Verify content chunks were streamed
|
||||
stream_chunks = [
|
||||
e["data"]["chunk"] for e in dumped if e["event"] == "on_chain_stream"
|
||||
]
|
||||
# Filter out empty final chunk if present (langchain-core 1.x)
|
||||
content_chunks = [c for c in stream_chunks if c != ""]
|
||||
assert content_chunks == ["Hello", " ", "World!"]
|
||||
|
||||
# Verify final output
|
||||
chain_end = [e for e in dumped if e["event"] == "on_chain_end"][-1]
|
||||
assert chain_end["data"]["output"] == "Hello World!"
|
||||
|
||||
|
||||
async def test_path_dependencies() -> None:
|
||||
@@ -2964,8 +2926,6 @@ async def test_path_dependencies() -> None:
|
||||
)
|
||||
|
||||
|
||||
# TODO(0.3): Fix in langchain-core and re-release for 0.3
|
||||
@pytest.mark.xfail(reason="Bug in AnyMessage in langchain-core.dev4")
|
||||
async def test_remote_configurable_remote_runnable() -> None:
|
||||
"""Test that a configurable a client runnable that's configurable works.
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Test utilities for streaming."""
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import uuid
|
||||
|
||||
@@ -174,7 +174,7 @@ async def test_invoke_request_with_runnables() -> None:
|
||||
assert request.config.tags == ["hello"]
|
||||
assert request.config.run_name == "run"
|
||||
assert isinstance(request.config.configurable, BaseModel)
|
||||
assert request.config.configurable.dict() == {
|
||||
assert request.config.configurable.model_dump() == {
|
||||
"template": "goodbye {name}",
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Fake Chat Model wrapper for testing purposes."""
|
||||
|
||||
import asyncio
|
||||
import re
|
||||
import time
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Tests for verifying that testing utility code works as expected."""
|
||||
|
||||
from itertools import cycle
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from uuid import UUID
|
||||
@@ -35,6 +36,18 @@ async def test_generic_fake_chat_model_ainvoke() -> None:
|
||||
assert response == _AnyIdAIMessage(content="hello")
|
||||
|
||||
|
||||
def _filter_final_empty_chunk(chunks: list) -> list:
|
||||
"""Filter out the final empty sentinel chunk emitted by langchain-core 1.x.
|
||||
|
||||
langchain-core 1.x emits an extra empty AIMessageChunk with
|
||||
chunk_position='last' at the end of streams. Strip it for backward-compat
|
||||
assertions.
|
||||
"""
|
||||
if chunks and chunks[-1].content == "" and not chunks[-1].additional_kwargs:
|
||||
return chunks[:-1]
|
||||
return chunks
|
||||
|
||||
|
||||
async def test_generic_fake_chat_model_stream() -> None:
|
||||
"""Test streaming."""
|
||||
infinite_cycle = cycle(
|
||||
@@ -43,14 +56,14 @@ async def test_generic_fake_chat_model_stream() -> None:
|
||||
]
|
||||
)
|
||||
model = GenericFakeChatModel(messages=infinite_cycle)
|
||||
chunks = [chunk async for chunk in model.astream("meow")]
|
||||
chunks = _filter_final_empty_chunk([chunk async for chunk in model.astream("meow")])
|
||||
assert chunks == [
|
||||
_AnyIdAIMessageChunk(content="hello"),
|
||||
_AnyIdAIMessageChunk(content=" "),
|
||||
_AnyIdAIMessageChunk(content="goodbye"),
|
||||
]
|
||||
|
||||
chunks = [chunk for chunk in model.stream("meow")]
|
||||
chunks = _filter_final_empty_chunk([chunk for chunk in model.stream("meow")])
|
||||
assert chunks == [
|
||||
_AnyIdAIMessageChunk(content="hello"),
|
||||
_AnyIdAIMessageChunk(content=" "),
|
||||
@@ -61,7 +74,7 @@ async def test_generic_fake_chat_model_stream() -> None:
|
||||
# Relying on insertion order of the additional kwargs dict
|
||||
message = AIMessage(content="", additional_kwargs={"foo": 42, "bar": 24}, id="1")
|
||||
model = GenericFakeChatModel(messages=cycle([message]))
|
||||
chunks = [chunk async for chunk in model.astream("meow")]
|
||||
chunks = _filter_final_empty_chunk([chunk async for chunk in model.astream("meow")])
|
||||
assert chunks == [
|
||||
_AnyIdAIMessageChunk(content="", additional_kwargs={"foo": 42}),
|
||||
_AnyIdAIMessageChunk(content="", additional_kwargs={"bar": 24}),
|
||||
@@ -78,7 +91,7 @@ async def test_generic_fake_chat_model_stream() -> None:
|
||||
},
|
||||
)
|
||||
model = GenericFakeChatModel(messages=cycle([message]))
|
||||
chunks = [chunk async for chunk in model.astream("meow")]
|
||||
chunks = _filter_final_empty_chunk([chunk async for chunk in model.astream("meow")])
|
||||
|
||||
assert chunks == [
|
||||
_AnyIdAIMessageChunk(
|
||||
@@ -130,7 +143,8 @@ async def test_generic_fake_chat_model_astream_log() -> None:
|
||||
log_patch async for log_patch in model.astream_log("meow", diff=False)
|
||||
]
|
||||
final = log_patches[-1]
|
||||
assert final.state["streamed_output"] == [
|
||||
streamed = _filter_final_empty_chunk(final.state["streamed_output"])
|
||||
assert streamed == [
|
||||
_AnyIdAIMessageChunk(content="hello"),
|
||||
_AnyIdAIMessageChunk(content=" "),
|
||||
_AnyIdAIMessageChunk(content="goodbye"),
|
||||
@@ -179,10 +193,14 @@ async def test_callback_handlers() -> None:
|
||||
model = GenericFakeChatModel(messages=infinite_cycle)
|
||||
tokens: List[str] = []
|
||||
# New model
|
||||
results = list(model.stream("meow", {"callbacks": [MyCustomAsyncHandler(tokens)]}))
|
||||
results = _filter_final_empty_chunk(
|
||||
list(model.stream("meow", {"callbacks": [MyCustomAsyncHandler(tokens)]}))
|
||||
)
|
||||
assert results == [
|
||||
_AnyIdAIMessageChunk(content="hello"),
|
||||
_AnyIdAIMessageChunk(content=" "),
|
||||
_AnyIdAIMessageChunk(content="goodbye"),
|
||||
]
|
||||
assert tokens == ["hello", " ", "goodbye"]
|
||||
# Filter empty token from final sentinel chunk if present
|
||||
content_tokens = [t for t in tokens if t]
|
||||
assert content_tokens == ["hello", " ", "goodbye"]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Dict, List
|
||||
from typing import Any, Dict, List, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from langchain_core.tracers import BaseTracer
|
||||
@@ -39,6 +39,34 @@ class FakeTracer(BaseTracer):
|
||||
}
|
||||
)
|
||||
|
||||
def _create_chain_run(
|
||||
self,
|
||||
serialized: Dict[str, Any],
|
||||
inputs: Dict[str, Any],
|
||||
run_id: UUID,
|
||||
tags: Optional[List[str]] = None,
|
||||
parent_run_id: Optional[UUID] = None,
|
||||
metadata: Optional[Dict[str, Any]] = None,
|
||||
run_type: Optional[str] = None,
|
||||
name: Optional[str] = None,
|
||||
**kwargs: Any,
|
||||
) -> Run:
|
||||
if name is None:
|
||||
# can't raise an exception from here, but can get a breakpoint
|
||||
# import pdb; pdb.set_trace()
|
||||
pass
|
||||
return super()._create_chain_run(
|
||||
serialized,
|
||||
inputs,
|
||||
run_id,
|
||||
tags,
|
||||
parent_run_id,
|
||||
metadata,
|
||||
run_type,
|
||||
name,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def _persist_run(self, run: Run) -> None:
|
||||
"""Persist a run."""
|
||||
self.runs.append(self._copy_run(run))
|
||||
|
||||
Reference in New Issue
Block a user