mirror of
https://github.com/hwchase17/langchain.git
synced 2026-04-20 05:04:50 +00:00
Compare commits
24 Commits
langchain-
...
langchain-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a2ff40fcc | ||
|
|
bf685c242f | ||
|
|
9998e55936 | ||
|
|
df78608741 | ||
|
|
c086410677 | ||
|
|
98175860ad | ||
|
|
7da0597ecb | ||
|
|
e264ccf484 | ||
|
|
4a05679fdb | ||
|
|
2ba8393182 | ||
|
|
01ab2918a2 | ||
|
|
7fcfe7c1f4 | ||
|
|
821196c4ee | ||
|
|
56c2a7f6d4 | ||
|
|
c113682328 | ||
|
|
df37c0d086 | ||
|
|
8964f8a710 | ||
|
|
b81fbc962c | ||
|
|
152427eca1 | ||
|
|
0535d72927 | ||
|
|
9be6b5a20f | ||
|
|
d5b4b7e05c | ||
|
|
3c3d3e9579 | ||
|
|
174e7d2ab2 |
5
.github/scripts/check_diff.py
vendored
5
.github/scripts/check_diff.py
vendored
@@ -95,6 +95,11 @@ def _get_configs_for_single_dir(job: str, dir_: str) -> List[Dict[str, str]]:
|
||||
# declare deps in funny way
|
||||
max_python = "3.11"
|
||||
|
||||
if dir_ in ["libs/community", "libs/langchain"] and job == "extended-tests":
|
||||
# community extended test resolution in 3.12 is slow
|
||||
# even in uv
|
||||
max_python = "3.11"
|
||||
|
||||
return [
|
||||
{"working-directory": dir_, "python-version": min_python},
|
||||
{"working-directory": dir_, "python-version": max_python},
|
||||
|
||||
18
docs/docs/integrations/platforms/aws.mdx
Normal file → Executable file
18
docs/docs/integrations/platforms/aws.mdx
Normal file → Executable file
@@ -197,6 +197,24 @@ See a [usage example](/docs/integrations/vectorstores/documentdb).
|
||||
```python
|
||||
from langchain.vectorstores import DocumentDBVectorSearch
|
||||
```
|
||||
### Amazon MemoryDB
|
||||
[Amazon MemoryDB](https://aws.amazon.com/memorydb/) is a durable, in-memory database service that delivers ultra-fast performance. MemoryDB is compatible with Redis OSS, a popular open source data store,
|
||||
enabling you to quickly build applications using the same flexible and friendly Redis OSS APIs, and commands that they already use today.
|
||||
|
||||
InMemoryVectorStore class provides a vectorstore to connect with Amazon MemoryDB.
|
||||
|
||||
```python
|
||||
from langchain_aws.vectorstores.inmemorydb import InMemoryVectorStore
|
||||
|
||||
vds = InMemoryVectorStore.from_documents(
|
||||
chunks,
|
||||
embeddings,
|
||||
redis_url="rediss://cluster_endpoint:6379/ssl=True ssl_cert_reqs=none",
|
||||
vector_schema=vector_schema,
|
||||
index_name=INDEX_NAME,
|
||||
)
|
||||
```
|
||||
See a [usage example](/docs/integrations/vectorstores/memorydb).
|
||||
|
||||
## Retrievers
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@
|
||||
"id": "859daaee-ac5d-47f8-8704-827f5578bf1b",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Define a metic\n",
|
||||
"## Define a metric\n",
|
||||
"\n",
|
||||
"We now need to define a metric. This will be used to determine which runs were successful and we can learn from. Here we will use DSPy's metrics, though you can write your own."
|
||||
]
|
||||
|
||||
537
docs/docs/integrations/vectorstores/memorydb.ipynb
Normal file
537
docs/docs/integrations/vectorstores/memorydb.ipynb
Normal file
@@ -0,0 +1,537 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Amazon MemoryDB\n",
|
||||
"\n",
|
||||
">[Vector Search](https://docs.aws.amazon.com/memorydb/latest/devguide/vector-search.html/) introduction and langchain integration guide.\n",
|
||||
"\n",
|
||||
"## What is Amazon MemoryDB?\n",
|
||||
"\n",
|
||||
"MemoryDB is compatible with Redis OSS, a popular open source data store, enabling you to quickly build applications using the same flexible and friendly Redis OSS data structures, APIs, and commands that they already use today. With MemoryDB, all of your data is stored in memory, which enables you to achieve microsecond read and single-digit millisecond write latency and high throughput. MemoryDB also stores data durably across multiple Availability Zones (AZs) using a Multi-AZ transactional log to enable fast failover, database recovery, and node restarts.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"## Vector search for MemoryDB \n",
|
||||
"\n",
|
||||
"Vector search for MemoryDB extends the functionality of MemoryDB. Vector search can be used in conjunction with existing MemoryDB functionality. Applications that do not use vector search are unaffected by its presence. Vector search is available in all Regions that MemoryDB is available. You can use your existing MemoryDB data or Redis OSS API to build machine learning and generative AI use cases, such as retrieval-augmented generation, anomaly detection, document retrieval, and real-time recommendations.\n",
|
||||
"\n",
|
||||
"* Indexing of multiple fields in Redis hashes and `JSON`\n",
|
||||
"* Vector similarity search (with `HNSW` (ANN) or `FLAT` (KNN))\n",
|
||||
"* Vector Range Search (e.g. find all vectors within a radius of a query vector)\n",
|
||||
"* Incremental indexing without performance loss\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Setting up\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"### Install Redis Python client\n",
|
||||
"\n",
|
||||
"`Redis-py` is a python client that can be used to connect to MemoryDB"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%pip install --upgrade --quiet redis langchain-aws"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain_aws.embeddings import BedrockEmbeddings\n",
|
||||
"\n",
|
||||
"embeddings = BedrockEmbeddings()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### MemoryDB Connection\n",
|
||||
"\n",
|
||||
"Valid Redis Url schemas are:\n",
|
||||
"1. `redis://` - Connection to Redis cluster, unencrypted\n",
|
||||
"2. `rediss://` - Connection to Redis cluster, with TLS encryption\n",
|
||||
"\n",
|
||||
"More information about additional connection parameters can be found in the [redis-py documentation](https://redis-py.readthedocs.io/en/stable/connections.html)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Sample data\n",
|
||||
"\n",
|
||||
"First we will describe some sample data so that the various attributes of the Redis vector store can be demonstrated."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"metadata = [\n",
|
||||
" {\n",
|
||||
" \"user\": \"john\",\n",
|
||||
" \"age\": 18,\n",
|
||||
" \"job\": \"engineer\",\n",
|
||||
" \"credit_score\": \"high\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"user\": \"derrick\",\n",
|
||||
" \"age\": 45,\n",
|
||||
" \"job\": \"doctor\",\n",
|
||||
" \"credit_score\": \"low\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"user\": \"nancy\",\n",
|
||||
" \"age\": 94,\n",
|
||||
" \"job\": \"doctor\",\n",
|
||||
" \"credit_score\": \"high\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"user\": \"tyler\",\n",
|
||||
" \"age\": 100,\n",
|
||||
" \"job\": \"engineer\",\n",
|
||||
" \"credit_score\": \"high\",\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"user\": \"joe\",\n",
|
||||
" \"age\": 35,\n",
|
||||
" \"job\": \"dentist\",\n",
|
||||
" \"credit_score\": \"medium\",\n",
|
||||
" },\n",
|
||||
"]\n",
|
||||
"texts = [\"foo\", \"foo\", \"foo\", \"bar\", \"bar\"]\n",
|
||||
"index_name = \"users\""
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Create MemoryDB vector store\n",
|
||||
"\n",
|
||||
"The InMemoryVectorStore instance can be initialized using the below methods \n",
|
||||
"- ``InMemoryVectorStore.__init__`` - Initialize directly\n",
|
||||
"- ``InMemoryVectorStore.from_documents`` - Initialize from a list of ``Langchain.docstore.Document`` objects\n",
|
||||
"- ``InMemoryVectorStore.from_texts`` - Initialize from a list of texts (optionally with metadata)\n",
|
||||
"- ``InMemoryVectorStore.from_existing_index`` - Initialize from an existing MemoryDB index\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 7,
|
||||
"metadata": {
|
||||
"tags": []
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from langchain_aws.vectorstores.inmemorydb import InMemoryVectorStore\n",
|
||||
"\n",
|
||||
"vds = InMemoryVectorStore.from_texts(\n",
|
||||
" embeddings,\n",
|
||||
" redis_url=\"rediss://cluster_endpoint:6379/ssl=True ssl_cert_reqs=none\",\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'users'"
|
||||
]
|
||||
},
|
||||
"execution_count": 6,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"vds.index_name"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Querying\n",
|
||||
"\n",
|
||||
"There are multiple ways to query the ``InMemoryVectorStore`` implementation based on what use case you have:\n",
|
||||
"\n",
|
||||
"- ``similarity_search``: Find the most similar vectors to a given vector.\n",
|
||||
"- ``similarity_search_with_score``: Find the most similar vectors to a given vector and return the vector distance\n",
|
||||
"- ``similarity_search_limit_score``: Find the most similar vectors to a given vector and limit the number of results to the ``score_threshold``\n",
|
||||
"- ``similarity_search_with_relevance_scores``: Find the most similar vectors to a given vector and return the vector similarities\n",
|
||||
"- ``max_marginal_relevance_search``: Find the most similar vectors to a given vector while also optimizing for diversity"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 10,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"foo\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"results = vds.similarity_search(\"foo\")\n",
|
||||
"print(results[0].page_content)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Content: foo --- Score: 0.0\n",
|
||||
"Content: foo --- Score: 0.0\n",
|
||||
"Content: foo --- Score: 0.0\n",
|
||||
"Content: bar --- Score: 0.1566\n",
|
||||
"Content: bar --- Score: 0.1566\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# with scores (distances)\n",
|
||||
"results = vds.similarity_search_with_score(\"foo\", k=5)\n",
|
||||
"for result in results:\n",
|
||||
" print(f\"Content: {result[0].page_content} --- Score: {result[1]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Content: foo --- Score: 0.0\n",
|
||||
"Content: foo --- Score: 0.0\n",
|
||||
"Content: foo --- Score: 0.0\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# limit the vector distance that can be returned\n",
|
||||
"results = vds.similarity_search_with_score(\"foo\", k=5, distance_threshold=0.1)\n",
|
||||
"for result in results:\n",
|
||||
" print(f\"Content: {result[0].page_content} --- Score: {result[1]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 14,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Content: foo --- Similiarity: 1.0\n",
|
||||
"Content: foo --- Similiarity: 1.0\n",
|
||||
"Content: foo --- Similiarity: 1.0\n",
|
||||
"Content: bar --- Similiarity: 0.8434\n",
|
||||
"Content: bar --- Similiarity: 0.8434\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# with scores\n",
|
||||
"results = vds.similarity_search_with_relevance_scores(\"foo\", k=5)\n",
|
||||
"for result in results:\n",
|
||||
" print(f\"Content: {result[0].page_content} --- Similiarity: {result[1]}\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['doc:users:b9c71d62a0a34241a37950b448dafd38']"
|
||||
]
|
||||
},
|
||||
"execution_count": 16,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# you can also add new documents as follows\n",
|
||||
"new_document = [\"baz\"]\n",
|
||||
"new_metadata = [{\"user\": \"sam\", \"age\": 50, \"job\": \"janitor\", \"credit_score\": \"high\"}]\n",
|
||||
"# both the document and metadata must be lists\n",
|
||||
"vds.add_texts(new_document, new_metadata)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## MemoryDB as Retriever\n",
|
||||
"\n",
|
||||
"Here we go over different options for using the vector store as a retriever.\n",
|
||||
"\n",
|
||||
"There are three different search methods we can use to do retrieval. By default, it will use semantic similarity."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Content: foo --- Score: 0.0\n",
|
||||
"Content: foo --- Score: 0.0\n",
|
||||
"Content: foo --- Score: 0.0\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"query = \"foo\"\n",
|
||||
"results = vds.similarity_search_with_score(query, k=3, return_metadata=True)\n",
|
||||
"\n",
|
||||
"for result in results:\n",
|
||||
" print(\"Content:\", result[0].page_content, \" --- Score: \", result[1])"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 27,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"retriever = vds.as_retriever(search_type=\"similarity\", search_kwargs={\"k\": 4})"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Document(page_content='foo', metadata={'id': 'doc:users_modified:988ecca7574048e396756efc0e79aeca', 'user': 'john', 'job': 'engineer', 'credit_score': 'high', 'age': '18'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users_modified:009b1afeb4084cc6bdef858c7a99b48e', 'user': 'derrick', 'job': 'doctor', 'credit_score': 'low', 'age': '45'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users_modified:7087cee9be5b4eca93c30fbdd09a2731', 'user': 'nancy', 'job': 'doctor', 'credit_score': 'high', 'age': '94'}),\n",
|
||||
" Document(page_content='bar', metadata={'id': 'doc:users_modified:01ef6caac12b42c28ad870aefe574253', 'user': 'tyler', 'job': 'engineer', 'credit_score': 'high', 'age': '100'})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"docs = retriever.invoke(query)\n",
|
||||
"docs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"There is also the `similarity_distance_threshold` retriever which allows the user to specify the vector distance"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"retriever = vds.as_retriever(\n",
|
||||
" search_type=\"similarity_distance_threshold\",\n",
|
||||
" search_kwargs={\"k\": 4, \"distance_threshold\": 0.1},\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Document(page_content='foo', metadata={'id': 'doc:users_modified:988ecca7574048e396756efc0e79aeca', 'user': 'john', 'job': 'engineer', 'credit_score': 'high', 'age': '18'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users_modified:009b1afeb4084cc6bdef858c7a99b48e', 'user': 'derrick', 'job': 'doctor', 'credit_score': 'low', 'age': '45'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users_modified:7087cee9be5b4eca93c30fbdd09a2731', 'user': 'nancy', 'job': 'doctor', 'credit_score': 'high', 'age': '94'})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"docs = retriever.invoke(query)\n",
|
||||
"docs"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"Lastly, the ``similarity_score_threshold`` allows the user to define the minimum score for similar documents"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"retriever = vds.as_retriever(\n",
|
||||
" search_type=\"similarity_score_threshold\",\n",
|
||||
" search_kwargs={\"score_threshold\": 0.9, \"k\": 10},\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Document(page_content='foo', metadata={'id': 'doc:users_modified:988ecca7574048e396756efc0e79aeca', 'user': 'john', 'job': 'engineer', 'credit_score': 'high', 'age': '18'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users_modified:009b1afeb4084cc6bdef858c7a99b48e', 'user': 'derrick', 'job': 'doctor', 'credit_score': 'low', 'age': '45'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users_modified:7087cee9be5b4eca93c30fbdd09a2731', 'user': 'nancy', 'job': 'doctor', 'credit_score': 'high', 'age': '94'})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 32,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"retriever.invoke(\"foo\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"[Document(page_content='foo', metadata={'id': 'doc:users:8f6b673b390647809d510112cde01a27', 'user': 'john', 'job': 'engineer', 'credit_score': 'high', 'age': '18'}),\n",
|
||||
" Document(page_content='bar', metadata={'id': 'doc:users:93521560735d42328b48c9c6f6418d6a', 'user': 'tyler', 'job': 'engineer', 'credit_score': 'high', 'age': '100'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users:125ecd39d07845eabf1a699d44134a5b', 'user': 'nancy', 'job': 'doctor', 'credit_score': 'high', 'age': '94'}),\n",
|
||||
" Document(page_content='foo', metadata={'id': 'doc:users:d6200ab3764c466082fde3eaab972a2a', 'user': 'derrick', 'job': 'doctor', 'credit_score': 'low', 'age': '45'})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"retriever.invoke(\"foo\")"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"## Delete index"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To delete your entries you have to address them by their keys."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"True"
|
||||
]
|
||||
},
|
||||
"execution_count": 34,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# delete the indices too\n",
|
||||
"InMemoryVectorStore.drop_index(\n",
|
||||
" index_name=\"users\", delete_documents=True, redis_url=\"redis://localhost:6379\"\n",
|
||||
")\n",
|
||||
"InMemoryVectorStore.drop_index(\n",
|
||||
" index_name=\"users_modified\",\n",
|
||||
" delete_documents=True,\n",
|
||||
" redis_url=\"redis://localhost:6379\",\n",
|
||||
")"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.10.12"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 4
|
||||
}
|
||||
@@ -207,7 +207,7 @@ class ChatDeepInfra(BaseChatModel):
|
||||
request_timeout: Optional[float] = Field(default=None, alias="timeout")
|
||||
temperature: Optional[float] = 1
|
||||
model_kwargs: Dict[str, Any] = Field(default_factory=dict)
|
||||
"""Run inference with this temperature. Must by in the closed
|
||||
"""Run inference with this temperature. Must be in the closed
|
||||
interval [0.0, 1.0]."""
|
||||
top_p: Optional[float] = None
|
||||
"""Decode using nucleus sampling: consider the smallest set of tokens whose
|
||||
|
||||
@@ -236,7 +236,7 @@ class ChatGooglePalm(BaseChatModel, BaseModel):
|
||||
"""Model name to use."""
|
||||
google_api_key: Optional[SecretStr] = None
|
||||
temperature: Optional[float] = None
|
||||
"""Run inference with this temperature. Must by in the closed
|
||||
"""Run inference with this temperature. Must be in the closed
|
||||
interval [0.0, 1.0]."""
|
||||
top_p: Optional[float] = None
|
||||
"""Decode using nucleus sampling: consider the smallest set of tokens whose
|
||||
|
||||
@@ -190,7 +190,7 @@ class ChatLiteLLM(BaseChatModel):
|
||||
request_timeout: Optional[Union[float, Tuple[float, float]]] = None
|
||||
temperature: Optional[float] = 1
|
||||
model_kwargs: Dict[str, Any] = Field(default_factory=dict)
|
||||
"""Run inference with this temperature. Must by in the closed
|
||||
"""Run inference with this temperature. Must be in the closed
|
||||
interval [0.0, 1.0]."""
|
||||
top_p: Optional[float] = None
|
||||
"""Decode using nucleus sampling: consider the smallest set of tokens whose
|
||||
|
||||
@@ -17,6 +17,7 @@ class FireCrawlLoader(BaseLoader):
|
||||
url: str,
|
||||
*,
|
||||
api_key: Optional[str] = None,
|
||||
api_url: Optional[str] = None,
|
||||
mode: Literal["crawl", "scrape"] = "crawl",
|
||||
params: Optional[dict] = None,
|
||||
):
|
||||
@@ -26,6 +27,8 @@ class FireCrawlLoader(BaseLoader):
|
||||
url: The url to be crawled.
|
||||
api_key: The Firecrawl API key. If not specified will be read from env var
|
||||
FIRECRAWL_API_KEY. Get an API key
|
||||
api_url: The Firecrawl API URL. If not specified will be read from env var
|
||||
FIRECRAWL_API_URL or defaults to https://api.firecrawl.dev.
|
||||
mode: The mode to run the loader in. Default is "crawl".
|
||||
Options include "scrape" (single url) and
|
||||
"crawl" (all accessible sub pages).
|
||||
@@ -45,7 +48,7 @@ class FireCrawlLoader(BaseLoader):
|
||||
f"Unrecognized mode '{mode}'. Expected one of 'crawl', 'scrape'."
|
||||
)
|
||||
api_key = api_key or get_from_env("api_key", "FIRECRAWL_API_KEY")
|
||||
self.firecrawl = FirecrawlApp(api_key=api_key)
|
||||
self.firecrawl = FirecrawlApp(api_key=api_key, api_url=api_url)
|
||||
self.url = url
|
||||
self.mode = mode
|
||||
self.params = params
|
||||
|
||||
@@ -11,12 +11,45 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class QianfanEmbeddingsEndpoint(BaseModel, Embeddings):
|
||||
"""`Baidu Qianfan Embeddings` embedding models."""
|
||||
"""Baidu Qianfan Embeddings embedding models.
|
||||
|
||||
qianfan_ak: Optional[SecretStr] = None
|
||||
Setup:
|
||||
To use, you should have the ``qianfan`` python package installed, and set
|
||||
environment variables ``QIANFAN_AK``, ``QIANFAN_SK``.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install qianfan
|
||||
export QIANFAN_AK="your-api-key"
|
||||
export QIANFAN_SK="your-secret_key"
|
||||
|
||||
Instantiate:
|
||||
.. code-block:: python
|
||||
|
||||
from langchain_community.embeddings import QianfanEmbeddingsEndpoint
|
||||
|
||||
embeddings = QianfanEmbeddingsEndpoint()
|
||||
|
||||
Embed:
|
||||
.. code-block:: python
|
||||
|
||||
# embed the documents
|
||||
vectors = embeddings.embed_documents([text1, text2, ...])
|
||||
|
||||
# embed the query
|
||||
vectors = embeddings.embed_query(text)
|
||||
|
||||
# embed the documents with async
|
||||
vectors = await embeddings.aembed_documents([text1, text2, ...])
|
||||
|
||||
# embed the query with async
|
||||
vectors = await embeddings.aembed_query(text)
|
||||
""" # noqa: E501
|
||||
|
||||
qianfan_ak: Optional[SecretStr] = Field(default=None, alias="api_key")
|
||||
"""Qianfan application apikey"""
|
||||
|
||||
qianfan_sk: Optional[SecretStr] = None
|
||||
qianfan_sk: Optional[SecretStr] = Field(default=None, alias="secret_key")
|
||||
"""Qianfan application secretkey"""
|
||||
|
||||
chunk_size: int = 16
|
||||
|
||||
@@ -72,7 +72,7 @@ class GooglePalm(BaseLLM, BaseModel):
|
||||
model_name: str = "models/text-bison-001"
|
||||
"""Model name to use."""
|
||||
temperature: float = 0.7
|
||||
"""Run inference with this temperature. Must by in the closed interval
|
||||
"""Run inference with this temperature. Must be in the closed interval
|
||||
[0.0, 1.0]."""
|
||||
top_p: Optional[float] = None
|
||||
"""Decode using nucleus sampling: consider the smallest set of tokens whose
|
||||
|
||||
@@ -327,6 +327,10 @@ class DocumentDBVectorSearch(VectorStore):
|
||||
Returns:
|
||||
A list of documents closest to the query vector
|
||||
"""
|
||||
# $match can't be null, so intializes to {} when None to avoid
|
||||
# "the match filter must be an expression in an object"
|
||||
if not filter:
|
||||
filter = {}
|
||||
pipeline: List[dict[str, Any]] = [
|
||||
{"$match": filter},
|
||||
{
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
"""Test Baidu Qianfan Embedding Endpoint."""
|
||||
|
||||
from typing import cast
|
||||
|
||||
from langchain_core.pydantic_v1 import SecretStr
|
||||
|
||||
from langchain_community.embeddings.baidu_qianfan_endpoint import (
|
||||
QianfanEmbeddingsEndpoint,
|
||||
)
|
||||
@@ -38,3 +42,17 @@ def test_rate_limit() -> None:
|
||||
assert len(output) == 2
|
||||
assert len(output[0]) == 384
|
||||
assert len(output[1]) == 384
|
||||
|
||||
|
||||
def test_initialization_with_alias() -> None:
|
||||
"""Test qianfan embedding model initialization with alias."""
|
||||
api_key = "your-api-key"
|
||||
secret_key = "your-secret-key"
|
||||
|
||||
embeddings = QianfanEmbeddingsEndpoint( # type: ignore[arg-type, call-arg]
|
||||
api_key=api_key, # type: ignore[arg-type]
|
||||
secret_key=secret_key, # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
assert cast(SecretStr, embeddings.qianfan_ak).get_secret_value() == api_key
|
||||
assert cast(SecretStr, embeddings.qianfan_sk).get_secret_value() == secret_key
|
||||
|
||||
@@ -230,7 +230,7 @@ class MessagesPlaceholder(BaseMessagePromptTemplate):
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(
|
||||
f"variable {self.variable_name} should be a list of base messages, "
|
||||
f"got {value}"
|
||||
f"got {value} of type {type(value)}"
|
||||
)
|
||||
value = convert_to_messages(value)
|
||||
if self.n_messages:
|
||||
|
||||
@@ -105,23 +105,31 @@ class InMemoryRateLimiter(BaseRateLimiter):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from langchain_core import InMemoryRateLimiter
|
||||
import time
|
||||
|
||||
from langchain_core.runnables import RunnableLambda, InMemoryRateLimiter
|
||||
from langchain_core.rate_limiters import InMemoryRateLimiter
|
||||
|
||||
rate_limiter = InMemoryRateLimiter(
|
||||
requests_per_second=100, check_every_n_seconds=0.1, max_bucket_size=10
|
||||
requests_per_second=0.1, # <-- Can only make a request once every 10 seconds!!
|
||||
check_every_n_seconds=0.1, # Wake up every 100 ms to check whether allowed to make a request,
|
||||
max_bucket_size=10, # Controls the maximum burst size.
|
||||
)
|
||||
|
||||
def foo(x: int) -> int:
|
||||
return x
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
model = ChatAnthropic(
|
||||
model_name="claude-3-opus-20240229",
|
||||
rate_limiter=rate_limiter
|
||||
)
|
||||
|
||||
for _ in range(5):
|
||||
tic = time.time()
|
||||
model.invoke("hello")
|
||||
toc = time.time()
|
||||
print(toc - tic)
|
||||
|
||||
foo_ = RunnableLambda(foo)
|
||||
chain = rate_limiter | foo_
|
||||
assert chain.invoke(1) == 1
|
||||
|
||||
.. versionadded:: 0.2.24
|
||||
"""
|
||||
""" # noqa: E501
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
@@ -20,7 +20,6 @@ tool for the job.
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import copy
|
||||
import functools
|
||||
import inspect
|
||||
import json
|
||||
@@ -120,6 +119,7 @@ def _get_filtered_args(
|
||||
func: Callable,
|
||||
*,
|
||||
filter_args: Sequence[str],
|
||||
include_injected: bool = True,
|
||||
) -> dict:
|
||||
"""Get the arguments from a function's signature."""
|
||||
schema = inferred_model.schema()["properties"]
|
||||
@@ -127,7 +127,9 @@ def _get_filtered_args(
|
||||
return {
|
||||
k: schema[k]
|
||||
for i, (k, param) in enumerate(valid_keys.items())
|
||||
if k not in filter_args and (i > 0 or param.name not in ("self", "cls"))
|
||||
if k not in filter_args
|
||||
and (i > 0 or param.name not in ("self", "cls"))
|
||||
and (include_injected or not _is_injected_arg_type(param.annotation))
|
||||
}
|
||||
|
||||
|
||||
@@ -247,6 +249,7 @@ def create_schema_from_function(
|
||||
filter_args: Optional[Sequence[str]] = None,
|
||||
parse_docstring: bool = False,
|
||||
error_on_invalid_docstring: bool = False,
|
||||
include_injected: bool = True,
|
||||
) -> Type[BaseModel]:
|
||||
"""Create a pydantic schema from a function's signature.
|
||||
|
||||
@@ -260,6 +263,9 @@ def create_schema_from_function(
|
||||
error_on_invalid_docstring: if ``parse_docstring`` is provided, configure
|
||||
whether to raise ValueError on invalid Google Style docstrings.
|
||||
Defaults to False.
|
||||
include_injected: Whether to include injected arguments in the schema.
|
||||
Defaults to True, since we want to include them in the schema
|
||||
when *validating* tool inputs.
|
||||
|
||||
Returns:
|
||||
A pydantic model with the same arguments as the function.
|
||||
@@ -277,7 +283,9 @@ def create_schema_from_function(
|
||||
error_on_invalid_docstring=error_on_invalid_docstring,
|
||||
)
|
||||
# Pydantic adds placeholder virtual fields we need to strip
|
||||
valid_properties = _get_filtered_args(inferred_model, func, filter_args=filter_args)
|
||||
valid_properties = _get_filtered_args(
|
||||
inferred_model, func, filter_args=filter_args, include_injected=include_injected
|
||||
)
|
||||
return _create_subset_model(
|
||||
f"{model_name}Schema",
|
||||
inferred_model,
|
||||
@@ -1482,9 +1490,8 @@ def _prep_run_args(
|
||||
) -> Tuple[Union[str, Dict], Dict]:
|
||||
config = ensure_config(config)
|
||||
if _is_tool_call(input):
|
||||
input_copy = copy.deepcopy(input)
|
||||
tool_call_id: Optional[str] = cast(ToolCall, input_copy)["id"]
|
||||
tool_input: Union[str, dict] = cast(ToolCall, input_copy)["args"]
|
||||
tool_call_id: Optional[str] = cast(ToolCall, input)["id"]
|
||||
tool_input: Union[str, dict] = cast(ToolCall, input)["args"].copy()
|
||||
else:
|
||||
tool_call_id = None
|
||||
tool_input = cast(Union[str, dict], input)
|
||||
|
||||
@@ -179,6 +179,7 @@ def convert_python_function_to_openai_function(
|
||||
filter_args=(),
|
||||
parse_docstring=True,
|
||||
error_on_invalid_docstring=False,
|
||||
include_injected=False,
|
||||
)
|
||||
return convert_pydantic_to_openai_function(
|
||||
model,
|
||||
|
||||
270
libs/core/poetry.lock
generated
270
libs/core/poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "annotated-types"
|
||||
@@ -660,13 +660,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "8.0.0"
|
||||
version = "8.2.0"
|
||||
description = "Read metadata from Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"},
|
||||
{file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"},
|
||||
{file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"},
|
||||
{file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1233,13 +1233,13 @@ url = "../text-splitters"
|
||||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
version = "0.1.92"
|
||||
version = "0.1.93"
|
||||
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
|
||||
optional = false
|
||||
python-versions = "<4.0,>=3.8.1"
|
||||
files = [
|
||||
{file = "langsmith-0.1.92-py3-none-any.whl", hash = "sha256:8acb27844ff5263bde14b23425f83ee63996f4d5a8e9998cdeef07fd913137ff"},
|
||||
{file = "langsmith-0.1.92.tar.gz", hash = "sha256:681a613a4dc8c8e57c8961c347a39ffcb64d6c697e8ddde1fd8458fcfaef6c13"},
|
||||
{file = "langsmith-0.1.93-py3-none-any.whl", hash = "sha256:811210b9d5f108f36431bd7b997eb9476a9ecf5a2abd7ddbb606c1cdcf0f43ce"},
|
||||
{file = "langsmith-0.1.93.tar.gz", hash = "sha256:285b6ad3a54f50fa8eb97b5f600acc57d0e37e139dd8cf2111a117d0435ba9b4"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1861,13 +1861,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pure-eval"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
description = "Safely evaluate AST nodes without side effects"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "pure_eval-0.2.2-py3-none-any.whl", hash = "sha256:01eaab343580944bc56080ebe0a674b39ec44a945e6d09ba7db3cb8cec289350"},
|
||||
{file = "pure_eval-0.2.2.tar.gz", hash = "sha256:2b45320af6dfaa1750f543d714b6d1c520a1688dec6fd24d339063ce0aaa9ac3"},
|
||||
{file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"},
|
||||
{file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@@ -2484,137 +2484,141 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "rpds-py"
|
||||
version = "0.19.0"
|
||||
version = "0.19.1"
|
||||
description = "Python bindings to Rust's persistent data structures (rpds)"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:fb37bd599f031f1a6fb9e58ec62864ccf3ad549cf14bac527dbfa97123edcca4"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3384d278df99ec2c6acf701d067147320b864ef6727405d6470838476e44d9e8"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e54548e0be3ac117595408fd4ca0ac9278fde89829b0b518be92863b17ff67a2"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8eb488ef928cdbc05a27245e52de73c0d7c72a34240ef4d9893fdf65a8c1a955"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a5da93debdfe27b2bfc69eefb592e1831d957b9535e0943a0ee8b97996de21b5"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:79e205c70afddd41f6ee79a8656aec738492a550247a7af697d5bd1aee14f766"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:959179efb3e4a27610e8d54d667c02a9feaa86bbabaf63efa7faa4dfa780d4f1"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a6e605bb9edcf010f54f8b6a590dd23a4b40a8cb141255eec2a03db249bc915b"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9133d75dc119a61d1a0ded38fb9ba40a00ef41697cc07adb6ae098c875195a3f"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd36b712d35e757e28bf2f40a71e8f8a2d43c8b026d881aa0c617b450d6865c9"},
|
||||
{file = "rpds_py-0.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:354f3a91718489912f2e0fc331c24eaaf6a4565c080e00fbedb6015857c00582"},
|
||||
{file = "rpds_py-0.19.0-cp310-none-win32.whl", hash = "sha256:ebcbf356bf5c51afc3290e491d3722b26aaf5b6af3c1c7f6a1b757828a46e336"},
|
||||
{file = "rpds_py-0.19.0-cp310-none-win_amd64.whl", hash = "sha256:75a6076289b2df6c8ecb9d13ff79ae0cad1d5fb40af377a5021016d58cd691ec"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6d45080095e585f8c5097897313def60caa2046da202cdb17a01f147fb263b81"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5c9581019c96f865483d031691a5ff1cc455feb4d84fc6920a5ffc48a794d8a"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1540d807364c84516417115c38f0119dfec5ea5c0dd9a25332dea60b1d26fc4d"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9e65489222b410f79711dc3d2d5003d2757e30874096b2008d50329ea4d0f88c"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9da6f400eeb8c36f72ef6646ea530d6d175a4f77ff2ed8dfd6352842274c1d8b"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:37f46bb11858717e0efa7893c0f7055c43b44c103e40e69442db5061cb26ed34"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:071d4adc734de562bd11d43bd134330fb6249769b2f66b9310dab7460f4bf714"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9625367c8955e4319049113ea4f8fee0c6c1145192d57946c6ffcd8fe8bf48dd"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e19509145275d46bc4d1e16af0b57a12d227c8253655a46bbd5ec317e941279d"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d438e4c020d8c39961deaf58f6913b1bf8832d9b6f62ec35bd93e97807e9cbc"},
|
||||
{file = "rpds_py-0.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:90bf55d9d139e5d127193170f38c584ed3c79e16638890d2e36f23aa1630b952"},
|
||||
{file = "rpds_py-0.19.0-cp311-none-win32.whl", hash = "sha256:8d6ad132b1bc13d05ffe5b85e7a01a3998bf3a6302ba594b28d61b8c2cf13aaf"},
|
||||
{file = "rpds_py-0.19.0-cp311-none-win_amd64.whl", hash = "sha256:7ec72df7354e6b7f6eb2a17fa6901350018c3a9ad78e48d7b2b54d0412539a67"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:5095a7c838a8647c32aa37c3a460d2c48debff7fc26e1136aee60100a8cd8f68"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f2f78ef14077e08856e788fa482107aa602636c16c25bdf59c22ea525a785e9"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b7cc6cb44f8636fbf4a934ca72f3e786ba3c9f9ba4f4d74611e7da80684e48d2"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf902878b4af334a09de7a45badbff0389e7cf8dc2e4dcf5f07125d0b7c2656d"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:688aa6b8aa724db1596514751ffb767766e02e5c4a87486ab36b8e1ebc1aedac"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57dbc9167d48e355e2569346b5aa4077f29bf86389c924df25c0a8b9124461fb"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4cf5a9497874822341c2ebe0d5850fed392034caadc0bad134ab6822c0925b"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8a790d235b9d39c70a466200d506bb33a98e2ee374a9b4eec7a8ac64c2c261fa"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1d16089dfa58719c98a1c06f2daceba6d8e3fb9b5d7931af4a990a3c486241cb"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bc9128e74fe94650367fe23f37074f121b9f796cabbd2f928f13e9661837296d"},
|
||||
{file = "rpds_py-0.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c8f77e661ffd96ff104bebf7d0f3255b02aa5d5b28326f5408d6284c4a8b3248"},
|
||||
{file = "rpds_py-0.19.0-cp312-none-win32.whl", hash = "sha256:5f83689a38e76969327e9b682be5521d87a0c9e5a2e187d2bc6be4765f0d4600"},
|
||||
{file = "rpds_py-0.19.0-cp312-none-win_amd64.whl", hash = "sha256:06925c50f86da0596b9c3c64c3837b2481337b83ef3519e5db2701df695453a4"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:52e466bea6f8f3a44b1234570244b1cff45150f59a4acae3fcc5fd700c2993ca"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e21cc693045fda7f745c790cb687958161ce172ffe3c5719ca1764e752237d16"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b31f059878eb1f5da8b2fd82480cc18bed8dcd7fb8fe68370e2e6285fa86da6"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1dd46f309e953927dd018567d6a9e2fb84783963650171f6c5fe7e5c41fd5666"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34a01a4490e170376cd79258b7f755fa13b1a6c3667e872c8e35051ae857a92b"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bcf426a8c38eb57f7bf28932e68425ba86def6e756a5b8cb4731d8e62e4e0223"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f68eea5df6347d3f1378ce992d86b2af16ad7ff4dcb4a19ccdc23dea901b87fb"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dab8d921b55a28287733263c0e4c7db11b3ee22aee158a4de09f13c93283c62d"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6fe87efd7f47266dfc42fe76dae89060038f1d9cb911f89ae7e5084148d1cc08"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:535d4b52524a961d220875688159277f0e9eeeda0ac45e766092bfb54437543f"},
|
||||
{file = "rpds_py-0.19.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8b1a94b8afc154fbe36978a511a1f155f9bd97664e4f1f7a374d72e180ceb0ae"},
|
||||
{file = "rpds_py-0.19.0-cp38-none-win32.whl", hash = "sha256:7c98298a15d6b90c8f6e3caa6457f4f022423caa5fa1a1ca7a5e9e512bdb77a4"},
|
||||
{file = "rpds_py-0.19.0-cp38-none-win_amd64.whl", hash = "sha256:b0da31853ab6e58a11db3205729133ce0df26e6804e93079dee095be3d681dc1"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5039e3cef7b3e7a060de468a4a60a60a1f31786da94c6cb054e7a3c75906111c"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ab1932ca6cb8c7499a4d87cb21ccc0d3326f172cfb6a64021a889b591bb3045c"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2afd2164a1e85226fcb6a1da77a5c8896c18bfe08e82e8ceced5181c42d2179"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b1c30841f5040de47a0046c243fc1b44ddc87d1b12435a43b8edff7e7cb1e0d0"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f757f359f30ec7dcebca662a6bd46d1098f8b9fb1fcd661a9e13f2e8ce343ba1"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15e65395a59d2e0e96caf8ee5389ffb4604e980479c32742936ddd7ade914b22"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb0f6eb3a320f24b94d177e62f4074ff438f2ad9d27e75a46221904ef21a7b05"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b228e693a2559888790936e20f5f88b6e9f8162c681830eda303bad7517b4d5a"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2575efaa5d949c9f4e2cdbe7d805d02122c16065bfb8d95c129372d65a291a0b"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:5c872814b77a4e84afa293a1bee08c14daed1068b2bb1cc312edbf020bbbca2b"},
|
||||
{file = "rpds_py-0.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:850720e1b383df199b8433a20e02b25b72f0fded28bc03c5bd79e2ce7ef050be"},
|
||||
{file = "rpds_py-0.19.0-cp39-none-win32.whl", hash = "sha256:ce84a7efa5af9f54c0aa7692c45861c1667080814286cacb9958c07fc50294fb"},
|
||||
{file = "rpds_py-0.19.0-cp39-none-win_amd64.whl", hash = "sha256:1c26da90b8d06227d7769f34915913911222d24ce08c0ab2d60b354e2d9c7aff"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:75969cf900d7be665ccb1622a9aba225cf386bbc9c3bcfeeab9f62b5048f4a07"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:8445f23f13339da640d1be8e44e5baf4af97e396882ebbf1692aecd67f67c479"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5a7c1062ef8aea3eda149f08120f10795835fc1c8bc6ad948fb9652a113ca55"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:462b0c18fbb48fdbf980914a02ee38c423a25fcc4cf40f66bacc95a2d2d73bc8"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3208f9aea18991ac7f2b39721e947bbd752a1abbe79ad90d9b6a84a74d44409b"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3444fe52b82f122d8a99bf66777aed6b858d392b12f4c317da19f8234db4533"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88cb4bac7185a9f0168d38c01d7a00addece9822a52870eee26b8d5b61409213"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6b130bd4163c93798a6b9bb96be64a7c43e1cec81126ffa7ffaa106e1fc5cef5"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a707b158b4410aefb6b054715545bbb21aaa5d5d0080217290131c49c2124a6e"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:dc9ac4659456bde7c567107556ab065801622396b435a3ff213daef27b495388"},
|
||||
{file = "rpds_py-0.19.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81ea573aa46d3b6b3d890cd3c0ad82105985e6058a4baed03cf92518081eec8c"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f148c3f47f7f29a79c38cc5d020edcb5ca780020fab94dbc21f9af95c463581"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0906357f90784a66e89ae3eadc2654f36c580a7d65cf63e6a616e4aec3a81be"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f629ecc2db6a4736b5ba95a8347b0089240d69ad14ac364f557d52ad68cf94b0"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6feacd1d178c30e5bc37184526e56740342fd2aa6371a28367bad7908d454fc"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae8b6068ee374fdfab63689be0963333aa83b0815ead5d8648389a8ded593378"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d57546bad81e0da13263e4c9ce30e96dcbe720dbff5ada08d2600a3502e526"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b6683a37338818646af718c9ca2a07f89787551057fae57c4ec0446dc6224b"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e8481b946792415adc07410420d6fc65a352b45d347b78fec45d8f8f0d7496f0"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bec35eb20792ea64c3c57891bc3ca0bedb2884fbac2c8249d9b731447ecde4fa"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:aa5476c3e3a402c37779e95f7b4048db2cb5b0ed0b9d006983965e93f40fe05a"},
|
||||
{file = "rpds_py-0.19.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:19d02c45f2507b489fd4df7b827940f1420480b3e2e471e952af4d44a1ea8e34"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a3e2fd14c5d49ee1da322672375963f19f32b3d5953f0615b175ff7b9d38daed"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:93a91c2640645303e874eada51f4f33351b84b351a689d470f8108d0e0694210"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b9fc03bf76a94065299d4a2ecd8dfbae4ae8e2e8098bbfa6ab6413ca267709"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a4b07cdf3f84310c08c1de2c12ddadbb7a77568bcb16e95489f9c81074322ed"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba0ed0dc6763d8bd6e5de5cf0d746d28e706a10b615ea382ac0ab17bb7388633"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:474bc83233abdcf2124ed3f66230a1c8435896046caa4b0b5ab6013c640803cc"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329c719d31362355a96b435f4653e3b4b061fcc9eba9f91dd40804ca637d914e"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef9101f3f7b59043a34f1dccbb385ca760467590951952d6701df0da9893ca0c"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:0121803b0f424ee2109d6e1f27db45b166ebaa4b32ff47d6aa225642636cd834"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8344127403dea42f5970adccf6c5957a71a47f522171fafaf4c6ddb41b61703a"},
|
||||
{file = "rpds_py-0.19.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:443cec402ddd650bb2b885113e1dcedb22b1175c6be223b14246a714b61cd521"},
|
||||
{file = "rpds_py-0.19.0.tar.gz", hash = "sha256:4fdc9afadbeb393b4bbbad75481e0ea78e4469f2e1d713a90811700830b553a9"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:aaf71f95b21f9dc708123335df22e5a2fef6307e3e6f9ed773b2e0938cc4d491"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ca0dda0c5715efe2ab35bb83f813f681ebcd2840d8b1b92bfc6fe3ab382fae4a"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81db2e7282cc0487f500d4db203edc57da81acde9e35f061d69ed983228ffe3b"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1a8dfa125b60ec00c7c9baef945bb04abf8ac772d8ebefd79dae2a5f316d7850"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271accf41b02687cef26367c775ab220372ee0f4925591c6796e7c148c50cab5"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9bc4161bd3b970cd6a6fcda70583ad4afd10f2750609fb1f3ca9505050d4ef3"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0cf2a0dbb5987da4bd92a7ca727eadb225581dd9681365beba9accbe5308f7d"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b5e28e56143750808c1c79c70a16519e9bc0a68b623197b96292b21b62d6055c"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c7af6f7b80f687b33a4cdb0a785a5d4de1fb027a44c9a049d8eb67d5bfe8a687"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e429fc517a1c5e2a70d576077231538a98d59a45dfc552d1ac45a132844e6dfb"},
|
||||
{file = "rpds_py-0.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d2dbd8f4990d4788cb122f63bf000357533f34860d269c1a8e90ae362090ff3a"},
|
||||
{file = "rpds_py-0.19.1-cp310-none-win32.whl", hash = "sha256:e0f9d268b19e8f61bf42a1da48276bcd05f7ab5560311f541d22557f8227b866"},
|
||||
{file = "rpds_py-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:df7c841813f6265e636fe548a49664c77af31ddfa0085515326342a751a6ba51"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:902cf4739458852fe917104365ec0efbea7d29a15e4276c96a8d33e6ed8ec137"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f3d73022990ab0c8b172cce57c69fd9a89c24fd473a5e79cbce92df87e3d9c48"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3837c63dd6918a24de6c526277910e3766d8c2b1627c500b155f3eecad8fad65"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cdb7eb3cf3deb3dd9e7b8749323b5d970052711f9e1e9f36364163627f96da58"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26ab43b6d65d25b1a333c8d1b1c2f8399385ff683a35ab5e274ba7b8bb7dc61c"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75130df05aae7a7ac171b3b5b24714cffeabd054ad2ebc18870b3aa4526eba23"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c34f751bf67cab69638564eee34023909380ba3e0d8ee7f6fe473079bf93f09b"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2671cb47e50a97f419a02cd1e0c339b31de017b033186358db92f4d8e2e17d8"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c73254c256081704dba0a333457e2fb815364018788f9b501efe7c5e0ada401"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4383beb4a29935b8fa28aca8fa84c956bf545cb0c46307b091b8d312a9150e6a"},
|
||||
{file = "rpds_py-0.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:dbceedcf4a9329cc665452db1aaf0845b85c666e4885b92ee0cddb1dbf7e052a"},
|
||||
{file = "rpds_py-0.19.1-cp311-none-win32.whl", hash = "sha256:f0a6d4a93d2a05daec7cb885157c97bbb0be4da739d6f9dfb02e101eb40921cd"},
|
||||
{file = "rpds_py-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:c149a652aeac4902ecff2dd93c3b2681c608bd5208c793c4a99404b3e1afc87c"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:56313be667a837ff1ea3508cebb1ef6681d418fa2913a0635386cf29cff35165"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6d1d7539043b2b31307f2c6c72957a97c839a88b2629a348ebabe5aa8b626d6b"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e1dc59a5e7bc7f44bd0c048681f5e05356e479c50be4f2c1a7089103f1621d5"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b8f78398e67a7227aefa95f876481485403eb974b29e9dc38b307bb6eb2315ea"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ef07a0a1d254eeb16455d839cef6e8c2ed127f47f014bbda64a58b5482b6c836"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8124101e92c56827bebef084ff106e8ea11c743256149a95b9fd860d3a4f331f"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08ce9c95a0b093b7aec75676b356a27879901488abc27e9d029273d280438505"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b02dd77a2de6e49078c8937aadabe933ceac04b41c5dde5eca13a69f3cf144e"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4dd02e29c8cbed21a1875330b07246b71121a1c08e29f0ee3db5b4cfe16980c4"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9c7042488165f7251dc7894cd533a875d2875af6d3b0e09eda9c4b334627ad1c"},
|
||||
{file = "rpds_py-0.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f809a17cc78bd331e137caa25262b507225854073fd319e987bd216bed911b7c"},
|
||||
{file = "rpds_py-0.19.1-cp312-none-win32.whl", hash = "sha256:3ddab996807c6b4227967fe1587febade4e48ac47bb0e2d3e7858bc621b1cace"},
|
||||
{file = "rpds_py-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:32e0db3d6e4f45601b58e4ac75c6f24afbf99818c647cc2066f3e4b192dabb1f"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:747251e428406b05fc86fee3904ee19550c4d2d19258cef274e2151f31ae9d38"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dc733d35f861f8d78abfaf54035461e10423422999b360966bf1c443cbc42705"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbda75f245caecff8faa7e32ee94dfaa8312a3367397975527f29654cd17a6ed"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bd04d8cab16cab5b0a9ffc7d10f0779cf1120ab16c3925404428f74a0a43205a"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2d66eb41ffca6cc3c91d8387509d27ba73ad28371ef90255c50cb51f8953301"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdf4890cda3b59170009d012fca3294c00140e7f2abe1910e6a730809d0f3f9b"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1fa67ef839bad3815124f5f57e48cd50ff392f4911a9f3cf449d66fa3df62a5"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b82c9514c6d74b89a370c4060bdb80d2299bc6857e462e4a215b4ef7aa7b090e"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c7b07959866a6afb019abb9564d8a55046feb7a84506c74a6f197cbcdf8a208e"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4f580ae79d0b861dfd912494ab9d477bea535bfb4756a2269130b6607a21802e"},
|
||||
{file = "rpds_py-0.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c6d20c8896c00775e6f62d8373aba32956aa0b850d02b5ec493f486c88e12859"},
|
||||
{file = "rpds_py-0.19.1-cp313-none-win32.whl", hash = "sha256:afedc35fe4b9e30ab240b208bb9dc8938cb4afe9187589e8d8d085e1aacb8309"},
|
||||
{file = "rpds_py-0.19.1-cp313-none-win_amd64.whl", hash = "sha256:1d4af2eb520d759f48f1073ad3caef997d1bfd910dc34e41261a595d3f038a94"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:34bca66e2e3eabc8a19e9afe0d3e77789733c702c7c43cd008e953d5d1463fde"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:24f8ae92c7fae7c28d0fae9b52829235df83f34847aa8160a47eb229d9666c7b"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71157f9db7f6bc6599a852852f3389343bea34315b4e6f109e5cbc97c1fb2963"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d494887d40dc4dd0d5a71e9d07324e5c09c4383d93942d391727e7a40ff810b"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7b3661e6d4ba63a094138032c1356d557de5b3ea6fd3cca62a195f623e381c76"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97fbb77eaeb97591efdc654b8b5f3ccc066406ccfb3175b41382f221ecc216e8"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cc4bc73e53af8e7a42c8fd7923bbe35babacfa7394ae9240b3430b5dcf16b2a"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:35af5e4d5448fa179fd7fff0bba0fba51f876cd55212f96c8bbcecc5c684ae5c"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3511f6baf8438326e351097cecd137eb45c5f019944fe0fd0ae2fea2fd26be39"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:57863d16187995c10fe9cf911b897ed443ac68189179541734502353af33e693"},
|
||||
{file = "rpds_py-0.19.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9e318e6786b1e750a62f90c6f7fa8b542102bdcf97c7c4de2a48b50b61bd36ec"},
|
||||
{file = "rpds_py-0.19.1-cp38-none-win32.whl", hash = "sha256:53dbc35808c6faa2ce3e48571f8f74ef70802218554884787b86a30947842a14"},
|
||||
{file = "rpds_py-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:8df1c283e57c9cb4d271fdc1875f4a58a143a2d1698eb0d6b7c0d7d5f49c53a1"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e76c902d229a3aa9d5ceb813e1cbcc69bf5bda44c80d574ff1ac1fa3136dea71"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:de1f7cd5b6b351e1afd7568bdab94934d656abe273d66cda0ceea43bbc02a0c2"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fc5a84777cb61692d17988989690d6f34f7f95968ac81398d67c0d0994a897"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:74129d5ffc4cde992d89d345f7f7d6758320e5d44a369d74d83493429dad2de5"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e360188b72f8080fefa3adfdcf3618604cc8173651c9754f189fece068d2a45"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13e6d4840897d4e4e6b2aa1443e3a8eca92b0402182aafc5f4ca1f5e24f9270a"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f09529d2332264a902688031a83c19de8fda5eb5881e44233286b9c9ec91856d"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0d4b52811dcbc1aba08fd88d475f75b4f6db0984ba12275d9bed1a04b2cae9b5"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dd635c2c4043222d80d80ca1ac4530a633102a9f2ad12252183bcf338c1b9474"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f35b34a5184d5e0cc360b61664c1c06e866aab077b5a7c538a3e20c8fcdbf90b"},
|
||||
{file = "rpds_py-0.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d4ec0046facab83012d821b33cead742a35b54575c4edfb7ed7445f63441835f"},
|
||||
{file = "rpds_py-0.19.1-cp39-none-win32.whl", hash = "sha256:f5b8353ea1a4d7dfb59a7f45c04df66ecfd363bb5b35f33b11ea579111d4655f"},
|
||||
{file = "rpds_py-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:1fb93d3486f793d54a094e2bfd9cd97031f63fcb5bc18faeb3dd4b49a1c06523"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7d5c7e32f3ee42f77d8ff1a10384b5cdcc2d37035e2e3320ded909aa192d32c3"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:89cc8921a4a5028d6dd388c399fcd2eef232e7040345af3d5b16c04b91cf3c7e"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bca34e913d27401bda2a6f390d0614049f5a95b3b11cd8eff80fe4ec340a1208"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5953391af1405f968eb5701ebbb577ebc5ced8d0041406f9052638bafe52209d"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:840e18c38098221ea6201f091fc5d4de6128961d2930fbbc96806fb43f69aec1"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6d8b735c4d162dc7d86a9cf3d717f14b6c73637a1f9cd57fe7e61002d9cb1972"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce757c7c90d35719b38fa3d4ca55654a76a40716ee299b0865f2de21c146801c"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a9421b23c85f361a133aa7c5e8ec757668f70343f4ed8fdb5a4a14abd5437244"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:3b823be829407393d84ee56dc849dbe3b31b6a326f388e171555b262e8456cc1"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:5e58b61dcbb483a442c6239c3836696b79f2cd8e7eec11e12155d3f6f2d886d1"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39d67896f7235b2c886fb1ee77b1491b77049dcef6fbf0f401e7b4cbed86bbd4"},
|
||||
{file = "rpds_py-0.19.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:8b32cd4ab6db50c875001ba4f5a6b30c0f42151aa1fbf9c2e7e3674893fb1dc4"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:1c32e41de995f39b6b315d66c27dea3ef7f7c937c06caab4c6a79a5e09e2c415"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:1a129c02b42d46758c87faeea21a9f574e1c858b9f358b6dd0bbd71d17713175"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:346557f5b1d8fd9966059b7a748fd79ac59f5752cd0e9498d6a40e3ac1c1875f"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:31e450840f2f27699d014cfc8865cc747184286b26d945bcea6042bb6aa4d26e"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:01227f8b3e6c8961490d869aa65c99653df80d2f0a7fde8c64ebddab2b9b02fd"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:69084fd29bfeff14816666c93a466e85414fe6b7d236cfc108a9c11afa6f7301"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4d2b88efe65544a7d5121b0c3b003ebba92bfede2ea3577ce548b69c5235185"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ea961a674172ed2235d990d7edf85d15d8dfa23ab8575e48306371c070cda67"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:5beffdbe766cfe4fb04f30644d822a1080b5359df7db3a63d30fa928375b2720"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:720f3108fb1bfa32e51db58b832898372eb5891e8472a8093008010911e324c5"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c2087dbb76a87ec2c619253e021e4fb20d1a72580feeaa6892b0b3d955175a71"},
|
||||
{file = "rpds_py-0.19.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ddd50f18ebc05ec29a0d9271e9dbe93997536da3546677f8ca00b76d477680c"},
|
||||
{file = "rpds_py-0.19.1.tar.gz", hash = "sha256:31dd5794837f00b46f4096aa8ccaa5972f73a938982e32ed817bb520c465e520"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.5.3"
|
||||
version = "0.5.5"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.5.3-py3-none-linux_armv6l.whl", hash = "sha256:b12424d9db7347fa63c5ed9af010003338c63c629fb9c9c6adb2aa4f5699729b"},
|
||||
{file = "ruff-0.5.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8d72c5684bbd4ed304a9a955ee2e67f57b35f6193222ade910cca8a805490e3"},
|
||||
{file = "ruff-0.5.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d2fc2cdb85ccac1e816cc9d5d8cedefd93661bd957756d902543af32a6b04a71"},
|
||||
{file = "ruff-0.5.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf4bc751240b2fab5d19254571bcacb315c7b0b00bf3c912d52226a82bbec073"},
|
||||
{file = "ruff-0.5.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc697ec874fdd7c7ba0a85ec76ab38f8595224868d67f097c5ffc21136e72fcd"},
|
||||
{file = "ruff-0.5.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e791d34d3557a3819b3704bc1f087293c821083fa206812842fa363f6018a192"},
|
||||
{file = "ruff-0.5.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:76bb5a87fd397520b91a83eae8a2f7985236d42dd9459f09eef58e7f5c1d8316"},
|
||||
{file = "ruff-0.5.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8cfc7a26422c78e94f1ec78ec02501bbad2df5834907e75afe474cc6b83a8c1"},
|
||||
{file = "ruff-0.5.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96066c4328a49fce2dd40e80f7117987369feec30ab771516cf95f1cc2db923c"},
|
||||
{file = "ruff-0.5.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03bfe9ab5bdc0b08470c3b261643ad54ea86edc32b64d1e080892d7953add3ad"},
|
||||
{file = "ruff-0.5.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7704582a026fa02cca83efd76671a98ee6eb412c4230209efe5e2a006c06db62"},
|
||||
{file = "ruff-0.5.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:08058d077e21b856d32ebf483443390e29dc44d927608dc8f092ff6776519da9"},
|
||||
{file = "ruff-0.5.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:77d49484429ed7c7e6e2e75a753f153b7b58f875bdb4158ad85af166a1ec1822"},
|
||||
{file = "ruff-0.5.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:642cbff6cbfa38d2566d8db086508d6f472edb136cbfcc4ea65997745368c29e"},
|
||||
{file = "ruff-0.5.3-py3-none-win32.whl", hash = "sha256:eafc45dd8bdc37a00b28e68cc038daf3ca8c233d73fea276dcd09defb1352841"},
|
||||
{file = "ruff-0.5.3-py3-none-win_amd64.whl", hash = "sha256:cbaec2ddf4f78e5e9ecf5456ea0f496991358a1d883862ed0b9e947e2b6aea93"},
|
||||
{file = "ruff-0.5.3-py3-none-win_arm64.whl", hash = "sha256:05fbd2cb404775d6cd7f2ff49504e2d20e13ef95fa203bd1ab22413af70d420b"},
|
||||
{file = "ruff-0.5.3.tar.gz", hash = "sha256:2a3eb4f1841771fa5b67a56be9c2d16fd3cc88e378bd86aaeaec2f7e6bcdd0a2"},
|
||||
{file = "ruff-0.5.5-py3-none-linux_armv6l.whl", hash = "sha256:605d589ec35d1da9213a9d4d7e7a9c761d90bba78fc8790d1c5e65026c1b9eaf"},
|
||||
{file = "ruff-0.5.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:00817603822a3e42b80f7c3298c8269e09f889ee94640cd1fc7f9329788d7bf8"},
|
||||
{file = "ruff-0.5.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:187a60f555e9f865a2ff2c6984b9afeffa7158ba6e1eab56cb830404c942b0f3"},
|
||||
{file = "ruff-0.5.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fe26fc46fa8c6e0ae3f47ddccfbb136253c831c3289bba044befe68f467bfb16"},
|
||||
{file = "ruff-0.5.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ad25dd9c5faac95c8e9efb13e15803cd8bbf7f4600645a60ffe17c73f60779b"},
|
||||
{file = "ruff-0.5.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f70737c157d7edf749bcb952d13854e8f745cec695a01bdc6e29c29c288fc36e"},
|
||||
{file = "ruff-0.5.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:cfd7de17cef6ab559e9f5ab859f0d3296393bc78f69030967ca4d87a541b97a0"},
|
||||
{file = "ruff-0.5.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a09b43e02f76ac0145f86a08e045e2ea452066f7ba064fd6b0cdccb486f7c3e7"},
|
||||
{file = "ruff-0.5.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0b856cb19c60cd40198be5d8d4b556228e3dcd545b4f423d1ad812bfdca5884"},
|
||||
{file = "ruff-0.5.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3687d002f911e8a5faf977e619a034d159a8373514a587249cc00f211c67a091"},
|
||||
{file = "ruff-0.5.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:ac9dc814e510436e30d0ba535f435a7f3dc97f895f844f5b3f347ec8c228a523"},
|
||||
{file = "ruff-0.5.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:af9bdf6c389b5add40d89b201425b531e0a5cceb3cfdcc69f04d3d531c6be74f"},
|
||||
{file = "ruff-0.5.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d40a8533ed545390ef8315b8e25c4bb85739b90bd0f3fe1280a29ae364cc55d8"},
|
||||
{file = "ruff-0.5.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cab904683bf9e2ecbbe9ff235bfe056f0eba754d0168ad5407832928d579e7ab"},
|
||||
{file = "ruff-0.5.5-py3-none-win32.whl", hash = "sha256:696f18463b47a94575db635ebb4c178188645636f05e934fdf361b74edf1bb2d"},
|
||||
{file = "ruff-0.5.5-py3-none-win_amd64.whl", hash = "sha256:50f36d77f52d4c9c2f1361ccbfbd09099a1b2ea5d2b2222c586ab08885cf3445"},
|
||||
{file = "ruff-0.5.5-py3-none-win_arm64.whl", hash = "sha256:3191317d967af701f1b73a31ed5788795936e423b7acce82a2b63e26eb3e89d6"},
|
||||
{file = "ruff-0.5.5.tar.gz", hash = "sha256:cc5516bdb4858d972fbc31d246bdb390eab8df1a26e2353be2dbc0c2d7f5421a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2853,13 +2857,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "types-pyyaml"
|
||||
version = "6.0.12.20240311"
|
||||
version = "6.0.12.20240724"
|
||||
description = "Typing stubs for PyYAML"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-PyYAML-6.0.12.20240311.tar.gz", hash = "sha256:a9e0f0f88dc835739b0c1ca51ee90d04ca2a897a71af79de9aec5f38cb0a5342"},
|
||||
{file = "types_PyYAML-6.0.12.20240311-py3-none-any.whl", hash = "sha256:b845b06a1c7e54b8e5b4c683043de0d9caf205e7434b3edc678ff2411979b8f6"},
|
||||
{file = "types-PyYAML-6.0.12.20240724.tar.gz", hash = "sha256:cf7b31ae67e0c5b2919c703d2affc415485099d3fe6666a6912f040fd05cb67f"},
|
||||
{file = "types_PyYAML-6.0.12.20240724-py3-none-any.whl", hash = "sha256:e5becec598f3aa3a2ddf671de4a75fa1c6856fbf73b2840286c9d50fae2d5d48"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3044,4 +3048,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools",
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
content-hash = "8db47de0615d9a5324dc0e28f6110908e9b16ccfee699aeafef21f68c879e62a"
|
||||
content-hash = "74434689496616068607618a26e7de242b0bb5c3123463566f4976ab28cc747f"
|
||||
|
||||
@@ -74,7 +74,7 @@ optional = true
|
||||
ruff = "^0.5"
|
||||
|
||||
[tool.poetry.group.typing.dependencies]
|
||||
mypy = "^1.10"
|
||||
mypy = ">=1.10,<1.11"
|
||||
types-pyyaml = "^6.0.12.2"
|
||||
types-requests = "^2.28.11.5"
|
||||
types-jinja2 = "^2.11.9"
|
||||
|
||||
@@ -4,6 +4,7 @@ import inspect
|
||||
import json
|
||||
import sys
|
||||
import textwrap
|
||||
import threading
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from functools import partial
|
||||
@@ -977,7 +978,7 @@ class AFooBase(FooBase):
|
||||
def test_tool_pass_config(tool: BaseTool) -> None:
|
||||
assert tool.invoke({"bar": "baz"}, {"configurable": {"foo": "not-bar"}}) == "baz"
|
||||
|
||||
# Test tool calls
|
||||
# Test we don't mutate tool calls
|
||||
tool_call = {
|
||||
"name": tool.name,
|
||||
"args": {"bar": "baz"},
|
||||
@@ -988,6 +989,25 @@ def test_tool_pass_config(tool: BaseTool) -> None:
|
||||
assert tool_call["args"] == {"bar": "baz"}
|
||||
|
||||
|
||||
class FooBaseNonPickleable(FooBase):
|
||||
def _run(self, bar: Any, bar_config: RunnableConfig, **kwargs: Any) -> Any:
|
||||
return True
|
||||
|
||||
|
||||
def test_tool_pass_config_non_pickleable() -> None:
|
||||
tool = FooBaseNonPickleable()
|
||||
|
||||
args = {"bar": threading.Lock()}
|
||||
tool_call = {
|
||||
"name": tool.name,
|
||||
"args": args,
|
||||
"id": "abc123",
|
||||
"type": "tool_call",
|
||||
}
|
||||
_ = tool.invoke(tool_call, {"configurable": {"foo": "not-bar"}})
|
||||
assert tool_call["args"] == args
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tool", [foo, afoo, simple_foo, asimple_foo, FooBase(), AFooBase()]
|
||||
)
|
||||
@@ -1429,6 +1449,36 @@ def test_tool_injected_arg_with_schema(tool_: BaseTool) -> None:
|
||||
}
|
||||
|
||||
|
||||
def _get_parametrized_tools() -> list:
|
||||
def my_tool(x: int, y: str, some_tool: Annotated[Any, InjectedToolArg]) -> str:
|
||||
"""my_tool."""
|
||||
return some_tool
|
||||
|
||||
async def my_async_tool(
|
||||
x: int, y: str, *, some_tool: Annotated[Any, InjectedToolArg]
|
||||
) -> str:
|
||||
"""my_tool."""
|
||||
return some_tool
|
||||
|
||||
return [my_tool, my_async_tool]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("tool_", _get_parametrized_tools())
|
||||
def test_fn_injected_arg_with_schema(tool_: Callable) -> None:
|
||||
assert convert_to_openai_function(tool_) == {
|
||||
"name": tool_.__name__,
|
||||
"description": "my_tool.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"x": {"type": "integer"},
|
||||
"y": {"type": "string"},
|
||||
},
|
||||
"required": ["x", "y"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def generate_models() -> List[Any]:
|
||||
"""Generate a list of base models depending on the pydantic version."""
|
||||
from pydantic import BaseModel as BaseModelProper # pydantic: ignore
|
||||
|
||||
@@ -144,7 +144,7 @@ class GenerativeAgentMemory(BaseMemory):
|
||||
+ " following piece of memory. Always answer with only a list of numbers."
|
||||
+ " If just given one memory still respond in a list."
|
||||
+ " Memories are separated by semi colans (;)"
|
||||
+ "\Memories: {memory_content}"
|
||||
+ "\nMemories: {memory_content}"
|
||||
+ "\nRating: "
|
||||
)
|
||||
scores = self.chain(prompt).run(memory_content=memory_content).strip()
|
||||
|
||||
@@ -332,6 +332,7 @@ def create_simple_model(
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
if node_properties:
|
||||
if isinstance(node_properties, list) and "id" in node_properties:
|
||||
raise ValueError("The node property 'id' is reserved and cannot be used.")
|
||||
@@ -347,6 +348,7 @@ def create_simple_model(
|
||||
node_properties_mapped,
|
||||
description="Property key.",
|
||||
input_type="property",
|
||||
llm_type=llm_type,
|
||||
)
|
||||
value: str = Field(..., description="value")
|
||||
|
||||
@@ -370,6 +372,7 @@ def create_simple_model(
|
||||
node_labels,
|
||||
description="The type or label of the source node.",
|
||||
input_type="node",
|
||||
llm_type=llm_type,
|
||||
),
|
||||
),
|
||||
"target_node_id": (
|
||||
@@ -385,6 +388,7 @@ def create_simple_model(
|
||||
node_labels,
|
||||
description="The type or label of the target node.",
|
||||
input_type="node",
|
||||
llm_type=llm_type,
|
||||
),
|
||||
),
|
||||
"type": (
|
||||
@@ -393,6 +397,7 @@ def create_simple_model(
|
||||
rel_types,
|
||||
description="The type of the relationship.",
|
||||
input_type="relationship",
|
||||
llm_type=llm_type,
|
||||
),
|
||||
),
|
||||
}
|
||||
@@ -416,6 +421,7 @@ def create_simple_model(
|
||||
relationship_properties_mapped,
|
||||
description="Property key.",
|
||||
input_type="property",
|
||||
llm_type=llm_type,
|
||||
)
|
||||
value: str = Field(..., description="value")
|
||||
|
||||
|
||||
@@ -3,10 +3,9 @@ from __future__ import annotations
|
||||
from typing import Any, TypeVar, Union
|
||||
|
||||
from langchain_core.exceptions import OutputParserException
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from langchain_core.output_parsers import BaseOutputParser
|
||||
from langchain_core.output_parsers import BaseOutputParser, StrOutputParser
|
||||
from langchain_core.prompts import BasePromptTemplate
|
||||
from langchain_core.runnables import RunnableSerializable
|
||||
from langchain_core.runnables import Runnable, RunnableSerializable
|
||||
from typing_extensions import TypedDict
|
||||
|
||||
from langchain.output_parsers.prompts import NAIVE_FIX_PROMPT
|
||||
@@ -42,7 +41,7 @@ class OutputFixingParser(BaseOutputParser[T]):
|
||||
@classmethod
|
||||
def from_llm(
|
||||
cls,
|
||||
llm: BaseLanguageModel,
|
||||
llm: Runnable,
|
||||
parser: BaseOutputParser[T],
|
||||
prompt: BasePromptTemplate = NAIVE_FIX_PROMPT,
|
||||
max_retries: int = 1,
|
||||
@@ -58,7 +57,7 @@ class OutputFixingParser(BaseOutputParser[T]):
|
||||
Returns:
|
||||
OutputFixingParser
|
||||
"""
|
||||
chain = prompt | llm
|
||||
chain = prompt | llm | StrOutputParser()
|
||||
return cls(parser=parser, retry_chain=chain, max_retries=max_retries)
|
||||
|
||||
def parse(self, completion: str) -> T:
|
||||
|
||||
@@ -4,7 +4,7 @@ from typing import Any, TypeVar, Union
|
||||
|
||||
from langchain_core.exceptions import OutputParserException
|
||||
from langchain_core.language_models import BaseLanguageModel
|
||||
from langchain_core.output_parsers import BaseOutputParser
|
||||
from langchain_core.output_parsers import BaseOutputParser, StrOutputParser
|
||||
from langchain_core.prompt_values import PromptValue
|
||||
from langchain_core.prompts import BasePromptTemplate, PromptTemplate
|
||||
from langchain_core.runnables import RunnableSerializable
|
||||
@@ -82,7 +82,7 @@ class RetryOutputParser(BaseOutputParser[T]):
|
||||
Returns:
|
||||
RetryOutputParser
|
||||
"""
|
||||
chain = prompt | llm
|
||||
chain = prompt | llm | StrOutputParser()
|
||||
return cls(parser=parser, retry_chain=chain, max_retries=max_retries)
|
||||
|
||||
def parse_with_prompt(self, completion: str, prompt_value: PromptValue) -> T:
|
||||
|
||||
@@ -3,6 +3,7 @@ from typing import Any, Callable, Dict, Optional, TypeVar
|
||||
|
||||
import pytest
|
||||
from langchain_core.exceptions import OutputParserException
|
||||
from langchain_core.messages import AIMessage
|
||||
from langchain_core.prompts.prompt import PromptTemplate
|
||||
from langchain_core.runnables import Runnable, RunnableLambda, RunnablePassthrough
|
||||
from pytest_mock import MockerFixture
|
||||
@@ -63,6 +64,22 @@ def test_output_fixing_parser_parse(
|
||||
# TODO: test whether "instructions" is passed to the retry_chain
|
||||
|
||||
|
||||
def test_output_fixing_parser_from_llm() -> None:
|
||||
def fake_llm(prompt: str) -> AIMessage:
|
||||
return AIMessage("2024-07-08T00:00:00.000000Z")
|
||||
|
||||
llm = RunnableLambda(fake_llm)
|
||||
|
||||
n = 1
|
||||
parser = OutputFixingParser.from_llm(
|
||||
llm=llm,
|
||||
parser=DatetimeOutputParser(),
|
||||
max_retries=n,
|
||||
)
|
||||
|
||||
assert parser.parse("not a date")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"base_parser",
|
||||
[
|
||||
|
||||
@@ -318,7 +318,7 @@ class ChatFireworks(BaseChatModel):
|
||||
"""Model name to use."""
|
||||
temperature: float = 0.0
|
||||
"""What sampling temperature to use."""
|
||||
stop: Optional[Union[str, List[str]]] = Field(None, alias="stop_sequences")
|
||||
stop: Optional[Union[str, List[str]]] = Field(default=None, alias="stop_sequences")
|
||||
"""Default stop sequences."""
|
||||
model_kwargs: Dict[str, Any] = Field(default_factory=dict)
|
||||
"""Holds any model parameters valid for `create` call not explicitly specified."""
|
||||
|
||||
@@ -4,12 +4,15 @@ from typing import Type
|
||||
|
||||
import pytest
|
||||
from langchain_core.language_models import BaseChatModel
|
||||
from langchain_standard_tests.integration_tests import ( # type: ignore[import-not-found]
|
||||
ChatModelIntegrationTests, # type: ignore[import-not-found]
|
||||
from langchain_core.rate_limiters import InMemoryRateLimiter
|
||||
from langchain_standard_tests.integration_tests import (
|
||||
ChatModelIntegrationTests,
|
||||
)
|
||||
|
||||
from langchain_groq import ChatGroq
|
||||
|
||||
rate_limiter = InMemoryRateLimiter(requests_per_second=0.45)
|
||||
|
||||
|
||||
class BaseTestGroq(ChatModelIntegrationTests):
|
||||
@property
|
||||
@@ -21,32 +24,13 @@ class BaseTestGroq(ChatModelIntegrationTests):
|
||||
super().test_tool_message_histories_list_content(model)
|
||||
|
||||
|
||||
class TestGroqMixtral(BaseTestGroq):
|
||||
@property
|
||||
def chat_model_params(self) -> dict:
|
||||
return {
|
||||
"temperature": 0,
|
||||
}
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason=("Fails with 'Failed to call a function. Please adjust your prompt.'")
|
||||
)
|
||||
def test_structured_output(self, model: BaseChatModel) -> None:
|
||||
super().test_structured_output(model)
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason=("May pass arguments: {'properties': {}, 'type': 'object'}")
|
||||
)
|
||||
def test_tool_calling_with_no_arguments(self, model: BaseChatModel) -> None:
|
||||
super().test_tool_calling_with_no_arguments(model)
|
||||
|
||||
|
||||
class TestGroqLlama(BaseTestGroq):
|
||||
@property
|
||||
def chat_model_params(self) -> dict:
|
||||
return {
|
||||
"model": "llama3-8b-8192",
|
||||
"model": "llama-3.1-8b-instant",
|
||||
"temperature": 0,
|
||||
"rate_limiter": rate_limiter,
|
||||
}
|
||||
|
||||
@pytest.mark.xfail(
|
||||
|
||||
@@ -15,8 +15,6 @@ from datetime import date, datetime
|
||||
from typing import Any, Dict, List, Union
|
||||
|
||||
import numpy as np
|
||||
from bson import ObjectId
|
||||
from bson.errors import InvalidId
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -95,7 +93,7 @@ def maximal_marginal_relevance(
|
||||
return idxs
|
||||
|
||||
|
||||
def str_to_oid(str_repr: str) -> ObjectId | str:
|
||||
def str_to_oid(str_repr: str) -> Any | str:
|
||||
"""Attempt to cast string representation of id to MongoDB's internal BSON ObjectId.
|
||||
|
||||
To be consistent with ObjectId, input must be a 24 character hex string.
|
||||
@@ -108,6 +106,9 @@ def str_to_oid(str_repr: str) -> ObjectId | str:
|
||||
Returns:
|
||||
ObjectID
|
||||
"""
|
||||
from bson import ObjectId
|
||||
from bson.errors import InvalidId
|
||||
|
||||
try:
|
||||
return ObjectId(str_repr)
|
||||
except InvalidId:
|
||||
@@ -118,7 +119,7 @@ def str_to_oid(str_repr: str) -> ObjectId | str:
|
||||
return str_repr
|
||||
|
||||
|
||||
def oid_to_str(oid: ObjectId) -> str:
|
||||
def oid_to_str(oid: Any) -> str:
|
||||
"""Convert MongoDB's internal BSON ObjectId into a simple str for compatibility.
|
||||
|
||||
Instructive helper to show where data is coming out of MongoDB.
|
||||
@@ -136,6 +137,8 @@ def make_serializable(
|
||||
obj: Dict[str, Any],
|
||||
) -> None:
|
||||
"""Recursively cast values in a dict to a form able to json.dump"""
|
||||
from bson import ObjectId
|
||||
|
||||
for k, v in obj.items():
|
||||
if isinstance(v, dict):
|
||||
make_serializable(v)
|
||||
|
||||
@@ -17,7 +17,6 @@ from typing import (
|
||||
)
|
||||
from uuid import uuid4
|
||||
|
||||
import ollama
|
||||
from langchain_core.callbacks import (
|
||||
CallbackManagerForLLMRun,
|
||||
)
|
||||
@@ -40,7 +39,7 @@ from langchain_core.pydantic_v1 import BaseModel
|
||||
from langchain_core.runnables import Runnable
|
||||
from langchain_core.tools import BaseTool
|
||||
from langchain_core.utils.function_calling import convert_to_openai_tool
|
||||
from ollama import AsyncClient, Message, Options
|
||||
from ollama import AsyncClient, Client, Message, Options
|
||||
|
||||
|
||||
def _get_usage_metadata_from_generation_info(
|
||||
@@ -292,6 +291,11 @@ class ChatOllama(BaseChatModel):
|
||||
"""The temperature of the model. Increasing the temperature will
|
||||
make the model answer more creatively. (Default: 0.8)"""
|
||||
|
||||
seed: Optional[int] = None
|
||||
"""Sets the random number seed to use for generation. Setting this
|
||||
to a specific number will make the model generate the same text for
|
||||
the same prompt."""
|
||||
|
||||
stop: Optional[List[str]] = None
|
||||
"""Sets the stop tokens to use."""
|
||||
|
||||
@@ -316,6 +320,9 @@ class ChatOllama(BaseChatModel):
|
||||
keep_alive: Optional[Union[int, str]] = None
|
||||
"""How long the model will stay loaded into memory."""
|
||||
|
||||
base_url: Optional[str] = None
|
||||
"""Base url the model is hosted under."""
|
||||
|
||||
@property
|
||||
def _default_params(self) -> Dict[str, Any]:
|
||||
"""Get the default parameters for calling Ollama."""
|
||||
@@ -333,6 +340,7 @@ class ChatOllama(BaseChatModel):
|
||||
"repeat_last_n": self.repeat_last_n,
|
||||
"repeat_penalty": self.repeat_penalty,
|
||||
"temperature": self.temperature,
|
||||
"seed": self.seed,
|
||||
"stop": self.stop,
|
||||
"tfs_z": self.tfs_z,
|
||||
"top_k": self.top_k,
|
||||
@@ -346,7 +354,7 @@ class ChatOllama(BaseChatModel):
|
||||
) -> Sequence[Message]:
|
||||
ollama_messages: List = []
|
||||
for message in messages:
|
||||
role = ""
|
||||
role: Literal["user", "assistant", "system", "tool"]
|
||||
tool_call_id: Optional[str] = None
|
||||
tool_calls: Optional[List[Dict[str, Any]]] = None
|
||||
if isinstance(message, HumanMessage):
|
||||
@@ -383,11 +391,13 @@ class ChatOllama(BaseChatModel):
|
||||
image_url = None
|
||||
temp_image_url = content_part.get("image_url")
|
||||
if isinstance(temp_image_url, str):
|
||||
image_url = content_part["image_url"]
|
||||
elif (
|
||||
isinstance(temp_image_url, dict) and "url" in temp_image_url
|
||||
):
|
||||
image_url = temp_image_url
|
||||
elif (
|
||||
isinstance(temp_image_url, dict)
|
||||
and "url" in temp_image_url
|
||||
and isinstance(temp_image_url["url"], str)
|
||||
):
|
||||
image_url = temp_image_url["url"]
|
||||
else:
|
||||
raise ValueError(
|
||||
"Only string image_url or dict with string 'url' "
|
||||
@@ -408,15 +418,16 @@ class ChatOllama(BaseChatModel):
|
||||
"Must either have type 'text' or type 'image_url' "
|
||||
"with a string 'image_url' field."
|
||||
)
|
||||
msg = {
|
||||
# Should convert to ollama.Message once role includes tool, and tool_call_id is in Message # noqa: E501
|
||||
msg: dict = {
|
||||
"role": role,
|
||||
"content": content,
|
||||
"images": images,
|
||||
}
|
||||
if tool_calls:
|
||||
msg["tool_calls"] = tool_calls # type: ignore
|
||||
if tool_call_id:
|
||||
msg["tool_call_id"] = tool_call_id
|
||||
if tool_calls:
|
||||
msg["tool_calls"] = tool_calls
|
||||
ollama_messages.append(msg)
|
||||
|
||||
return ollama_messages
|
||||
@@ -439,7 +450,7 @@ class ChatOllama(BaseChatModel):
|
||||
|
||||
params["options"]["stop"] = stop
|
||||
if "tools" in kwargs:
|
||||
yield await AsyncClient().chat(
|
||||
yield await AsyncClient(host=self.base_url).chat(
|
||||
model=params["model"],
|
||||
messages=ollama_messages,
|
||||
stream=False,
|
||||
@@ -449,7 +460,7 @@ class ChatOllama(BaseChatModel):
|
||||
tools=kwargs["tools"],
|
||||
) # type:ignore
|
||||
else:
|
||||
async for part in await AsyncClient().chat(
|
||||
async for part in await AsyncClient(host=self.base_url).chat(
|
||||
model=params["model"],
|
||||
messages=ollama_messages,
|
||||
stream=True,
|
||||
@@ -477,7 +488,7 @@ class ChatOllama(BaseChatModel):
|
||||
|
||||
params["options"]["stop"] = stop
|
||||
if "tools" in kwargs:
|
||||
yield ollama.chat(
|
||||
yield Client(host=self.base_url).chat(
|
||||
model=params["model"],
|
||||
messages=ollama_messages,
|
||||
stream=False,
|
||||
@@ -487,7 +498,7 @@ class ChatOllama(BaseChatModel):
|
||||
tools=kwargs["tools"],
|
||||
)
|
||||
else:
|
||||
yield from ollama.chat(
|
||||
yield from Client(host=self.base_url).chat(
|
||||
model=params["model"],
|
||||
messages=ollama_messages,
|
||||
stream=True,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
from typing import Type
|
||||
|
||||
import pytest
|
||||
from langchain_core.language_models import BaseChatModel
|
||||
from langchain_standard_tests.integration_tests import ChatModelIntegrationTests
|
||||
|
||||
from langchain_ollama.chat_models import ChatOllama
|
||||
@@ -15,3 +17,23 @@ class TestChatOllama(ChatModelIntegrationTests):
|
||||
@property
|
||||
def chat_model_params(self) -> dict:
|
||||
return {"model": "llama3-groq-tool-use"}
|
||||
|
||||
@property
|
||||
def supports_image_inputs(self) -> bool:
|
||||
return True
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason=(
|
||||
"Fails with 'AssertionError'. Ollama does not support 'tool_choice' yet."
|
||||
)
|
||||
)
|
||||
def test_structured_output(self, model: BaseChatModel) -> None:
|
||||
super().test_structured_output(model)
|
||||
|
||||
@pytest.mark.xfail(
|
||||
reason=(
|
||||
"Fails with 'AssertionError'. Ollama does not support 'tool_choice' yet."
|
||||
)
|
||||
)
|
||||
def test_structured_output_pydantic_2_v1(self, model: BaseChatModel) -> None:
|
||||
super().test_structured_output_pydantic_2_v1(model)
|
||||
|
||||
@@ -423,10 +423,19 @@ class BaseChatOpenAI(BaseChatModel):
|
||||
"default_headers": values["default_headers"],
|
||||
"default_query": values["default_query"],
|
||||
}
|
||||
|
||||
openai_proxy = values["openai_proxy"]
|
||||
if values["openai_proxy"] and (
|
||||
values["http_client"] or values["http_async_client"]
|
||||
):
|
||||
openai_proxy = values["openai_proxy"]
|
||||
http_client = values["http_client"]
|
||||
http_async_client = values["http_async_client"]
|
||||
raise ValueError(
|
||||
"Cannot specify 'openai_proxy' if one of "
|
||||
"'http_client'/'http_async_client' is already specified. Received:\n"
|
||||
f"{openai_proxy=}\n{http_client=}\n{http_async_client=}"
|
||||
)
|
||||
if not values.get("client"):
|
||||
if openai_proxy and not values["http_client"]:
|
||||
if values["openai_proxy"] and not values["http_client"]:
|
||||
try:
|
||||
import httpx
|
||||
except ImportError as e:
|
||||
@@ -434,13 +443,13 @@ class BaseChatOpenAI(BaseChatModel):
|
||||
"Could not import httpx python package. "
|
||||
"Please install it with `pip install httpx`."
|
||||
) from e
|
||||
values["http_client"] = httpx.Client(proxy=openai_proxy)
|
||||
values["http_client"] = httpx.Client(proxy=values["openai_proxy"])
|
||||
sync_specific = {"http_client": values["http_client"]}
|
||||
values["client"] = openai.OpenAI(
|
||||
**client_params, **sync_specific
|
||||
).chat.completions
|
||||
if not values.get("async_client"):
|
||||
if openai_proxy and not values["http_async_client"]:
|
||||
if values["openai_proxy"] and not values["http_async_client"]:
|
||||
try:
|
||||
import httpx
|
||||
except ImportError as e:
|
||||
@@ -448,7 +457,9 @@ class BaseChatOpenAI(BaseChatModel):
|
||||
"Could not import httpx python package. "
|
||||
"Please install it with `pip install httpx`."
|
||||
) from e
|
||||
values["http_async_client"] = httpx.AsyncClient(proxy=openai_proxy)
|
||||
values["http_async_client"] = httpx.AsyncClient(
|
||||
proxy=values["openai_proxy"]
|
||||
)
|
||||
async_specific = {"http_client": values["http_async_client"]}
|
||||
values["async_client"] = openai.AsyncOpenAI(
|
||||
**client_params, **async_specific
|
||||
|
||||
@@ -282,12 +282,44 @@ class OpenAIEmbeddings(BaseModel, Embeddings):
|
||||
"default_headers": values["default_headers"],
|
||||
"default_query": values["default_query"],
|
||||
}
|
||||
|
||||
if values["openai_proxy"] and (
|
||||
values["http_client"] or values["http_async_client"]
|
||||
):
|
||||
openai_proxy = values["openai_proxy"]
|
||||
http_client = values["http_client"]
|
||||
http_async_client = values["http_async_client"]
|
||||
raise ValueError(
|
||||
"Cannot specify 'openai_proxy' if one of "
|
||||
"'http_client'/'http_async_client' is already specified. Received:\n"
|
||||
f"{openai_proxy=}\n{http_client=}\n{http_async_client=}"
|
||||
)
|
||||
if not values.get("client"):
|
||||
if values["openai_proxy"] and not values["http_client"]:
|
||||
try:
|
||||
import httpx
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
"Could not import httpx python package. "
|
||||
"Please install it with `pip install httpx`."
|
||||
) from e
|
||||
values["http_client"] = httpx.Client(proxy=values["openai_proxy"])
|
||||
sync_specific = {"http_client": values["http_client"]}
|
||||
values["client"] = openai.OpenAI(
|
||||
**client_params, **sync_specific
|
||||
).embeddings
|
||||
if not values.get("async_client"):
|
||||
if values["openai_proxy"] and not values["http_async_client"]:
|
||||
try:
|
||||
import httpx
|
||||
except ImportError as e:
|
||||
raise ImportError(
|
||||
"Could not import httpx python package. "
|
||||
"Please install it with `pip install httpx`."
|
||||
) from e
|
||||
values["http_async_client"] = httpx.AsyncClient(
|
||||
proxy=values["openai_proxy"]
|
||||
)
|
||||
async_specific = {"http_client": values["http_async_client"]}
|
||||
values["async_client"] = openai.AsyncOpenAI(
|
||||
**client_params, **async_specific
|
||||
|
||||
@@ -88,14 +88,14 @@ class UnstructuredLoader(BaseLoader):
|
||||
# SDK parameters
|
||||
api_key: Optional[str] = None,
|
||||
client: Optional[UnstructuredClient] = None,
|
||||
server_url: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
**kwargs: Any,
|
||||
):
|
||||
"""Initialize loader."""
|
||||
if file_path is not None and file is not None:
|
||||
raise ValueError("file_path and file cannot be defined simultaneously.")
|
||||
if client is not None:
|
||||
disallowed_params = [("api_key", api_key), ("server_url", server_url)]
|
||||
disallowed_params = [("api_key", api_key), ("url", url)]
|
||||
bad_params = [
|
||||
param for param, value in disallowed_params if value is not None
|
||||
]
|
||||
@@ -106,8 +106,8 @@ class UnstructuredLoader(BaseLoader):
|
||||
f"params: {', '.join(bad_params)}."
|
||||
)
|
||||
|
||||
unstructured_api_key = api_key or os.getenv("UNSTRUCTURED_API_KEY")
|
||||
unstructured_url = server_url or os.getenv("UNSTRUCTURED_URL") or _DEFAULT_URL
|
||||
unstructured_api_key = api_key or os.getenv("UNSTRUCTURED_API_KEY") or ""
|
||||
unstructured_url = url or os.getenv("UNSTRUCTURED_URL") or _DEFAULT_URL
|
||||
|
||||
self.client = client or UnstructuredClient(
|
||||
api_key_auth=unstructured_api_key, server_url=unstructured_url
|
||||
@@ -165,7 +165,6 @@ class _SingleDocumentLoader(BaseLoader):
|
||||
file: Optional[IO[bytes]] = None,
|
||||
partition_via_api: bool = False,
|
||||
post_processors: Optional[list[Callable[[str], str]]] = None,
|
||||
# SDK parameters
|
||||
**kwargs: Any,
|
||||
):
|
||||
"""Initialize loader."""
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "langchain-unstructured"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
description = "An integration package connecting Unstructured and LangChain"
|
||||
authors = []
|
||||
readme = "README.md"
|
||||
|
||||
@@ -7,6 +7,7 @@ import pytest
|
||||
from unstructured.documents.elements import Text # type: ignore
|
||||
|
||||
from langchain_unstructured.document_loaders import (
|
||||
UnstructuredLoader,
|
||||
_SingleDocumentLoader, # type: ignore
|
||||
)
|
||||
|
||||
@@ -16,6 +17,45 @@ EXAMPLE_DOCS_DIRECTORY = str(
|
||||
)
|
||||
|
||||
|
||||
# --- UnstructuredLoader.__init__() ---
|
||||
|
||||
|
||||
def test_it_initializes_with_file_path(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.delenv("UNSTRUCTURED_API_KEY", raising=False)
|
||||
|
||||
loader = UnstructuredLoader(file_path="dummy_path")
|
||||
|
||||
assert loader.file_path == "dummy_path"
|
||||
assert loader.file is None
|
||||
assert loader.partition_via_api is False
|
||||
assert loader.post_processors is None
|
||||
assert loader.unstructured_kwargs == {}
|
||||
# A client is always created and passed to _SingleDocumentLoader, but it's not
|
||||
# used unless partition_via_api=True
|
||||
assert loader.client is not None
|
||||
assert loader.client.sdk_configuration.security.api_key_auth == "" # type: ignore
|
||||
assert (
|
||||
loader.client.sdk_configuration.server_url == "https://api.unstructuredapp.io"
|
||||
)
|
||||
|
||||
|
||||
def test_it_initializes_with_env_api_key(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setenv("UNSTRUCTURED_API_KEY", "FAKE_API_KEY")
|
||||
|
||||
loader = UnstructuredLoader(file_path="dummy_path")
|
||||
|
||||
assert loader.file_path == "dummy_path"
|
||||
assert loader.file is None
|
||||
assert loader.partition_via_api is False
|
||||
assert loader.post_processors is None
|
||||
assert loader.unstructured_kwargs == {}
|
||||
assert loader.client is not None
|
||||
assert loader.client.sdk_configuration.security.api_key_auth == "FAKE_API_KEY" # type: ignore
|
||||
assert (
|
||||
loader.client.sdk_configuration.server_url == "https://api.unstructuredapp.io"
|
||||
)
|
||||
|
||||
|
||||
# --- _SingleDocumentLoader._get_content() ---
|
||||
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ class ChatModelIntegrationTests(ChatModelTests):
|
||||
assert isinstance(chunk, Joke)
|
||||
|
||||
# Schema
|
||||
chat = model.with_structured_output(Joke.schema())
|
||||
chat = model.with_structured_output(Joke.model_json_schema())
|
||||
result = chat.invoke("Tell me a joke about cats.")
|
||||
assert isinstance(result, dict)
|
||||
assert set(result.keys()) == {"setup", "punchline"}
|
||||
|
||||
Reference in New Issue
Block a user