Compare commits
50 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0766a44ccf | |||
| 036bf3a161 | |||
| 41bd258b93 | |||
| 38e212c721 | |||
| 2f285ea00a | |||
| d38120c839 | |||
| d94aee812b | |||
| 68d650ec40 | |||
| 769d926f5a | |||
| 9478bab04e | |||
| 7ad4af250f | |||
| 9fa368b114 | |||
| 4afef04f26 | |||
| 8fe2c3effc | |||
| fa78c972be | |||
| 0e66261644 | |||
| 819650a254 | |||
| 34c41c87dc | |||
| 2985b667b0 | |||
| 31bb0e7f0f | |||
| 8f28264aec | |||
| ec4fb11aa5 | |||
| b210723de1 | |||
| 433f99dd78 | |||
| e75c05112e | |||
| d2a5b50ff8 | |||
| 120690afd4 | |||
| 344dbeee42 | |||
| 3fe3b0320a | |||
| 75896b647f | |||
| 446d0975aa | |||
| b7d365119c | |||
| 2d9fbd4e49 | |||
| 22e14b5e65 | |||
| 1a654beea4 | |||
| f50f8a444a | |||
| 3cc3a0058d | |||
| ae473b5e3c | |||
| efb7e31565 | |||
| 069d265338 | |||
| 751a3a4bd1 | |||
| cb0499407e | |||
| 9afc6878c8 | |||
| 0b5b12575a | |||
| d79d30bf0c | |||
| 59600e2a5b | |||
| e572b5a3dc | |||
| 5b46daaee4 | |||
| 2784bae772 | |||
| 325e11f0de |
@@ -32,9 +32,6 @@
|
||||
|
||||
<hr />
|
||||
|
||||
|
||||
> ### Checkout our latest [Sadhguru AI app](https://sadhguru-ai.streamlit.app/) built using Embedchain.
|
||||
|
||||
## What is Embedchain?
|
||||
|
||||
Embedchain is an Open Source RAG Framework that makes it easy to create and deploy AI apps. At its core, Embedchain follows the design principle of being *"Conventional but Configurable"* to serve both software engineers and machine learning engineers.
|
||||
@@ -64,7 +61,7 @@ For example, you can create an Elon Musk bot using the following code:
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# Create a bot instance
|
||||
os.environ["OPENAI_API_KEY"] = "YOUR API KEY"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Card title="Talk to founders" icon="calendar" href="https://cal.com/taranjeetio/ec">
|
||||
Schedule a call
|
||||
</Card>
|
||||
<Card title="Slack" icon="slack" href="https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw" color="#4A154B">
|
||||
<Card title="Slack" icon="slack" href="https://embedchain.ai/slack" color="#4A154B">
|
||||
Join our slack community
|
||||
</Card>
|
||||
<Card title="Discord" icon="discord" href="https://discord.gg/6PzXDgEjG5" color="#7289DA">
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<Card title="Google Form" icon="file" href="https://forms.gle/NDRCKsRpUHsz2Wcm8" color="#7387d0">
|
||||
Fill out this form
|
||||
</Card>
|
||||
<Card title="Slack" icon="slack" href="https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw" color="#4A154B">
|
||||
<Card title="Slack" icon="slack" href="https://embedchain.ai/slack" color="#4A154B">
|
||||
Let us know on our slack community
|
||||
</Card>
|
||||
<Card title="Discord" icon="discord" href="https://discord.gg/6PzXDgEjG5" color="#7289DA">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<p>If you can't find the specific LLM you need, no need to fret. We're continuously expanding our support for additional LLMs, and you can help us prioritize by opening an issue on our GitHub or simply reaching out to us on our Slack or Discord community.</p>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Slack" icon="slack" href="https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw" color="#4A154B">
|
||||
<Card title="Slack" icon="slack" href="https://embedchain.ai/slack" color="#4A154B">
|
||||
Let us know on our slack community
|
||||
</Card>
|
||||
<Card title="Discord" icon="discord" href="https://discord.gg/6PzXDgEjG5" color="#7289DA">
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<p>If you can't find the specific vector database, please feel free to request through one of the following channels and help us prioritize.</p>
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Slack" icon="slack" href="https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw" color="#4A154B">
|
||||
<Card title="Slack" icon="slack" href="https://embedchain.ai/slack" color="#4A154B">
|
||||
Let us know on our slack community
|
||||
</Card>
|
||||
<Card title="Discord" icon="discord" href="https://discord.gg/6PzXDgEjG5" color="#7289DA">
|
||||
|
||||
@@ -8,7 +8,7 @@ You can configure different components of your app (`llm`, `embedding model`, or
|
||||
|
||||
|
||||
<Tip>
|
||||
Embedchain applications are configurable using YAML file, JSON file or by directly passing the config dictionary. Checkout the [docs here](/api-reference/pipeline/overview#usage) on how to use other formats.
|
||||
Embedchain applications are configurable using YAML file, JSON file or by directly passing the config dictionary. Checkout the [docs here](/api-reference/app/overview#usage) on how to use other formats.
|
||||
</Tip>
|
||||
|
||||
<CodeGroup>
|
||||
@@ -200,9 +200,10 @@ Alright, let's dive into what each key means in the yaml config above:
|
||||
- `stream` (Boolean): Controls if the response is streamed back to the user (set to false).
|
||||
- `prompt` (String): A prompt for the model to follow when generating responses, requires `$context` and `$query` variables.
|
||||
- `system_prompt` (String): A system prompt for the model to follow when generating responses, in this case, it's set to the style of William Shakespeare.
|
||||
- `stream` (Boolean): Controls if the response is streamed back to the user (set to false).
|
||||
- `stream` (Boolean): Controls if the response is streamed back to the user (set to false).
|
||||
- `number_documents` (Integer): Number of documents to pull from the vectordb as context, defaults to 1
|
||||
- `api_key` (String): The API key for the language model.
|
||||
- `model_kwargs` (Dict): Keyword arguments to pass to the language model. Used for `aws_bedrock` provider, since it requires different arguments for each model.
|
||||
3. `vectordb` Section:
|
||||
- `provider` (String): The provider for the vector database, set to 'chroma'. You can find the full list of vector database providers in [our docs](/components/vector-databases).
|
||||
- `config`:
|
||||
@@ -214,7 +215,11 @@ Alright, let's dive into what each key means in the yaml config above:
|
||||
- `provider` (String): The provider for the embedder, set to 'openai'. You can find the full list of embedding model providers in [our docs](/components/embedding-models).
|
||||
- `config`:
|
||||
- `model` (String): The specific model used for text embedding, 'text-embedding-ada-002'.
|
||||
- `vector_dimension` (Integer): The vector dimension of the embedding model. [Defaults](https://github.com/embedchain/embedchain/blob/e572b5a3dc1b66f1e9b3357d11a88c63b5ce06e3/embedchain/models/vector_dimensions.py)
|
||||
- `api_key` (String): The API key for the embedding model.
|
||||
- `deployment_name` (String): The deployment name for the embedding model.
|
||||
- `title` (String): The title for the embedding model for Google Embedder.
|
||||
- `task_type` (String): The task type for the embedding model for Google Embedder.
|
||||
5. `chunker` Section:
|
||||
- `chunk_size` (Integer): The size of each chunk of text that is sent to the language model.
|
||||
- `chunk_overlap` (Integer): The amount of overlap between each chunk of text.
|
||||
|
||||
@@ -129,3 +129,18 @@ app.chat("What is the net worth of Bill Gates?", session_id="user2")
|
||||
app.chat("What was my last question", session_id="user1")
|
||||
# 'Your last question was "What is the net worth of Elon Musk?"'
|
||||
```
|
||||
|
||||
### With custom context window
|
||||
|
||||
If you want to customize the context window that you want to use during chat (default context window is 3 document chunks), you can do using the following code snippet:
|
||||
|
||||
```python with custom chunks size
|
||||
from embedchain import App
|
||||
from embedchain.config import BaseLlmConfig
|
||||
|
||||
app = App()
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
|
||||
query_config = BaseLlmConfig(number_documents=5)
|
||||
app.chat("What is the net worth of Elon Musk?", config=query_config)
|
||||
```
|
||||
|
||||
@@ -2,9 +2,33 @@
|
||||
title: 🗑 delete
|
||||
---
|
||||
|
||||
## Delete Document
|
||||
|
||||
`delete()` method allows you to delete a document previously added to the app.
|
||||
|
||||
### Usage
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
forbes_doc_id = app.add("https://www.forbes.com/profile/elon-musk")
|
||||
wiki_doc_id = app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
|
||||
app.delete(forbes_doc_id) # deletes the forbes document
|
||||
```
|
||||
|
||||
<Note>
|
||||
If you do not have the document id, you can use `app.db.get()` method to get the document and extract the `hash` key from `metadatas` dictionary object, which serves as the document id.
|
||||
</Note>
|
||||
|
||||
|
||||
## Delete Chat Session History
|
||||
|
||||
`delete_session_chat_history()` method allows you to delete all previous messages in a chat history.
|
||||
|
||||
## Usage
|
||||
### Usage
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
@@ -16,4 +40,9 @@ app.add("https://www.forbes.com/profile/elon-musk")
|
||||
app.chat("What is the net worth of Elon Musk?")
|
||||
|
||||
app.delete_session_chat_history()
|
||||
```
|
||||
```
|
||||
|
||||
<Note>
|
||||
`delete_session_chat_history(session_id="session_1")` method also accepts `session_id` optional param for deleting chat history of a specific session.
|
||||
It assumes the default session if no `session_id` is provided.
|
||||
</Note>
|
||||
@@ -2,30 +2,4 @@
|
||||
title: 🚀 deploy
|
||||
---
|
||||
|
||||
Using the `deploy()` method, Embedchain allows developers to easily launch their LLM-powered applications on the [Embedchain Platform](https://app.embedchain.ai). This platform facilitates seamless access to your data's context via a free and user-friendly REST API. Once your pipeline is deployed, you can update your data sources at any time.
|
||||
|
||||
The `deploy()` method not only deploys your pipeline but also efficiently manages LLMs, vector databases, embedding models, and data syncing, enabling you to focus on querying, chatting, or searching without the hassle of infrastructure management.
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
|
||||
# Add data source
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
|
||||
# Deploy your pipeline to Embedchain Platform
|
||||
app.deploy()
|
||||
|
||||
# 🔑 Enter your Embedchain API key. You can find the API key at https://app.embedchain.ai/settings/keys/
|
||||
# ec-xxxxxx
|
||||
|
||||
# 🛠️ Creating pipeline on the platform...
|
||||
# 🎉🎉🎉 Pipeline created successfully! View your pipeline: https://app.embedchain.ai/pipelines/xxxxx
|
||||
|
||||
# 🛠️ Adding data to your pipeline...
|
||||
# ✅ Data of type: web_page, value: https://www.forbes.com/profile/elon-musk added successfully.
|
||||
```
|
||||
The `deploy()` method is currently available on an invitation-only basis. To request access, please submit your information via the provided [Google Form](https://forms.gle/vigN11h7b4Ywat668). We will review your request and respond promptly.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: 📄 get
|
||||
---
|
||||
|
||||
## Get data sources
|
||||
|
||||
`get_data_sources()` returns a list of all the data sources added in the app.
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
|
||||
data_sources = app.get_data_sources()
|
||||
# [
|
||||
# {
|
||||
# 'data_type': 'web_page',
|
||||
# 'data_value': 'https://en.wikipedia.org/wiki/Elon_Musk',
|
||||
# 'metadata': 'null'
|
||||
# },
|
||||
# {
|
||||
# 'data_type': 'web_page',
|
||||
# 'data_value': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'metadata': 'null'
|
||||
# }
|
||||
# ]
|
||||
```
|
||||
@@ -12,6 +12,13 @@ title: '🔍 search'
|
||||
<ParamField path="num_documents" type="int" optional>
|
||||
Number of relevant documents to fetch. Defaults to `3`
|
||||
</ParamField>
|
||||
<ParamField path="where" type="dict" optional>
|
||||
Key value pair for metadata filtering.
|
||||
</ParamField>
|
||||
<ParamField path="raw_filter" type="dict" optional>
|
||||
Pass raw filter query based on your vector database.
|
||||
Currently, `raw_filter` param is only supported for Pinecone vector database.
|
||||
</ParamField>
|
||||
|
||||
### Returns
|
||||
|
||||
@@ -21,37 +28,84 @@ title: '🔍 search'
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic
|
||||
|
||||
Refer to the following example on how to use the search api:
|
||||
|
||||
```python Code example
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
|
||||
# Add data source
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
|
||||
# Get relevant context using semantic search
|
||||
context = app.search("What is the net worth of Elon?", num_documents=2)
|
||||
print(context)
|
||||
# Context:
|
||||
# [
|
||||
# {
|
||||
# 'context': 'Elon Musk PROFILEElon MuskCEO, Tesla$221.9BReal Time Net Worth ...',
|
||||
# 'metadata': {
|
||||
# 'source': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'document_id': 'some_document_id',
|
||||
# 'score': 0.404,
|
||||
# }
|
||||
# },
|
||||
# {
|
||||
# 'context': 'company, which is now called X.Wealth HistoryHOVER TO REVEAL NET WORTH ...',
|
||||
# 'metadata': {
|
||||
# 'source': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'document_id': 'some_document_id',
|
||||
# 'score': 0.435,
|
||||
# }
|
||||
# }
|
||||
# ]
|
||||
```
|
||||
|
||||
### Advanced
|
||||
|
||||
#### Metadata filtering using `where` params
|
||||
|
||||
Here is an advanced example of `search()` API with metadata filtering on pinecone database:
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
from embedchain import App
|
||||
|
||||
os.environ["PINECONE_API_KEY"] = "xxx"
|
||||
|
||||
config = {
|
||||
"vectordb": {
|
||||
"provider": "pinecone",
|
||||
"config": {
|
||||
"metric": "dotproduct",
|
||||
"vector_dimension": 1536,
|
||||
"index_name": "ec-test",
|
||||
"serverless_config": {"cloud": "aws", "region": "us-west-2"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
app = App.from_config(config=config)
|
||||
|
||||
app.add("https://www.forbes.com/profile/bill-gates", metadata={"type": "forbes", "person": "gates"})
|
||||
app.add("https://en.wikipedia.org/wiki/Bill_Gates", metadata={"type": "wiki", "person": "gates"})
|
||||
|
||||
results = app.search("What is the net worth of Bill Gates?", where={"person": "gates"})
|
||||
print("Num of search results: ", len(results))
|
||||
```
|
||||
|
||||
#### Metadata filtering using `raw_filter` params
|
||||
|
||||
Following is an example of metadata filtering by passing the raw filter query that pinecone vector database follows:
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
from embedchain import App
|
||||
|
||||
os.environ["PINECONE_API_KEY"] = "xxx"
|
||||
|
||||
config = {
|
||||
"vectordb": {
|
||||
"provider": "pinecone",
|
||||
"config": {
|
||||
"metric": "dotproduct",
|
||||
"vector_dimension": 1536,
|
||||
"index_name": "ec-test",
|
||||
"serverless_config": {"cloud": "aws", "region": "us-west-2"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
app = App.from_config(config=config)
|
||||
|
||||
app.add("https://www.forbes.com/profile/bill-gates", metadata={"year": 2022, "person": "gates"})
|
||||
app.add("https://en.wikipedia.org/wiki/Bill_Gates", metadata={"year": 2024, "person": "gates"})
|
||||
|
||||
print("Filter with person: gates and year > 2023")
|
||||
raw_filter = {"$and": [{"person": "gates"}, {"year": {"$gt": 2023}}]}
|
||||
results = app.search("What is the net worth of Bill Gates?", raw_filter=raw_filter)
|
||||
print("Num of search results: ", len(results))
|
||||
```
|
||||
|
||||
@@ -8,7 +8,7 @@ We believe in building a vibrant and supportive community around embedchain. The
|
||||
<Card title="Twitter" icon="twitter" href="https://twitter.com/embedchain">
|
||||
Follow us on Twitter
|
||||
</Card>
|
||||
<Card title="Slack" icon="slack" href="https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw" color="#4A154B">
|
||||
<Card title="Slack" icon="slack" href="https://embedchain.ai/slack" color="#4A154B">
|
||||
Join our slack community
|
||||
</Card>
|
||||
<Card title="Discord" icon="discord" href="https://discord.gg/6PzXDgEjG5" color="#7289DA">
|
||||
|
||||
@@ -7,11 +7,12 @@ When we say "custom", we mean that you can customize the loader and chunker to y
|
||||
```python
|
||||
from embedchain import App
|
||||
import your_loader
|
||||
import your_chunker
|
||||
from my_module import CustomLoader
|
||||
from my_module import CustomChunker
|
||||
|
||||
app = App()
|
||||
loader = your_loader()
|
||||
chunker = your_chunker()
|
||||
loader = CustomLoader()
|
||||
chunker = CustomChunker()
|
||||
|
||||
app.add("source", data_type="custom", loader=loader, chunker=chunker)
|
||||
```
|
||||
|
||||
@@ -22,7 +22,7 @@ Following is an example of how to use the dropbox loader:
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["DROPBOX_ACCESS_TOKEN"] = "sl.xxx"
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
|
||||
@@ -19,7 +19,7 @@ The first time you use the loader, you will be prompted to enter your Google acc
|
||||
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -4,13 +4,6 @@ title: '📰 PDF'
|
||||
|
||||
You can load any pdf file from your local file system or through a URL.
|
||||
|
||||
## Setup
|
||||
Install the following packages for loading youtube videos which help in transcription.
|
||||
|
||||
```bash
|
||||
pip install pytube youtube-transcript-api
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Load from a local file
|
||||
@@ -29,7 +22,7 @@ app = App()
|
||||
app.add('https://arxiv.org/pdf/1706.03762.pdf', data_type='pdf_file')
|
||||
app.query("What is the paper 'attention is all you need' about?", citations=True)
|
||||
# Answer: The paper "Attention Is All You Need" proposes a new network architecture called the Transformer, which is based solely on attention mechanisms. It suggests that complex recurrent or convolutional neural networks can be replaced with a simpler architecture that connects the encoder and decoder through attention. The paper discusses how this approach can improve sequence transduction models, such as neural machine translation.
|
||||
# Contexts:
|
||||
# Contexts:
|
||||
# [
|
||||
# (
|
||||
# 'Provided proper attribution is ...',
|
||||
|
||||
@@ -2,15 +2,17 @@
|
||||
title: '📽️ Youtube Channel'
|
||||
---
|
||||
|
||||
To add all the videos from a youtube channel to your app, use the data_type as `youtube_channel`.
|
||||
## Setup
|
||||
|
||||
<Note>
|
||||
Make sure you have all the required packages installed before using this data type. You can install them by running the following command in your terminal.
|
||||
|
||||
```bash
|
||||
pip install -u "embedchain[youtube]"
|
||||
pip install -U "embedchain[youtube]"
|
||||
```
|
||||
</Note>
|
||||
|
||||
## Usage
|
||||
|
||||
To add all the videos from a youtube channel to your app, use the data_type as `youtube_channel`.
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
title: '📺 Youtube Video'
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure you have all the required packages installed before using this data type. You can install them by running the following command in your terminal.
|
||||
|
||||
```bash
|
||||
pip install -U "embedchain[youtube]"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
To add any youtube video to your app, use the data_type as `youtube_video`. Eg:
|
||||
|
||||
```python
|
||||
|
||||
@@ -40,7 +40,27 @@ app.query("What is OpenAI?")
|
||||
embedder:
|
||||
provider: openai
|
||||
config:
|
||||
model: 'text-embedding-ada-002'
|
||||
model: 'text-embedding-3-small'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
* OpenAI announced two new embedding models: `text-embedding-3-small` and `text-embedding-3-large`. Embedchain supports both these models. Below you can find YAML config for both:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```yaml text-embedding-3-small.yaml
|
||||
embedder:
|
||||
provider: openai
|
||||
config:
|
||||
model: 'text-embedding-3-small'
|
||||
```
|
||||
|
||||
```yaml text-embedding-3-large.yaml
|
||||
embedder:
|
||||
provider: openai
|
||||
config:
|
||||
model: 'text-embedding-3-large'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
+137
-104
@@ -20,6 +20,8 @@ Embedchain comes with built-in support for various popular large language models
|
||||
<Card title="Hugging Face" href="#hugging-face"></Card>
|
||||
<Card title="Llama2" href="#llama2"></Card>
|
||||
<Card title="Vertex AI" href="#vertex-ai"></Card>
|
||||
<Card title="Mistral AI" href="#mistral-ai"></Card>
|
||||
<Card title="AWS Bedrock" href="#aws-bedrock"></Card>
|
||||
</CardGroup>
|
||||
|
||||
## OpenAI
|
||||
@@ -66,125 +68,75 @@ llm:
|
||||
</CodeGroup>
|
||||
|
||||
### Function Calling
|
||||
To enable [function calling](https://platform.openai.com/docs/guides/function-calling) in your application using embedchain and OpenAI, you need to pass functions into `OpenAILlm` class as an array of functions. Here are several ways in which you can achieve that:
|
||||
Embedchain supports OpenAI [Function calling](https://platform.openai.com/docs/guides/function-calling) with a single function. It accepts inputs in accordance with the [Langchain interface](https://python.langchain.com/docs/modules/model_io/chat/function_calling#legacy-args-functions-and-function_call).
|
||||
|
||||
Examples:
|
||||
<Accordion title="Using Pydantic Models">
|
||||
<Accordion title="Pydantic Model">
|
||||
```python
|
||||
import os
|
||||
from embedchain import App
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
import requests
|
||||
from pydantic import BaseModel, Field, ValidationError, field_validator
|
||||
from pydantic import BaseModel
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
class multiply(BaseModel):
|
||||
"""Multiply two integers together."""
|
||||
|
||||
class QA(BaseModel):
|
||||
"""
|
||||
A question and answer pair.
|
||||
"""
|
||||
|
||||
question: str = Field(
|
||||
..., description="The question.", example="What is a mountain?"
|
||||
)
|
||||
answer: str = Field(
|
||||
..., description="The answer.", example="A mountain is a hill."
|
||||
)
|
||||
person_who_is_asking: str = Field(
|
||||
..., description="The person who is asking the question.", example="John"
|
||||
)
|
||||
|
||||
@field_validator("question")
|
||||
def question_must_end_with_a_question_mark(cls, v):
|
||||
"""
|
||||
Validate that the question ends with a question mark.
|
||||
"""
|
||||
if not v.endswith("?"):
|
||||
raise ValueError("question must end with a question mark")
|
||||
return v
|
||||
|
||||
@field_validator("answer")
|
||||
def answer_must_end_with_a_period(cls, v):
|
||||
"""
|
||||
Validate that the answer ends with a period.
|
||||
"""
|
||||
if not v.endswith("."):
|
||||
raise ValueError("answer must end with a period")
|
||||
return v
|
||||
|
||||
llm = OpenAILlm(config=None,functions=[QA])
|
||||
app = App(llm=llm)
|
||||
|
||||
result = app.query("Hey I am Sid. What is a mountain? A mountain is a hill.")
|
||||
|
||||
print(result)
|
||||
a: int = Field(..., description="First integer")
|
||||
b: int = Field(..., description="Second integer")
|
||||
```
|
||||
</Accordion>
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Using OpenAI JSON schema">
|
||||
<Accordion title="Python function">
|
||||
```python
|
||||
def multiply(a: int, b: int) -> int:
|
||||
"""Multiply two integers together.
|
||||
|
||||
Args:
|
||||
a: First integer
|
||||
b: Second integer
|
||||
"""
|
||||
return a * b
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="OpenAI tool dictionary">
|
||||
```python
|
||||
multiply = {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": "multiply",
|
||||
"description": "Multiply two integers together.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"a": {
|
||||
"description": "First integer",
|
||||
"type": "integer"
|
||||
},
|
||||
"b": {
|
||||
"description": "Second integer",
|
||||
"type": "integer"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"a",
|
||||
"b"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
With any of the previous inputs, the OpenAI LLM can be queried to provide the appropriate arguments for the function.
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import App
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
import requests
|
||||
from pydantic import BaseModel, Field, ValidationError, field_validator
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
|
||||
json_schema = {
|
||||
"name": "get_qa",
|
||||
"description": "A question and answer pair and the user who is asking the question.",
|
||||
"parameters": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"question": {"type": "string", "description": "The question."},
|
||||
"answer": {"type": "string", "description": "The answer."},
|
||||
"person_who_is_asking": {
|
||||
"type": "string",
|
||||
"description": "The person who is asking the question.",
|
||||
}
|
||||
},
|
||||
"required": ["question", "answer", "person_who_is_asking"],
|
||||
},
|
||||
}
|
||||
|
||||
llm = OpenAILlm(config=None,functions=[json_schema])
|
||||
llm = OpenAILlm(tools=multiply)
|
||||
app = App(llm=llm)
|
||||
|
||||
result = app.query("Hey I am Sid. What is a mountain? A mountain is a hill.")
|
||||
|
||||
print(result)
|
||||
```
|
||||
</Accordion>
|
||||
<Accordion title="Using actual python functions">
|
||||
```python
|
||||
import os
|
||||
from embedchain import App
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
import requests
|
||||
from pydantic import BaseModel, Field, ValidationError, field_validator
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
|
||||
def find_info_of_pokemon(pokemon: str):
|
||||
"""
|
||||
Find the information of the given pokemon.
|
||||
Args:
|
||||
pokemon: The pokemon.
|
||||
"""
|
||||
req = requests.get(f"https://pokeapi.co/api/v2/pokemon/{pokemon}")
|
||||
if req.status_code == 404:
|
||||
raise ValueError("pokemon not found")
|
||||
return req.json()
|
||||
|
||||
llm = OpenAILlm(config=None,functions=[find_info_of_pokemon])
|
||||
app = App(llm=llm)
|
||||
|
||||
result = app.query("Tell me more about the pokemon pikachu.")
|
||||
|
||||
print(result)
|
||||
result = app.query("What is the result of 125 multiplied by fifteen?")
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
## Google AI
|
||||
|
||||
@@ -250,7 +202,7 @@ app = App.from_config(config_path="config.yaml")
|
||||
llm:
|
||||
provider: azure_openai
|
||||
config:
|
||||
model: gpt-35-turbo
|
||||
model: gpt-3.5-turbo
|
||||
deployment_name: your_llm_deployment_name
|
||||
temperature: 0.5
|
||||
max_tokens: 1000
|
||||
@@ -620,5 +572,86 @@ llm:
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
## Mistral AI
|
||||
|
||||
Obtain the Mistral AI api key from their [console](https://console.mistral.ai/).
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
os.environ["MISTRAL_API_KEY"] = "xxx"
|
||||
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
|
||||
response = app.query("what is the net worth of Elon Musk?")
|
||||
# As of January 16, 2024, Elon Musk's net worth is $225.4 billion.
|
||||
|
||||
response = app.chat("which companies does elon own?")
|
||||
# Elon Musk owns Tesla, SpaceX, Boring Company, Twitter, and X.
|
||||
|
||||
response = app.chat("what question did I ask you already?")
|
||||
# You have asked me several times already which companies Elon Musk owns, specifically Tesla, SpaceX, Boring Company, Twitter, and X.
|
||||
```
|
||||
|
||||
```yaml config.yaml
|
||||
llm:
|
||||
provider: mistralai
|
||||
config:
|
||||
model: mistral-tiny
|
||||
temperature: 0.5
|
||||
max_tokens: 1000
|
||||
top_p: 1
|
||||
embedder:
|
||||
provider: mistralai
|
||||
config:
|
||||
model: mistral-embed
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
## AWS Bedrock
|
||||
|
||||
### Setup
|
||||
- Before using the AWS Bedrock LLM, make sure you have the appropriate model access from [Bedrock Console](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/modelaccess).
|
||||
- You will also need to authenticate the `boto3` client by using a method in the [AWS documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials)
|
||||
- You can optionally export an `AWS_REGION`
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import App
|
||||
|
||||
os.environ["AWS_ACCESS_KEY_ID"] = "xxx"
|
||||
os.environ["AWS_SECRET_ACCESS_KEY"] = "xxx"
|
||||
os.environ["AWS_REGION"] = "us-west-2"
|
||||
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
```
|
||||
|
||||
```yaml config.yaml
|
||||
llm:
|
||||
provider: aws_bedrock
|
||||
config:
|
||||
model: amazon.titan-text-express-v1
|
||||
# check notes below for model_kwargs
|
||||
model_kwargs:
|
||||
temperature: 0.5
|
||||
topP: 1
|
||||
maxTokenCount: 1000
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<br />
|
||||
<Note>
|
||||
The model arguments are different for each providers. Please refer to the [AWS Bedrock Documentation](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/providers) to find the appropriate arguments for your model.
|
||||
</Note>
|
||||
|
||||
<br/ >
|
||||
<Snippet file="missing-llm-tip.mdx" />
|
||||
|
||||
@@ -167,7 +167,7 @@ Install pinecone related dependencies using the following command:
|
||||
pip install --upgrade 'embedchain[pinecone]'
|
||||
```
|
||||
|
||||
In order to use Pinecone as vector database, set the environment variables `PINECONE_API_KEY` and `PINECONE_ENV` which you can find on [Pinecone dashboard](https://app.pinecone.io/).
|
||||
In order to use Pinecone as vector database, set the environment variable `PINECONE_API_KEY` which you can find on [Pinecone dashboard](https://app.pinecone.io/).
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
@@ -175,20 +175,46 @@ In order to use Pinecone as vector database, set the environment variables `PINE
|
||||
from embedchain import App
|
||||
|
||||
# load pinecone configuration from yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
app = App.from_config(config_path="pod_config.yaml")
|
||||
# or
|
||||
app = App.from_config(config_path="serverless_config.yaml")
|
||||
```
|
||||
|
||||
```yaml config.yaml
|
||||
```yaml pod_config.yaml
|
||||
vectordb:
|
||||
provider: pinecone
|
||||
config:
|
||||
metric: cosine
|
||||
vector_dimension: 1536
|
||||
collection_name: my-pinecone-index
|
||||
index_name: my-pinecone-index
|
||||
pod_config:
|
||||
environment: gcp-starter
|
||||
metadata_config:
|
||||
indexed:
|
||||
- "url"
|
||||
- "hash"
|
||||
```
|
||||
|
||||
```yaml serverless_config.yaml
|
||||
vectordb:
|
||||
provider: pinecone
|
||||
config:
|
||||
metric: cosine
|
||||
vector_dimension: 1536
|
||||
index_name: my-pinecone-index
|
||||
serverless_config:
|
||||
cloud: aws
|
||||
region: us-west-2
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<br />
|
||||
<Note>
|
||||
You can find more information about Pinecone configuration [here](https://docs.pinecone.io/docs/manage-indexes#create-a-pod-based-index).
|
||||
You can also optionally provide `index_name` as a config param in yaml file to specify the index name. If not provided, the index name will be `{collection_name}-{vector_dimension}`.
|
||||
</Note>
|
||||
|
||||
## Qdrant
|
||||
|
||||
In order to use Qdrant as a vector database, set the environment variables `QDRANT_URL` and `QDRANT_API_KEY` which you can find on [Qdrant Dashboard](https://cloud.qdrant.io/).
|
||||
|
||||
@@ -7,29 +7,8 @@ description: 'Deploy your RAG application to embedchain.ai platform'
|
||||
|
||||
Embedchain enables developers to deploy their LLM-powered apps in production using the [Embedchain platform](https://app.embedchain.ai). The platform offers free access to context on your data through its REST API. Once the pipeline is deployed, you can update your data sources anytime after deployment.
|
||||
|
||||
See the example below on how to use the deploy your app (for free):
|
||||
Deployment to Embedchain Platform is currently available on an invitation-only basis. To request access, please submit your information via the provided [Google Form](https://forms.gle/vigN11h7b4Ywat668). We will review your request and respond promptly.
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
|
||||
# Add data source
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
|
||||
# Deploy your pipeline to Embedchain Platform
|
||||
app.deploy()
|
||||
|
||||
# 🔑 Enter your Embedchain API key. You can find the API key at https://app.embedchain.ai/settings/keys/
|
||||
# ec-xxxxxx
|
||||
|
||||
# 🛠️ Creating pipeline on the platform...
|
||||
# 🎉🎉🎉 Pipeline created successfully! View your pipeline: https://app.embedchain.ai/pipelines/xxxxx
|
||||
|
||||
# 🛠️ Adding data to your pipeline...
|
||||
# ✅ Data of type: web_page, value: https://www.forbes.com/profile/elon-musk added successfully.
|
||||
```
|
||||
|
||||
## Seeking help?
|
||||
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
title: 'Railway.app'
|
||||
description: 'Deploy your RAG application to railway.app'
|
||||
---
|
||||
|
||||
It's easy to host your Embedchain-powered apps and APIs on railway.
|
||||
|
||||
Follow the instructions given below to deploy your first application quickly:
|
||||
|
||||
## Step-1: Create RAG app
|
||||
|
||||
```bash Install embedchain
|
||||
pip install embedchain
|
||||
```
|
||||
|
||||
<Tip>
|
||||
**Create a full stack app using Embedchain CLI**
|
||||
|
||||
To use your hosted embedchain RAG app, you can easily set up a FastAPI server that can be used anywhere.
|
||||
To easily set up a FastAPI server, check out [Get started with Full stack](https://docs.embedchain.ai/get-started/full-stack) page.
|
||||
|
||||
Hosting this server on railway is super easy!
|
||||
|
||||
</Tip>
|
||||
|
||||
## Step-2: Set up your project
|
||||
|
||||
### With Docker
|
||||
|
||||
You can create a `Dockerfile` in the root of the project, with all the instructions. However, this method is sometimes slower in deployment.
|
||||
|
||||
### Without Docker
|
||||
|
||||
By default, Railway uses Python 3.7. Embedchain requires the python version to be >3.9 in order to install.
|
||||
|
||||
To fix this, create a `.python-version` file in the root directory of your project and specify the correct version
|
||||
|
||||
```bash .python-version
|
||||
3.10
|
||||
```
|
||||
|
||||
You also need to create a `requirements.txt` file to specify the requirements.
|
||||
|
||||
```bash requirements.txt
|
||||
python-dotenv
|
||||
embedchain
|
||||
fastapi==0.108.0
|
||||
uvicorn==0.25.0
|
||||
embedchain
|
||||
beautifulsoup4
|
||||
sentence-transformers
|
||||
```
|
||||
|
||||
## Step-3: Deploy to Railway 🚀
|
||||
|
||||
1. Go to https://railway.app and create an account.
|
||||
2. Create a project by clicking on the "Start a new project" button
|
||||
|
||||
### With Github
|
||||
|
||||
Select `Empty Project` or `Deploy from Github Repo`.
|
||||
|
||||
You should be all set!
|
||||
|
||||
### Without Github
|
||||
|
||||
You can also use the railway CLI to deploy your apps from the terminal, if you don't want to connect a git repository.
|
||||
|
||||
To do this, just run this command in your terminal
|
||||
|
||||
```bash Install and set up railway CLI
|
||||
npm i -g @railway/cli
|
||||
railway login
|
||||
railway link [projectID]
|
||||
```
|
||||
|
||||
Finally, run `railway up` to deploy your app.
|
||||
```bash Deploy
|
||||
railway up
|
||||
```
|
||||
|
||||
## Seeking help?
|
||||
|
||||
If you run into issues with deployment, please feel free to reach out to us via any of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -20,7 +20,7 @@ Embedchain community has been super active in creating demos on top of Embedchai
|
||||
- [Create Instant ChatBot 🤖 using embedchain](https://databutton.com/v/h3e680h9) by Avra, ([Tweet](https://twitter.com/Avra_b/status/1674704745154641920/))
|
||||
- [JOBO 🤖 — The AI-driven sidekick to craft your resume](https://try-jobo.com/) by Enrico Willemse, ([LinkedIn Post](https://www.linkedin.com/posts/enrico-willemse_jobai-gptfun-embedchain-activity-7090340080879374336-ueLB/))
|
||||
- [Explore Your Knowledge Base: Interactive chats over various forms of documents](https://chatdocs.dkedar.com/) by Kedar Dabhadkar, ([LinkedIn Post](https://www.linkedin.com/posts/dkedar7_machinelearning-llmops-activity-7092524836639424513-2O3L/))
|
||||
- [Chatbot trained on 1000+ videos of Ester hicks the co-author behind the famous book Secret](https://ask-abraham.thoughtseed.repl.co) by Mohan Kumar
|
||||
- [Chatbot trained on 1000+ videos of Ester hicks the co-author behind the famous book Secret](https://askabraham.tokenofme.io/) by Mohan Kumar
|
||||
|
||||
|
||||
## Templates
|
||||
|
||||
@@ -9,6 +9,7 @@ After successfully setting up and testing your RAG app locally, the next step is
|
||||
<Card title="Fly.io" href="/deployment/fly_io"></Card>
|
||||
<Card title="Modal.com" href="/deployment/modal_com"></Card>
|
||||
<Card title="Render.com" href="/deployment/render_com"></Card>
|
||||
<Card title="Railway.app" href="/deployment/railway"></Card>
|
||||
<Card title="Streamlit.io" href="/deployment/streamlit_io"></Card>
|
||||
<Card title="Gradio.app" href="/deployment/gradio_app"></Card>
|
||||
<Card title="Huggingface.co" href="/deployment/huggingface_spaces"></Card>
|
||||
|
||||
@@ -8,6 +8,9 @@ Get started with full-stack RAG applications using Embedchain's easy-to-use CLI
|
||||
|
||||
Choose your setup method:
|
||||
|
||||
* [Without docker](#without-docker)
|
||||
* [With Docker](#with-docker)
|
||||
|
||||
### Without Docker
|
||||
|
||||
Ensure these are installed:
|
||||
@@ -21,6 +24,14 @@ Install Docker from [Docker's official website](https://docs.docker.com/engine/i
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
### Install the package
|
||||
|
||||
Before proceeding, make sure you have the Embedchain package installed.
|
||||
|
||||
```bash
|
||||
pip install embedchain -U
|
||||
```
|
||||
|
||||
### Setting Up
|
||||
|
||||
For the purpose of the demo, you have to set `OPENAI_API_KEY` to start with but you can choose any llm by changing the configuration easily.
|
||||
@@ -60,3 +71,11 @@ Open http://localhost:3000 to view the chat UI.
|
||||
Check out the Embedchain admin panel to see the document chunks for your RAG application.
|
||||
|
||||

|
||||
|
||||
### API Server
|
||||
|
||||
If you want to access the API server, you can do so at http://localhost:8000/docs.
|
||||
|
||||

|
||||
|
||||
You can customize the UI and code as per your requirements.
|
||||
|
||||
@@ -47,7 +47,7 @@ app.query("What is the net worth of Elon Musk today?")
|
||||
llm:
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'mistralai/Mistral-7B-v0.1'
|
||||
model: 'mistralai/Mistral-7B-Instruct-v0.2'
|
||||
top_p: 0.5
|
||||
embedder:
|
||||
provider: huggingface
|
||||
@@ -80,4 +80,4 @@ Now that you have created your first app, you can follow any of the links:
|
||||
* [Introduction](/get-started/introduction)
|
||||
* [Customization](/components/introduction)
|
||||
* [Use cases](/use-cases/introduction)
|
||||
* [Deployment](/get-started/deployment)
|
||||
* [Deployment](/get-started/deployment)
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 262 KiB |
+13
-11
@@ -142,6 +142,7 @@
|
||||
"deployment/fly_io",
|
||||
"deployment/modal_com",
|
||||
"deployment/render_com",
|
||||
"deployment/railway",
|
||||
"deployment/streamlit_io",
|
||||
"deployment/gradio_app",
|
||||
"deployment/huggingface_spaces",
|
||||
@@ -199,18 +200,19 @@
|
||||
{
|
||||
"group": "API Reference",
|
||||
"pages": [
|
||||
"api-reference/pipeline/overview",
|
||||
"api-reference/app/overview",
|
||||
{
|
||||
"group": "Pipeline methods",
|
||||
"group": "App methods",
|
||||
"pages": [
|
||||
"api-reference/pipeline/add",
|
||||
"api-reference/pipeline/query",
|
||||
"api-reference/pipeline/chat",
|
||||
"api-reference/pipeline/search",
|
||||
"api-reference/pipeline/deploy",
|
||||
"api-reference/pipeline/reset",
|
||||
"api-reference/pipeline/delete",
|
||||
"api-reference/pipeline/evaluate"
|
||||
"api-reference/app/add",
|
||||
"api-reference/app/query",
|
||||
"api-reference/app/chat",
|
||||
"api-reference/app/search",
|
||||
"api-reference/app/get",
|
||||
"api-reference/app/evaluate",
|
||||
"api-reference/app/deploy",
|
||||
"api-reference/app/reset",
|
||||
"api-reference/app/delete"
|
||||
]
|
||||
},
|
||||
"api-reference/store/openai-assistant",
|
||||
@@ -238,7 +240,7 @@
|
||||
"footerSocials": {
|
||||
"website": "https://embedchain.ai",
|
||||
"github": "https://github.com/embedchain/embedchain",
|
||||
"slack": "https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw",
|
||||
"slack": "https://embedchain.ai/slack",
|
||||
"discord": "https://discord.gg/6PzXDgEjG5",
|
||||
"twitter": "https://twitter.com/embedchain",
|
||||
"linkedin": "https://www.linkedin.com/company/embedchain"
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: 'FAQs'
|
||||
---
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: 'Overview'
|
||||
---
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: 'Quickstart'
|
||||
---
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: 'Roadmap'
|
||||
---
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: 'Security'
|
||||
---
|
||||
@@ -250,30 +250,6 @@ class App(EmbedChain):
|
||||
r.raise_for_status()
|
||||
return r.json()
|
||||
|
||||
def search(self, query, num_documents=3):
|
||||
"""
|
||||
Search for similar documents related to the query in the vector database.
|
||||
"""
|
||||
# Send anonymous telemetry
|
||||
self.telemetry.capture(event_name="search", properties=self._telemetry_props)
|
||||
|
||||
# TODO: Search will call the endpoint rather than fetching the data from the db itself when deploy=True.
|
||||
if self.id is None:
|
||||
where = {"app_id": self.local_id}
|
||||
context = self.db.query(
|
||||
query,
|
||||
n_results=num_documents,
|
||||
where=where,
|
||||
citations=True,
|
||||
)
|
||||
result = []
|
||||
for c in context:
|
||||
result.append({"context": c[0], "metadata": c[1]})
|
||||
return result
|
||||
else:
|
||||
# Make API call to the backend to get the results
|
||||
NotImplementedError("Search is not implemented yet for the prod mode.")
|
||||
|
||||
def _upload_file_to_presigned_url(self, presigned_url, file_path):
|
||||
try:
|
||||
with open(file_path, "rb") as file:
|
||||
|
||||
@@ -39,11 +39,14 @@ class BaseChunker(JSONSerializable):
|
||||
for data in data_records:
|
||||
content = data["content"]
|
||||
|
||||
meta_data = data["meta_data"]
|
||||
metadata = data["meta_data"]
|
||||
# add data type to meta data to allow query using data type
|
||||
meta_data["data_type"] = self.data_type.value
|
||||
meta_data["doc_id"] = doc_id
|
||||
url = meta_data["url"]
|
||||
metadata["data_type"] = self.data_type.value
|
||||
metadata["doc_id"] = doc_id
|
||||
|
||||
# TODO: Currently defaulting to the src as the url. This is done intentianally since some
|
||||
# of the data types like 'gmail' loader doesn't have the url in the meta data.
|
||||
url = metadata.get("url", src)
|
||||
|
||||
chunks = self.get_chunks(content)
|
||||
for chunk in chunks:
|
||||
@@ -53,7 +56,7 @@ class BaseChunker(JSONSerializable):
|
||||
id_map[chunk_id] = True
|
||||
chunk_ids.append(chunk_id)
|
||||
documents.append(chunk)
|
||||
metadatas.append(meta_data)
|
||||
metadatas.append(metadata)
|
||||
return {
|
||||
"documents": documents,
|
||||
"ids": chunk_ids,
|
||||
|
||||
@@ -6,7 +6,11 @@ from embedchain.helpers.json_serializable import register_deserializable
|
||||
@register_deserializable
|
||||
class BaseEmbedderConfig:
|
||||
def __init__(
|
||||
self, model: Optional[str] = None, deployment_name: Optional[str] = None, api_key: Optional[str] = None
|
||||
self,
|
||||
model: Optional[str] = None,
|
||||
deployment_name: Optional[str] = None,
|
||||
vector_dimension: Optional[int] = None,
|
||||
api_key: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Initialize a new instance of an embedder config class.
|
||||
@@ -18,4 +22,5 @@ class BaseEmbedderConfig:
|
||||
"""
|
||||
self.model = model
|
||||
self.deployment_name = deployment_name
|
||||
self.vector_dimension = vector_dimension
|
||||
self.api_key = api_key
|
||||
|
||||
@@ -24,7 +24,8 @@ DEFAULT_PROMPT_WITH_HISTORY = """
|
||||
|
||||
$context
|
||||
|
||||
History: $history
|
||||
History:
|
||||
$history
|
||||
|
||||
Query: $query
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||
@@ -8,13 +9,28 @@ from embedchain.helpers.json_serializable import register_deserializable
|
||||
class PineconeDBConfig(BaseVectorDbConfig):
|
||||
def __init__(
|
||||
self,
|
||||
collection_name: Optional[str] = None,
|
||||
dir: Optional[str] = None,
|
||||
index_name: Optional[str] = None,
|
||||
api_key: Optional[str] = None,
|
||||
vector_dimension: int = 1536,
|
||||
metric: Optional[str] = "cosine",
|
||||
pod_config: Optional[dict[str, any]] = None,
|
||||
serverless_config: Optional[dict[str, any]] = None,
|
||||
**extra_params: dict[str, any],
|
||||
):
|
||||
self.metric = metric
|
||||
self.api_key = api_key
|
||||
self.index_name = index_name
|
||||
self.vector_dimension = vector_dimension
|
||||
self.extra_params = extra_params
|
||||
super().__init__(collection_name=collection_name, dir=dir)
|
||||
if pod_config is None and serverless_config is None:
|
||||
# If no config is provided, use the default pod spec config
|
||||
pod_environment = os.environ.get("PINECONE_ENV", "gcp-starter")
|
||||
self.pod_config = {"environment": pod_environment, "metadata_config": {"indexed": ["*"]}}
|
||||
else:
|
||||
self.pod_config = pod_config
|
||||
self.serverless_config = serverless_config
|
||||
|
||||
if self.pod_config and self.serverless_config:
|
||||
raise ValueError("Only one of pod_config or serverless_config can be provided.")
|
||||
|
||||
super().__init__(collection_name=self.index_name, dir=None)
|
||||
|
||||
@@ -2,12 +2,12 @@ from dotenv import load_dotenv
|
||||
from fastapi import FastAPI, responses
|
||||
from pydantic import BaseModel
|
||||
|
||||
from embedchain import Pipeline
|
||||
from embedchain import App
|
||||
|
||||
load_dotenv(".env")
|
||||
|
||||
app = FastAPI(title="Embedchain FastAPI App")
|
||||
embedchain_app = Pipeline()
|
||||
embedchain_app = App()
|
||||
|
||||
|
||||
class SourceModel(BaseModel):
|
||||
|
||||
@@ -2,7 +2,7 @@ from dotenv import load_dotenv
|
||||
from fastapi import Body, FastAPI, responses
|
||||
from modal import Image, Secret, Stub, asgi_app
|
||||
|
||||
from embedchain import Pipeline
|
||||
from embedchain import App
|
||||
|
||||
load_dotenv(".env")
|
||||
|
||||
@@ -18,7 +18,7 @@ stub = Stub(
|
||||
)
|
||||
|
||||
web_app = FastAPI()
|
||||
embedchain_app = Pipeline(name="embedchain-modal-app")
|
||||
embedchain_app = App(name="embedchain-modal-app")
|
||||
|
||||
|
||||
@web_app.post("/add")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from fastapi import FastAPI, responses
|
||||
from pydantic import BaseModel
|
||||
|
||||
from embedchain import Pipeline
|
||||
from embedchain import App
|
||||
|
||||
app = FastAPI(title="Embedchain FastAPI App")
|
||||
embedchain_app = Pipeline()
|
||||
embedchain_app = App()
|
||||
|
||||
|
||||
class SourceModel(BaseModel):
|
||||
|
||||
@@ -433,10 +433,27 @@ class EmbedChain(JSONSerializable):
|
||||
# Count before, to calculate a delta in the end.
|
||||
chunks_before_addition = self.db.count()
|
||||
|
||||
self.db.add(documents=documents, metadatas=metadatas, ids=ids, **kwargs)
|
||||
count_new_chunks = self.db.count() - chunks_before_addition
|
||||
# Filter out empty documents and ensure they meet the API requirements
|
||||
valid_documents = [doc for doc in documents if doc and isinstance(doc, str)]
|
||||
|
||||
documents = valid_documents
|
||||
|
||||
# Chunk documents into batches of 2048 and handle each batch
|
||||
# helps wigth large loads of embeddings that hit OpenAI limits
|
||||
document_batches = [documents[i : i + 2048] for i in range(0, len(documents), 2048)]
|
||||
for batch in document_batches:
|
||||
try:
|
||||
# Add only valid batches
|
||||
if batch:
|
||||
self.db.add(documents=batch, metadatas=metadatas, ids=ids, **kwargs)
|
||||
except Exception as e:
|
||||
print(f"Failed to add batch due to a bad request: {e}")
|
||||
# Handle the error, e.g., by logging, retrying, or skipping
|
||||
pass
|
||||
|
||||
count_new_chunks = self.db.count() - chunks_before_addition
|
||||
print(f"Successfully saved {src} ({chunker.data_type}). New chunks count: {count_new_chunks}")
|
||||
|
||||
return list(documents), metadatas, ids, count_new_chunks
|
||||
|
||||
@staticmethod
|
||||
@@ -634,6 +651,41 @@ class EmbedChain(JSONSerializable):
|
||||
else:
|
||||
return answer
|
||||
|
||||
def search(self, query, num_documents=3, where=None, raw_filter=None):
|
||||
"""
|
||||
Search for similar documents related to the query in the vector database.
|
||||
|
||||
Args:
|
||||
query (str): The query to use.
|
||||
num_documents (int, optional): Number of similar documents to fetch. Defaults to 3.
|
||||
where (dict[str, any], optional): Filter criteria for the search.
|
||||
raw_filter (dict[str, any], optional): Advanced raw filter criteria for the search.
|
||||
|
||||
Raises:
|
||||
ValueError: If both `raw_filter` and `where` are used simultaneously.
|
||||
|
||||
Returns:
|
||||
list[dict]: A list of dictionaries, each containing the 'context' and 'metadata' of a document.
|
||||
"""
|
||||
# Send anonymous telemetry
|
||||
self.telemetry.capture(event_name="search", properties=self._telemetry_props)
|
||||
|
||||
if raw_filter and where:
|
||||
raise ValueError("You can't use both `raw_filter` and `where` together.")
|
||||
|
||||
filter_type = "raw_filter" if raw_filter else "where"
|
||||
filter_criteria = raw_filter if raw_filter else where
|
||||
|
||||
params = {
|
||||
"input_query": query,
|
||||
"n_results": num_documents,
|
||||
"citations": True,
|
||||
"app_id": self.config.id,
|
||||
filter_type: filter_criteria,
|
||||
}
|
||||
|
||||
return [{"context": c[0], "metadata": c[1]} for c in self.db.query(**params)]
|
||||
|
||||
def set_collection_name(self, name: str):
|
||||
"""
|
||||
Set the name of the collection. A collection is an isolated space for vectors.
|
||||
@@ -661,9 +713,19 @@ class EmbedChain(JSONSerializable):
|
||||
# Send anonymous telemetry
|
||||
self.telemetry.capture(event_name="reset", properties=self._telemetry_props)
|
||||
|
||||
def get_history(self, num_rounds: int = 10, display_format: bool = True, session_id: Optional[str] = "default"):
|
||||
def get_history(
|
||||
self,
|
||||
num_rounds: int = 10,
|
||||
display_format: bool = True,
|
||||
session_id: Optional[str] = "default",
|
||||
fetch_all: bool = False,
|
||||
):
|
||||
history = self.llm.memory.get(
|
||||
app_id=self.config.id, session_id=session_id, num_rounds=num_rounds, display_format=display_format
|
||||
app_id=self.config.id,
|
||||
session_id=session_id,
|
||||
num_rounds=num_rounds,
|
||||
display_format=display_format,
|
||||
fetch_all=fetch_all,
|
||||
)
|
||||
return history
|
||||
|
||||
@@ -674,3 +736,15 @@ class EmbedChain(JSONSerializable):
|
||||
def delete_all_chat_history(self, app_id: str):
|
||||
self.llm.memory.delete(app_id=app_id)
|
||||
self.llm.update_history(app_id=app_id)
|
||||
|
||||
def delete(self, source_id: str):
|
||||
"""
|
||||
Deletes the data from the database.
|
||||
:param source_hash: The hash of the source.
|
||||
:type source_hash: str
|
||||
"""
|
||||
self.db.delete(where={"hash": source_id})
|
||||
logging.info(f"Successfully deleted {source_id}")
|
||||
# Send anonymous telemetry
|
||||
if self.config.collect_metrics:
|
||||
self.telemetry.capture(event_name="delete", properties=self._telemetry_props)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Optional
|
||||
from typing import Optional, Union
|
||||
|
||||
import google.generativeai as genai
|
||||
from chromadb import EmbeddingFunction, Embeddings
|
||||
@@ -13,12 +13,19 @@ class GoogleAIEmbeddingFunction(EmbeddingFunction):
|
||||
super().__init__()
|
||||
self.config = config or GoogleAIEmbedderConfig()
|
||||
|
||||
def __call__(self, input_: str) -> Embeddings:
|
||||
def __call__(self, input: Union[list[str], str]) -> Embeddings:
|
||||
model = self.config.model
|
||||
title = self.config.title
|
||||
task_type = self.config.task_type
|
||||
embeddings = genai.embed_content(model=model, content=input_, task_type=task_type, title=title)
|
||||
return embeddings["embedding"]
|
||||
if isinstance(input, str):
|
||||
input_ = [input]
|
||||
else:
|
||||
input_ = input
|
||||
data = genai.embed_content(model=model, content=input_, task_type=task_type, title=title)
|
||||
embeddings = data["embedding"]
|
||||
if isinstance(input_, str):
|
||||
embeddings = [embeddings]
|
||||
return embeddings
|
||||
|
||||
|
||||
class GoogleAIEmbedder(BaseEmbedder):
|
||||
@@ -27,5 +34,5 @@ class GoogleAIEmbedder(BaseEmbedder):
|
||||
embedding_fn = GoogleAIEmbeddingFunction(config=config)
|
||||
self.set_embedding_fn(embedding_fn=embedding_fn)
|
||||
|
||||
vector_dimension = VectorDimensions.GOOGLE_AI.value
|
||||
vector_dimension = self.config.vector_dimension or VectorDimensions.GOOGLE_AI.value
|
||||
self.set_vector_dimension(vector_dimension=vector_dimension)
|
||||
|
||||
@@ -16,5 +16,5 @@ class GPT4AllEmbedder(BaseEmbedder):
|
||||
embedding_fn = BaseEmbedder._langchain_default_concept(embeddings)
|
||||
self.set_embedding_fn(embedding_fn=embedding_fn)
|
||||
|
||||
vector_dimension = VectorDimensions.GPT4ALL.value
|
||||
vector_dimension = self.config.vector_dimension or VectorDimensions.GPT4ALL.value
|
||||
self.set_vector_dimension(vector_dimension=vector_dimension)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
from langchain.embeddings import HuggingFaceEmbeddings
|
||||
from langchain_community.embeddings import HuggingFaceEmbeddings
|
||||
|
||||
from embedchain.config import BaseEmbedderConfig
|
||||
from embedchain.embedder.base import BaseEmbedder
|
||||
@@ -15,5 +15,5 @@ class HuggingFaceEmbedder(BaseEmbedder):
|
||||
embedding_fn = BaseEmbedder._langchain_default_concept(embeddings)
|
||||
self.set_embedding_fn(embedding_fn=embedding_fn)
|
||||
|
||||
vector_dimension = VectorDimensions.HUGGING_FACE.value
|
||||
vector_dimension = self.config.vector_dimension or VectorDimensions.HUGGING_FACE.value
|
||||
self.set_vector_dimension(vector_dimension=vector_dimension)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
from typing import Optional, Union
|
||||
|
||||
from chromadb import EmbeddingFunction, Embeddings
|
||||
|
||||
from embedchain.config import BaseEmbedderConfig
|
||||
from embedchain.embedder.base import BaseEmbedder
|
||||
from embedchain.models import VectorDimensions
|
||||
|
||||
|
||||
class MistralAIEmbeddingFunction(EmbeddingFunction):
|
||||
def __init__(self, config: BaseEmbedderConfig) -> None:
|
||||
super().__init__()
|
||||
try:
|
||||
from langchain_mistralai import MistralAIEmbeddings
|
||||
except ModuleNotFoundError:
|
||||
raise ModuleNotFoundError(
|
||||
"The required dependencies for MistralAI are not installed."
|
||||
'Please install with `pip install --upgrade "embedchain[mistralai]"`'
|
||||
) from None
|
||||
self.config = config
|
||||
api_key = self.config.api_key or os.getenv("MISTRAL_API_KEY")
|
||||
self.client = MistralAIEmbeddings(mistral_api_key=api_key)
|
||||
self.client.model = self.config.model
|
||||
|
||||
def __call__(self, input: Union[list[str], str]) -> Embeddings:
|
||||
if isinstance(input, str):
|
||||
input_ = [input]
|
||||
else:
|
||||
input_ = input
|
||||
response = self.client.embed_documents(input_)
|
||||
return response
|
||||
|
||||
|
||||
class MistralAIEmbedder(BaseEmbedder):
|
||||
def __init__(self, config: Optional[BaseEmbedderConfig] = None):
|
||||
super().__init__(config)
|
||||
|
||||
if self.config.model is None:
|
||||
self.config.model = "mistral-embed"
|
||||
|
||||
embedding_fn = MistralAIEmbeddingFunction(config=self.config)
|
||||
self.set_embedding_fn(embedding_fn=embedding_fn)
|
||||
|
||||
vector_dimension = self.config.vector_dimension or VectorDimensions.MISTRAL_AI.value
|
||||
self.set_vector_dimension(vector_dimension=vector_dimension)
|
||||
@@ -2,7 +2,7 @@ import os
|
||||
from typing import Optional
|
||||
|
||||
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
|
||||
from langchain.embeddings import AzureOpenAIEmbeddings
|
||||
from langchain_community.embeddings import AzureOpenAIEmbeddings
|
||||
|
||||
from embedchain.config import BaseEmbedderConfig
|
||||
from embedchain.embedder.base import BaseEmbedder
|
||||
@@ -32,4 +32,5 @@ class OpenAIEmbedder(BaseEmbedder):
|
||||
model_name=self.config.model,
|
||||
)
|
||||
self.set_embedding_fn(embedding_fn=embedding_fn)
|
||||
self.set_vector_dimension(vector_dimension=VectorDimensions.OPENAI.value)
|
||||
vector_dimension = self.config.vector_dimension or VectorDimensions.OPENAI.value
|
||||
self.set_vector_dimension(vector_dimension=vector_dimension)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from typing import Optional
|
||||
|
||||
from langchain.embeddings import VertexAIEmbeddings
|
||||
from langchain_community.embeddings import VertexAIEmbeddings
|
||||
|
||||
from embedchain.config import BaseEmbedderConfig
|
||||
from embedchain.embedder.base import BaseEmbedder
|
||||
@@ -15,5 +15,5 @@ class VertexAIEmbedder(BaseEmbedder):
|
||||
embedding_fn = BaseEmbedder._langchain_default_concept(embeddings)
|
||||
self.set_embedding_fn(embedding_fn=embedding_fn)
|
||||
|
||||
vector_dimension = VectorDimensions.VERTEX_AI.value
|
||||
vector_dimension = self.config.vector_dimension or VectorDimensions.VERTEX_AI.value
|
||||
self.set_vector_dimension(vector_dimension=vector_dimension)
|
||||
|
||||
@@ -21,7 +21,7 @@ class Groundedness(BaseMetric):
|
||||
def __init__(self, config: Optional[GroundednessConfig] = None):
|
||||
super().__init__(name=EvalMetric.GROUNDEDNESS.value)
|
||||
self.config = config or GroundednessConfig()
|
||||
api_key = self.config.api_key or os.environ["OPENAI_API_KEY"]
|
||||
api_key = self.config.api_key or os.getenv("OPENAI_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError("Please set the OPENAI_API_KEY environment variable or pass the `api_key` in config.")
|
||||
self.client = OpenAI(api_key=api_key)
|
||||
|
||||
@@ -21,6 +21,8 @@ class LlmFactory:
|
||||
"openai": "embedchain.llm.openai.OpenAILlm",
|
||||
"vertexai": "embedchain.llm.vertex_ai.VertexAILlm",
|
||||
"google": "embedchain.llm.google.GoogleLlm",
|
||||
"aws_bedrock": "embedchain.llm.aws_bedrock.AWSBedrockLlm",
|
||||
"mistralai": "embedchain.llm.mistralai.MistralAILlm",
|
||||
}
|
||||
provider_to_config_class = {
|
||||
"embedchain": "embedchain.config.llm.base.BaseLlmConfig",
|
||||
@@ -50,12 +52,14 @@ class EmbedderFactory:
|
||||
"openai": "embedchain.embedder.openai.OpenAIEmbedder",
|
||||
"vertexai": "embedchain.embedder.vertexai.VertexAIEmbedder",
|
||||
"google": "embedchain.embedder.google.GoogleAIEmbedder",
|
||||
"mistralai": "embedchain.embedder.mistralai.MistralAIEmbedder",
|
||||
}
|
||||
provider_to_config_class = {
|
||||
"azure_openai": "embedchain.config.embedder.base.BaseEmbedderConfig",
|
||||
"openai": "embedchain.config.embedder.base.BaseEmbedderConfig",
|
||||
"gpt4all": "embedchain.config.embedder.base.BaseEmbedderConfig",
|
||||
"google": "embedchain.config.embedder.google.GoogleAIEmbedderConfig",
|
||||
"huggingface": "embedchain.config.embedder.base.BaseEmbedderConfig",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -19,7 +19,7 @@ class AnthropicLlm(BaseLlm):
|
||||
|
||||
@staticmethod
|
||||
def _get_answer(prompt: str, config: BaseLlmConfig) -> str:
|
||||
from langchain.chat_models import ChatAnthropic
|
||||
from langchain_community.chat_models import ChatAnthropic
|
||||
|
||||
chat = ChatAnthropic(
|
||||
anthropic_api_key=os.environ["ANTHROPIC_API_KEY"], temperature=config.temperature, model=config.model
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from langchain_community.llms import Bedrock
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
from embedchain.llm.base import BaseLlm
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class AWSBedrockLlm(BaseLlm):
|
||||
def __init__(self, config: Optional[BaseLlmConfig] = None):
|
||||
super().__init__(config)
|
||||
|
||||
def get_llm_model_answer(self, prompt) -> str:
|
||||
response = self._get_answer(prompt, self.config)
|
||||
return response
|
||||
|
||||
def _get_answer(self, prompt: str, config: BaseLlmConfig) -> str:
|
||||
try:
|
||||
import boto3
|
||||
except ModuleNotFoundError:
|
||||
raise ModuleNotFoundError(
|
||||
"The required dependencies for AWSBedrock are not installed."
|
||||
'Please install with `pip install --upgrade "embedchain[aws-bedrock]"`'
|
||||
) from None
|
||||
|
||||
self.boto_client = boto3.client("bedrock-runtime", "us-west-2" or os.environ.get("AWS_REGION"))
|
||||
|
||||
kwargs = {
|
||||
"model_id": config.model or "amazon.titan-text-express-v1",
|
||||
"client": self.boto_client,
|
||||
"model_kwargs": config.model_kwargs
|
||||
or {
|
||||
"temperature": config.temperature,
|
||||
},
|
||||
}
|
||||
|
||||
if config.stream:
|
||||
from langchain.callbacks.streaming_stdout import \
|
||||
StreamingStdOutCallbackHandler
|
||||
|
||||
callbacks = [StreamingStdOutCallbackHandler()]
|
||||
llm = Bedrock(**kwargs, streaming=config.stream, callbacks=callbacks)
|
||||
else:
|
||||
llm = Bedrock(**kwargs)
|
||||
|
||||
return llm(prompt)
|
||||
@@ -16,7 +16,7 @@ class AzureOpenAILlm(BaseLlm):
|
||||
|
||||
@staticmethod
|
||||
def _get_answer(prompt: str, config: BaseLlmConfig) -> str:
|
||||
from langchain.chat_models import AzureChatOpenAI
|
||||
from langchain_community.chat_models import AzureChatOpenAI
|
||||
|
||||
if not config.deployment_name:
|
||||
raise ValueError("Deployment name must be provided for Azure OpenAI")
|
||||
|
||||
+10
-4
@@ -65,6 +65,14 @@ class BaseLlm(JSONSerializable):
|
||||
self.memory.add(app_id=app_id, chat_message=chat_message, session_id=session_id)
|
||||
self.update_history(app_id=app_id, session_id=session_id)
|
||||
|
||||
def _format_history(self) -> str:
|
||||
"""Format history to be used in prompt
|
||||
|
||||
:return: Formatted history
|
||||
:rtype: str
|
||||
"""
|
||||
return "\n".join(self.history)
|
||||
|
||||
def generate_prompt(self, input_query: str, contexts: list[str], **kwargs: dict[str, Any]) -> str:
|
||||
"""
|
||||
Generates a prompt based on the given query and context, ready to be
|
||||
@@ -84,10 +92,8 @@ class BaseLlm(JSONSerializable):
|
||||
|
||||
prompt_contains_history = self.config._validate_prompt_history(self.config.prompt)
|
||||
if prompt_contains_history:
|
||||
# Prompt contains history
|
||||
# If there is no history yet, we insert `- no history -`
|
||||
prompt = self.config.prompt.substitute(
|
||||
context=context_string, query=input_query, history=self.history or "- no history -"
|
||||
context=context_string, query=input_query, history=self._format_history() or "No history"
|
||||
)
|
||||
elif self.history and not prompt_contains_history:
|
||||
# History is present, but not included in the prompt.
|
||||
@@ -98,7 +104,7 @@ class BaseLlm(JSONSerializable):
|
||||
):
|
||||
# swap in the template with history
|
||||
prompt = DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE.substitute(
|
||||
context=context_string, query=input_query, history=self.history
|
||||
context=context_string, query=input_query, history=self._format_history()
|
||||
)
|
||||
else:
|
||||
# If we can't swap in the default, we still proceed but tell users that the history is ignored.
|
||||
|
||||
@@ -2,7 +2,7 @@ import importlib
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from langchain.llms.cohere import Cohere
|
||||
from langchain_community.llms.cohere import Cohere
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
@@ -26,7 +26,8 @@ class GPT4ALLLlm(BaseLlm):
|
||||
@staticmethod
|
||||
def _get_instance(model):
|
||||
try:
|
||||
from langchain.llms.gpt4all import GPT4All as LangchainGPT4All
|
||||
from langchain_community.llms.gpt4all import \
|
||||
GPT4All as LangchainGPT4All
|
||||
except ModuleNotFoundError:
|
||||
raise ModuleNotFoundError(
|
||||
"The GPT4All python package is not installed. Please install it with `pip install --upgrade embedchain[opensource]`" # noqa E501
|
||||
|
||||
@@ -3,8 +3,8 @@ import logging
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from langchain.llms.huggingface_endpoint import HuggingFaceEndpoint
|
||||
from langchain.llms.huggingface_hub import HuggingFaceHub
|
||||
from langchain_community.llms.huggingface_endpoint import HuggingFaceEndpoint
|
||||
from langchain_community.llms.huggingface_hub import HuggingFaceHub
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from langchain.chat_models import JinaChat
|
||||
from langchain.schema import HumanMessage, SystemMessage
|
||||
from langchain_community.chat_models import JinaChat
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
@@ -2,7 +2,7 @@ import importlib
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from langchain.llms.replicate import Replicate
|
||||
from langchain_community.llms.replicate import Replicate
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
from embedchain.llm.base import BaseLlm
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class MistralAILlm(BaseLlm):
|
||||
def __init__(self, config: Optional[BaseLlmConfig] = None):
|
||||
super().__init__(config)
|
||||
if not self.config.api_key and "MISTRAL_API_KEY" not in os.environ:
|
||||
raise ValueError("Please set the MISTRAL_API_KEY environment variable or pass it in the config.")
|
||||
|
||||
def get_llm_model_answer(self, prompt):
|
||||
return MistralAILlm._get_answer(prompt=prompt, config=self.config)
|
||||
|
||||
@staticmethod
|
||||
def _get_answer(prompt: str, config: BaseLlmConfig):
|
||||
try:
|
||||
from langchain_core.messages import HumanMessage, SystemMessage
|
||||
from langchain_mistralai.chat_models import ChatMistralAI
|
||||
except ModuleNotFoundError:
|
||||
raise ModuleNotFoundError(
|
||||
"The required dependencies for MistralAI are not installed."
|
||||
'Please install with `pip install --upgrade "embedchain[mistralai]"`'
|
||||
) from None
|
||||
|
||||
api_key = config.api_key or os.getenv("MISTRAL_API_KEY")
|
||||
client = ChatMistralAI(mistral_api_key=api_key)
|
||||
messages = []
|
||||
if config.system_prompt:
|
||||
messages.append(SystemMessage(content=config.system_prompt))
|
||||
messages.append(HumanMessage(content=prompt))
|
||||
kwargs = {
|
||||
"model": config.model or "mistral-tiny",
|
||||
"temperature": config.temperature,
|
||||
"max_tokens": config.max_tokens,
|
||||
"top_p": config.top_p,
|
||||
}
|
||||
|
||||
# TODO: Add support for streaming
|
||||
if config.stream:
|
||||
answer = ""
|
||||
for chunk in client.stream(**kwargs, input=messages):
|
||||
answer += chunk.content
|
||||
return answer
|
||||
else:
|
||||
response = client.invoke(**kwargs, input=messages)
|
||||
answer = response.content
|
||||
return answer
|
||||
@@ -4,7 +4,7 @@ from typing import Optional, Union
|
||||
from langchain.callbacks.manager import CallbackManager
|
||||
from langchain.callbacks.stdout import StdOutCallbackHandler
|
||||
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
||||
from langchain.llms.ollama import Ollama
|
||||
from langchain_community.llms.ollama import Ollama
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
+30
-21
@@ -1,9 +1,12 @@
|
||||
import json
|
||||
import os
|
||||
from typing import Any, Optional
|
||||
from typing import Any, Callable, Dict, Optional, Type, Union
|
||||
|
||||
from langchain.chat_models import ChatOpenAI
|
||||
from langchain.schema import AIMessage, HumanMessage, SystemMessage
|
||||
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
||||
from langchain.schema import BaseMessage, HumanMessage, SystemMessage
|
||||
from langchain_core.tools import BaseTool
|
||||
from langchain_openai import ChatOpenAI
|
||||
from pydantic import BaseModel
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
@@ -12,8 +15,12 @@ from embedchain.llm.base import BaseLlm
|
||||
|
||||
@register_deserializable
|
||||
class OpenAILlm(BaseLlm):
|
||||
def __init__(self, config: Optional[BaseLlmConfig] = None, functions: Optional[dict[str, Any]] = None):
|
||||
self.functions = functions
|
||||
def __init__(
|
||||
self,
|
||||
config: Optional[BaseLlmConfig] = None,
|
||||
tools: Optional[Union[Dict[str, Any], Type[BaseModel], Callable[..., Any], BaseTool]] = None,
|
||||
):
|
||||
self.tools = tools
|
||||
super().__init__(config=config)
|
||||
|
||||
def get_llm_model_answer(self, prompt) -> str:
|
||||
@@ -35,26 +42,28 @@ class OpenAILlm(BaseLlm):
|
||||
if config.top_p:
|
||||
kwargs["model_kwargs"]["top_p"] = config.top_p
|
||||
if config.stream:
|
||||
from langchain.callbacks.streaming_stdout import \
|
||||
StreamingStdOutCallbackHandler
|
||||
|
||||
callbacks = config.callbacks if config.callbacks else [StreamingStdOutCallbackHandler()]
|
||||
chat = ChatOpenAI(**kwargs, streaming=config.stream, callbacks=callbacks, api_key=api_key)
|
||||
else:
|
||||
chat = ChatOpenAI(**kwargs, api_key=api_key)
|
||||
if self.tools:
|
||||
return self._query_function_call(chat, self.tools, messages)
|
||||
|
||||
if self.functions is not None:
|
||||
from langchain.chains.openai_functions import \
|
||||
create_openai_fn_runnable
|
||||
from langchain.prompts import ChatPromptTemplate
|
||||
return chat.invoke(messages).content
|
||||
|
||||
structured_prompt = ChatPromptTemplate.from_messages(messages)
|
||||
runnable = create_openai_fn_runnable(functions=self.functions, prompt=structured_prompt, llm=chat)
|
||||
fn_res = runnable.invoke(
|
||||
{
|
||||
"input": prompt,
|
||||
}
|
||||
)
|
||||
messages.append(AIMessage(content=json.dumps(fn_res)))
|
||||
def _query_function_call(
|
||||
self,
|
||||
chat: ChatOpenAI,
|
||||
tools: Optional[Union[Dict[str, Any], Type[BaseModel], Callable[..., Any], BaseTool]],
|
||||
messages: list[BaseMessage],
|
||||
) -> str:
|
||||
from langchain.output_parsers.openai_tools import JsonOutputToolsParser
|
||||
from langchain_core.utils.function_calling import \
|
||||
convert_to_openai_tool
|
||||
|
||||
return chat(messages).content
|
||||
openai_tools = [convert_to_openai_tool(tools)]
|
||||
chat = chat.bind(tools=openai_tools).pipe(JsonOutputToolsParser())
|
||||
try:
|
||||
return json.dumps(chat.invoke(messages)[0])
|
||||
except IndexError:
|
||||
return "Input could not be mapped to the function!"
|
||||
|
||||
@@ -2,7 +2,7 @@ import importlib
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from langchain.llms import Together
|
||||
from langchain_community.llms import Together
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
@@ -2,6 +2,9 @@ import importlib
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
||||
from langchain_google_vertexai import ChatVertexAI
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
from embedchain.llm.base import BaseLlm
|
||||
@@ -24,13 +27,17 @@ class VertexAILlm(BaseLlm):
|
||||
|
||||
@staticmethod
|
||||
def _get_answer(prompt: str, config: BaseLlmConfig) -> str:
|
||||
from langchain.chat_models import ChatVertexAI
|
||||
|
||||
chat = ChatVertexAI(temperature=config.temperature, model=config.model)
|
||||
|
||||
if config.top_p and config.top_p != 1:
|
||||
logging.warning("Config option `top_p` is not supported by this model.")
|
||||
|
||||
messages = BaseLlm._get_messages(prompt, system_prompt=config.system_prompt)
|
||||
|
||||
return chat(messages).content
|
||||
if config.stream:
|
||||
callbacks = config.callbacks if config.callbacks else [StreamingStdOutCallbackHandler()]
|
||||
llm = ChatVertexAI(
|
||||
temperature=config.temperature, model=config.model, callbacks=callbacks, streaming=config.stream
|
||||
)
|
||||
else:
|
||||
llm = ChatVertexAI(temperature=config.temperature, model=config.model)
|
||||
|
||||
return llm.invoke(messages).content
|
||||
|
||||
@@ -14,19 +14,19 @@ class DiscourseLoader(BaseLoader):
|
||||
super().__init__()
|
||||
if not config:
|
||||
raise ValueError(
|
||||
"DiscourseLoader requires a config. Check the documentation for the correct format - `https://docs.embedchain.ai/data-sources/discourse`" # noqa: E501
|
||||
"DiscourseLoader requires a config. Check the documentation for the correct format - `https://docs.embedchain.ai/components/data-sources/discourse`" # noqa: E501
|
||||
)
|
||||
|
||||
self.domain = config.get("domain")
|
||||
if not self.domain:
|
||||
raise ValueError(
|
||||
"DiscourseLoader requires a domain. Check the documentation for the correct format - `https://docs.embedchain.ai/data-sources/discourse`" # noqa: E501
|
||||
"DiscourseLoader requires a domain. Check the documentation for the correct format - `https://docs.embedchain.ai/components/data-sources/discourse`" # noqa: E501
|
||||
)
|
||||
|
||||
def _check_query(self, query):
|
||||
if not query or not isinstance(query, str):
|
||||
raise ValueError(
|
||||
"DiscourseLoader requires a query. Check the documentation for the correct format - `https://docs.embedchain.ai/data-sources/discourse`" # noqa: E501
|
||||
"DiscourseLoader requires a query. Check the documentation for the correct format - `https://docs.embedchain.ai/components/data-sources/discourse`" # noqa: E501
|
||||
)
|
||||
|
||||
def _load_post(self, post_id):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import hashlib
|
||||
|
||||
try:
|
||||
from langchain.document_loaders import Docx2txtLoader
|
||||
from langchain_community.document_loaders import Docx2txtLoader
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
'Docx file requires extra dependencies. Install with `pip install --upgrade "embedchain[dataloaders]"`'
|
||||
|
||||
@@ -8,8 +8,8 @@ except ImportError:
|
||||
"Google Drive requires extra dependencies. Install with `pip install embedchain[googledrive]`"
|
||||
) from None
|
||||
|
||||
from langchain.document_loaders import GoogleDriveLoader as Loader
|
||||
from langchain.document_loaders import UnstructuredFileIOLoader
|
||||
from langchain_community.document_loaders import GoogleDriveLoader as Loader
|
||||
from langchain_community.document_loaders import UnstructuredFileIOLoader
|
||||
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
from embedchain.loaders.base_loader import BaseLoader
|
||||
|
||||
@@ -36,7 +36,9 @@ class JSONReader:
|
||||
return ["\n".join(useful_lines)]
|
||||
|
||||
|
||||
VALID_URL_PATTERN = "^https:\/\/[0-9A-Za-z]+(\.[0-9A-Za-z]+)*\/[0-9A-Za-z_\/]*\.json$"
|
||||
VALID_URL_PATTERN = (
|
||||
"^https?://(?:www\.)?(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}|[a-zA-Z0-9.-]+)(?::\d+)?/(?:[^/\s]+/)*[^/\s]+\.json$"
|
||||
)
|
||||
|
||||
|
||||
class JSONLoader(BaseLoader):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import hashlib
|
||||
|
||||
try:
|
||||
from langchain.document_loaders import PyPDFLoader
|
||||
from langchain_community.document_loaders import PyPDFLoader
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
'PDF File requires extra dependencies. Install with `pip install --upgrade "embedchain[dataloaders]"`'
|
||||
@@ -15,7 +15,10 @@ from embedchain.utils.misc import clean_string
|
||||
class PdfFileLoader(BaseLoader):
|
||||
def load_data(self, url):
|
||||
"""Load data from a PDF file."""
|
||||
loader = PyPDFLoader(url)
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", # noqa:E501
|
||||
}
|
||||
loader = PyPDFLoader(url, headers=headers)
|
||||
data = []
|
||||
all_content = []
|
||||
pages = loader.load_and_split()
|
||||
|
||||
@@ -28,7 +28,7 @@ class RSSFeedLoader(BaseLoader):
|
||||
@staticmethod
|
||||
def get_rss_content(url: str):
|
||||
try:
|
||||
from langchain.document_loaders import \
|
||||
from langchain_community.document_loaders import \
|
||||
RSSFeedLoader as LangchainRSSFeedLoader
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
|
||||
@@ -31,10 +31,13 @@ class SitemapLoader(BaseLoader):
|
||||
def load_data(self, sitemap_source):
|
||||
output = []
|
||||
web_page_loader = WebPageLoader()
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", # noqa:E501
|
||||
}
|
||||
|
||||
if urlparse(sitemap_source).scheme in ("http", "https"):
|
||||
try:
|
||||
response = requests.get(sitemap_source)
|
||||
response = requests.get(sitemap_source, headers=headers)
|
||||
response.raise_for_status()
|
||||
soup = BeautifulSoup(response.text, "xml")
|
||||
except requests.RequestException as e:
|
||||
|
||||
@@ -10,7 +10,8 @@ class UnstructuredLoader(BaseLoader):
|
||||
def load_data(self, url):
|
||||
"""Load data from an Unstructured file."""
|
||||
try:
|
||||
from langchain.document_loaders import UnstructuredFileLoader
|
||||
from langchain_community.document_loaders import \
|
||||
UnstructuredFileLoader
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
'Unstructured file requires extra dependencies. Install with `pip install --upgrade "embedchain[dataloaders]"`' # noqa: E501
|
||||
|
||||
@@ -22,7 +22,10 @@ class WebPageLoader(BaseLoader):
|
||||
|
||||
def load_data(self, url):
|
||||
"""Load data from a web page using a shared requests' session."""
|
||||
response = self._session.get(url, timeout=30)
|
||||
headers = {
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36", # noqa:E501
|
||||
}
|
||||
response = self._session.get(url, headers=headers, timeout=30)
|
||||
response.raise_for_status()
|
||||
data = response.content
|
||||
content = self._get_clean_content(data, url)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import hashlib
|
||||
|
||||
try:
|
||||
from langchain.document_loaders import UnstructuredXMLLoader
|
||||
from langchain_community.document_loaders import UnstructuredXMLLoader
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
'XML file requires extra dependencies. Install with `pip install --upgrade "embedchain[dataloaders]"`'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import hashlib
|
||||
|
||||
try:
|
||||
from langchain.document_loaders import YoutubeLoader
|
||||
from langchain_community.document_loaders import YoutubeLoader
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
'YouTube video requires extra dependencies. Install with `pip install --upgrade "embedchain[dataloaders]"`'
|
||||
|
||||
@@ -92,12 +92,12 @@ class ChatHistory:
|
||||
"""
|
||||
|
||||
if fetch_all:
|
||||
additional_query = "ORDER BY created_at DESC"
|
||||
additional_query = "ORDER BY created_at ASC"
|
||||
params = (app_id,)
|
||||
else:
|
||||
additional_query = """
|
||||
AND session_id=?
|
||||
ORDER BY created_at DESC
|
||||
ORDER BY created_at ASC
|
||||
LIMIT ?
|
||||
"""
|
||||
params = (app_id, session_id, num_rounds)
|
||||
|
||||
@@ -8,3 +8,4 @@ class VectorDimensions(Enum):
|
||||
VERTEX_AI = 768
|
||||
HUGGING_FACE = 384
|
||||
GOOGLE_AI = 768
|
||||
MISTRAL_AI = 1024
|
||||
|
||||
@@ -88,7 +88,7 @@ class OpenAIAssistant:
|
||||
if Path(source).is_file():
|
||||
return source
|
||||
data_type = data_type or detect_datatype(source)
|
||||
formatter = DataFormatter(data_type=DataType(data_type), config=AddConfig(), kwargs={})
|
||||
formatter = DataFormatter(data_type=DataType(data_type), config=AddConfig())
|
||||
data = formatter.loader.load_data(source)["data"]
|
||||
return self._save_temp_data(data=data[0]["content"].encode(), source=source)
|
||||
|
||||
|
||||
@@ -201,10 +201,16 @@ def detect_datatype(source: Any) -> DataType:
|
||||
formatted_source = format_source(str(source), 30)
|
||||
|
||||
if url:
|
||||
from langchain.document_loaders.youtube import \
|
||||
ALLOWED_NETLOCK as YOUTUBE_ALLOWED_NETLOCS
|
||||
YOUTUBE_ALLOWED_NETLOCKS = {
|
||||
"www.youtube.com",
|
||||
"m.youtube.com",
|
||||
"youtu.be",
|
||||
"youtube.com",
|
||||
"vid.plus",
|
||||
"www.youtube-nocookie.com",
|
||||
}
|
||||
|
||||
if url.netloc in YOUTUBE_ALLOWED_NETLOCS:
|
||||
if url.netloc in YOUTUBE_ALLOWED_NETLOCKS:
|
||||
logging.debug(f"Source of `{formatted_source}` detected as `youtube_video`.")
|
||||
return DataType.YOUTUBE_VIDEO
|
||||
|
||||
@@ -400,6 +406,8 @@ def validate_config(config_data):
|
||||
"llama2",
|
||||
"vertexai",
|
||||
"google",
|
||||
"aws_bedrock",
|
||||
"mistralai",
|
||||
),
|
||||
Optional("config"): {
|
||||
Optional("model"): str,
|
||||
@@ -416,6 +424,7 @@ def validate_config(config_data):
|
||||
Optional("query_type"): str,
|
||||
Optional("api_key"): str,
|
||||
Optional("endpoint"): str,
|
||||
Optional("model_kwargs"): dict,
|
||||
},
|
||||
},
|
||||
Optional("vectordb"): {
|
||||
@@ -425,23 +434,41 @@ def validate_config(config_data):
|
||||
Optional("config"): object, # TODO: add particular config schema for each provider
|
||||
},
|
||||
Optional("embedder"): {
|
||||
Optional("provider"): Or("openai", "gpt4all", "huggingface", "vertexai", "azure_openai", "google"),
|
||||
Optional("provider"): Or(
|
||||
"openai",
|
||||
"gpt4all",
|
||||
"huggingface",
|
||||
"vertexai",
|
||||
"azure_openai",
|
||||
"google",
|
||||
"mistralai",
|
||||
),
|
||||
Optional("config"): {
|
||||
Optional("model"): Optional(str),
|
||||
Optional("deployment_name"): Optional(str),
|
||||
Optional("api_key"): str,
|
||||
Optional("title"): str,
|
||||
Optional("task_type"): str,
|
||||
Optional("vector_dimension"): int,
|
||||
},
|
||||
},
|
||||
Optional("embedding_model"): {
|
||||
Optional("provider"): Or("openai", "gpt4all", "huggingface", "vertexai", "azure_openai", "google"),
|
||||
Optional("provider"): Or(
|
||||
"openai",
|
||||
"gpt4all",
|
||||
"huggingface",
|
||||
"vertexai",
|
||||
"azure_openai",
|
||||
"google",
|
||||
"mistralai",
|
||||
),
|
||||
Optional("config"): {
|
||||
Optional("model"): str,
|
||||
Optional("deployment_name"): str,
|
||||
Optional("api_key"): str,
|
||||
Optional("title"): str,
|
||||
Optional("task_type"): str,
|
||||
Optional("vector_dimension"): int,
|
||||
},
|
||||
},
|
||||
Optional("chunker"): {
|
||||
|
||||
@@ -75,3 +75,8 @@ class BaseVectorDB(JSONSerializable):
|
||||
:type name: str
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def delete(self):
|
||||
"""Delete from database."""
|
||||
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -79,6 +79,8 @@ class ChromaDB(BaseVectorDB):
|
||||
def _generate_where_clause(where: dict[str, any]) -> dict[str, any]:
|
||||
# If only one filter is supplied, return it as is
|
||||
# (no need to wrap in $and based on chroma docs)
|
||||
if where is None:
|
||||
return {}
|
||||
if len(where.keys()) <= 1:
|
||||
return where
|
||||
where_filters = []
|
||||
@@ -180,9 +182,10 @@ class ChromaDB(BaseVectorDB):
|
||||
self,
|
||||
input_query: list[str],
|
||||
n_results: int,
|
||||
where: dict[str, any],
|
||||
where: Optional[dict[str, any]] = None,
|
||||
raw_filter: Optional[dict[str, any]] = None,
|
||||
citations: bool = False,
|
||||
**kwargs: Optional[dict[str, Any]],
|
||||
**kwargs: Optional[dict[str, any]],
|
||||
) -> Union[list[tuple[str, dict]], list[str]]:
|
||||
"""
|
||||
Query contents from vector database based on vector similarity
|
||||
@@ -193,6 +196,8 @@ class ChromaDB(BaseVectorDB):
|
||||
:type n_results: int
|
||||
:param where: to filter data
|
||||
:type where: dict[str, Any]
|
||||
:param raw_filter: Raw filter to apply
|
||||
:type raw_filter: dict[str, Any]
|
||||
:param citations: we use citations boolean param to return context along with the answer.
|
||||
:type citations: bool, default is False.
|
||||
:raises InvalidDimensionException: Dimensions do not match.
|
||||
@@ -200,14 +205,21 @@ class ChromaDB(BaseVectorDB):
|
||||
along with url of the source and doc_id (if citations flag is true)
|
||||
:rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]]
|
||||
"""
|
||||
if where and raw_filter:
|
||||
raise ValueError("Both `where` and `raw_filter` cannot be used together.")
|
||||
|
||||
where_clause = {}
|
||||
if raw_filter:
|
||||
where_clause = raw_filter
|
||||
if where:
|
||||
where_clause = self._generate_where_clause(where)
|
||||
try:
|
||||
result = self.collection.query(
|
||||
query_texts=[
|
||||
input_query,
|
||||
],
|
||||
n_results=n_results,
|
||||
where=self._generate_where_clause(where),
|
||||
**kwargs,
|
||||
where=where_clause,
|
||||
)
|
||||
except InvalidDimensionException as e:
|
||||
raise InvalidDimensionException(
|
||||
|
||||
@@ -99,14 +99,24 @@ class ElasticsearchDB(BaseVectorDB):
|
||||
query = {"bool": {"must": [{"ids": {"values": ids}}]}}
|
||||
else:
|
||||
query = {"bool": {"must": []}}
|
||||
if "app_id" in where:
|
||||
app_id = where["app_id"]
|
||||
query["bool"]["must"].append({"term": {"metadata.app_id": app_id}})
|
||||
|
||||
response = self.client.search(index=self._get_index(), query=query, _source=False, size=limit)
|
||||
if where:
|
||||
for key, value in where.items():
|
||||
query["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}})
|
||||
|
||||
response = self.client.search(index=self._get_index(), query=query, _source=True, size=limit)
|
||||
docs = response["hits"]["hits"]
|
||||
ids = [doc["_id"] for doc in docs]
|
||||
return {"ids": set(ids)}
|
||||
doc_ids = [doc["_source"]["metadata"]["doc_id"] for doc in docs]
|
||||
|
||||
# Result is modified for compatibility with other vector databases
|
||||
# TODO: Add method in vector database to return result in a standard format
|
||||
result = {"ids": ids, "metadatas": []}
|
||||
|
||||
for doc_id in doc_ids:
|
||||
result["metadatas"].append({"doc_id": doc_id})
|
||||
|
||||
return result
|
||||
|
||||
def add(
|
||||
self,
|
||||
@@ -186,9 +196,11 @@ class ElasticsearchDB(BaseVectorDB):
|
||||
},
|
||||
}
|
||||
}
|
||||
if "app_id" in where:
|
||||
app_id = where["app_id"]
|
||||
query["script_score"]["query"] = {"match": {"metadata.app_id": app_id}}
|
||||
|
||||
if where:
|
||||
for key, value in where.items():
|
||||
query["script_score"]["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}})
|
||||
|
||||
_source = ["text", "metadata"]
|
||||
response = self.client.search(index=self._get_index(), query=query, _source=_source, size=n_results)
|
||||
docs = response["hits"]["hits"]
|
||||
@@ -244,3 +256,11 @@ class ElasticsearchDB(BaseVectorDB):
|
||||
# NOTE: The method is preferred to an attribute, because if collection name changes,
|
||||
# it's always up-to-date.
|
||||
return f"{self.config.collection_name}_{self.embedder.vector_dimension}".lower()
|
||||
|
||||
def delete(self, where):
|
||||
"""Delete documents from the database."""
|
||||
query = {"query": {"bool": {"must": []}}}
|
||||
for key, value in where.items():
|
||||
query["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}})
|
||||
self.client.delete_by_query(index=self._get_index(), body=query)
|
||||
self.client.indices.refresh(index=self._get_index())
|
||||
|
||||
@@ -12,8 +12,8 @@ except ImportError:
|
||||
"OpenSearch requires extra dependencies. Install with `pip install --upgrade embedchain[opensearch]`"
|
||||
) from None
|
||||
|
||||
from langchain.embeddings.openai import OpenAIEmbeddings
|
||||
from langchain.vectorstores import OpenSearchVectorSearch
|
||||
from langchain_community.embeddings.openai import OpenAIEmbeddings
|
||||
from langchain_community.vectorstores import OpenSearchVectorSearch
|
||||
|
||||
from embedchain.config import OpenSearchDBConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
@@ -96,9 +96,9 @@ class OpenSearchDB(BaseVectorDB):
|
||||
else:
|
||||
query["query"] = {"bool": {"must": []}}
|
||||
|
||||
if "app_id" in where:
|
||||
app_id = where["app_id"]
|
||||
query["query"]["bool"]["must"].append({"term": {"metadata.app_id.keyword": app_id}})
|
||||
if where:
|
||||
for key, value in where.items():
|
||||
query["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}})
|
||||
|
||||
# OpenSearch syntax is different from Elasticsearch
|
||||
response = self.client.search(index=self._get_index(), body=query, _source=True, size=limit)
|
||||
@@ -176,9 +176,11 @@ class OpenSearchDB(BaseVectorDB):
|
||||
)
|
||||
|
||||
pre_filter = {"match_all": {}} # default
|
||||
if "app_id" in where:
|
||||
app_id = where["app_id"]
|
||||
pre_filter = {"bool": {"must": [{"term": {"metadata.app_id.keyword": app_id}}]}}
|
||||
if len(where) > 0:
|
||||
pre_filter = {"bool": {"must": []}}
|
||||
for key, value in where.items():
|
||||
pre_filter["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}})
|
||||
|
||||
docs = docsearch.similarity_search_with_score(
|
||||
input_query,
|
||||
search_type="script_scoring",
|
||||
@@ -236,10 +238,9 @@ class OpenSearchDB(BaseVectorDB):
|
||||
|
||||
def delete(self, where):
|
||||
"""Deletes a document from the OpenSearch index"""
|
||||
if "doc_id" not in where:
|
||||
raise ValueError("doc_id is required to delete a document")
|
||||
|
||||
query = {"query": {"bool": {"must": [{"term": {"metadata.doc_id": where["doc_id"]}}]}}}
|
||||
query = {"query": {"bool": {"must": []}}}
|
||||
for key, value in where.items():
|
||||
query["query"]["bool"]["must"].append({"term": {f"metadata.{key}.keyword": value}})
|
||||
self.client.delete_by_query(index=self._get_index(), body=query)
|
||||
|
||||
def _get_index(self) -> str:
|
||||
|
||||
@@ -41,7 +41,7 @@ class PineconeDB(BaseVectorDB):
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
self.config = config
|
||||
self.client = self._setup_pinecone_index()
|
||||
self._setup_pinecone_index()
|
||||
# Call parent init here because embedder is needed
|
||||
super().__init__(config=self.config)
|
||||
|
||||
@@ -52,20 +52,30 @@ class PineconeDB(BaseVectorDB):
|
||||
if not self.embedder:
|
||||
raise ValueError("Embedder not set. Please set an embedder with `set_embedder` before initialization.")
|
||||
|
||||
# Loads the Pinecone index or creates it if not present.
|
||||
def _setup_pinecone_index(self):
|
||||
pinecone.init(
|
||||
api_key=os.environ.get("PINECONE_API_KEY"),
|
||||
environment=os.environ.get("PINECONE_ENV"),
|
||||
**self.config.extra_params,
|
||||
)
|
||||
self.index_name = self._get_index_name()
|
||||
indexes = pinecone.list_indexes()
|
||||
if indexes is None or self.index_name not in indexes:
|
||||
pinecone.create_index(
|
||||
name=self.index_name, metric=self.config.metric, dimension=self.config.vector_dimension
|
||||
"""
|
||||
Loads the Pinecone index or creates it if not present.
|
||||
"""
|
||||
api_key = self.config.api_key or os.environ.get("PINECONE_API_KEY")
|
||||
if not api_key:
|
||||
raise ValueError("Please set the PINECONE_API_KEY environment variable or pass it in config.")
|
||||
self.client = pinecone.Pinecone(api_key=api_key, **self.config.extra_params)
|
||||
indexes = self.client.list_indexes().names()
|
||||
if indexes is None or self.config.index_name not in indexes:
|
||||
if self.config.pod_config:
|
||||
spec = pinecone.PodSpec(**self.config.pod_config)
|
||||
elif self.config.serverless_config:
|
||||
spec = pinecone.ServerlessSpec(**self.config.serverless_config)
|
||||
else:
|
||||
raise ValueError("No pod_config or serverless_config found.")
|
||||
|
||||
self.client.create_index(
|
||||
name=self.config.index_name,
|
||||
metric=self.config.metric,
|
||||
dimension=self.config.vector_dimension,
|
||||
spec=spec,
|
||||
)
|
||||
return pinecone.Index(self.index_name)
|
||||
self.pinecone_index = self.client.Index(self.config.index_name)
|
||||
|
||||
def get(self, ids: Optional[list[str]] = None, where: Optional[dict[str, any]] = None, limit: Optional[int] = None):
|
||||
"""
|
||||
@@ -79,12 +89,16 @@ class PineconeDB(BaseVectorDB):
|
||||
:rtype: Set[str]
|
||||
"""
|
||||
existing_ids = list()
|
||||
metadatas = []
|
||||
|
||||
if ids is not None:
|
||||
for i in range(0, len(ids), 1000):
|
||||
result = self.client.fetch(ids=ids[i : i + 1000])
|
||||
batch_existing_ids = list(result.get("vectors").keys())
|
||||
result = self.pinecone_index.fetch(ids=ids[i : i + 1000])
|
||||
vectors = result.get("vectors")
|
||||
batch_existing_ids = list(vectors.keys())
|
||||
existing_ids.extend(batch_existing_ids)
|
||||
return {"ids": existing_ids}
|
||||
metadatas.extend([vectors.get(ids).get("metadata") for ids in batch_existing_ids])
|
||||
return {"ids": existing_ids, "metadatas": metadatas}
|
||||
|
||||
def add(
|
||||
self,
|
||||
@@ -103,7 +117,6 @@ class PineconeDB(BaseVectorDB):
|
||||
:type ids: list[str]
|
||||
"""
|
||||
docs = []
|
||||
print("Adding documents to Pinecone...")
|
||||
embeddings = self.embedder.embedding_fn(documents)
|
||||
for id, text, metadata, embedding in zip(ids, documents, metadatas, embeddings):
|
||||
docs.append(
|
||||
@@ -114,43 +127,51 @@ class PineconeDB(BaseVectorDB):
|
||||
}
|
||||
)
|
||||
|
||||
for chunk in chunks(docs, self.BATCH_SIZE, desc="Adding chunks in batches..."):
|
||||
self.client.upsert(chunk, **kwargs)
|
||||
for chunk in chunks(docs, self.BATCH_SIZE, desc="Adding chunks in batches"):
|
||||
self.pinecone_index.upsert(chunk, **kwargs)
|
||||
|
||||
def query(
|
||||
self,
|
||||
input_query: list[str],
|
||||
n_results: int,
|
||||
where: dict[str, any],
|
||||
where: Optional[dict[str, any]] = None,
|
||||
raw_filter: Optional[dict[str, any]] = None,
|
||||
citations: bool = False,
|
||||
app_id: Optional[str] = None,
|
||||
**kwargs: Optional[dict[str, any]],
|
||||
) -> Union[list[tuple[str, dict]], list[str]]:
|
||||
"""
|
||||
query contents from vector database based on vector similarity
|
||||
:param input_query: list of query string
|
||||
:type input_query: list[str]
|
||||
:param n_results: no of similar documents to fetch from database
|
||||
:type n_results: int
|
||||
:param where: Optional. to filter data
|
||||
:type where: dict[str, any]
|
||||
:param citations: we use citations boolean param to return context along with the answer.
|
||||
:type citations: bool, default is False.
|
||||
:return: The content of the document that matched your query,
|
||||
along with url of the source and doc_id (if citations flag is true)
|
||||
:rtype: list[str], if citations=False, otherwise list[tuple[str, str, str]]
|
||||
Query contents from vector database based on vector similarity.
|
||||
|
||||
Args:
|
||||
input_query (list[str]): List of query strings.
|
||||
n_results (int): Number of similar documents to fetch from the database.
|
||||
where (dict[str, any], optional): Filter criteria for the search.
|
||||
raw_filter (dict[str, any], optional): Advanced raw filter criteria for the search.
|
||||
citations (bool, optional): Flag to return context along with metadata. Defaults to False.
|
||||
app_id (str, optional): Application ID to be passed to Pinecone.
|
||||
|
||||
Returns:
|
||||
Union[list[tuple[str, dict]], list[str]]: List of document contexts, optionally with metadata.
|
||||
"""
|
||||
query_filter = raw_filter if raw_filter is not None else self._generate_filter(where)
|
||||
if app_id:
|
||||
query_filter["app_id"] = {"$eq": app_id}
|
||||
|
||||
query_vector = self.embedder.embedding_fn([input_query])[0]
|
||||
data = self.client.query(vector=query_vector, filter=where, top_k=n_results, include_metadata=True, **kwargs)
|
||||
contexts = []
|
||||
for doc in data["matches"]:
|
||||
metadata = doc["metadata"]
|
||||
context = metadata["text"]
|
||||
if citations:
|
||||
metadata["score"] = doc["score"]
|
||||
contexts.append(tuple((context, metadata)))
|
||||
else:
|
||||
contexts.append(context)
|
||||
return contexts
|
||||
data = self.pinecone_index.query(
|
||||
vector=query_vector,
|
||||
filter=query_filter,
|
||||
top_k=n_results,
|
||||
include_metadata=True,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
return [
|
||||
(metadata.get("text"), {**metadata, "score": doc.get("score")}) if citations else metadata.get("text")
|
||||
for doc in data.get("matches", [])
|
||||
for metadata in [doc.get("metadata", {})]
|
||||
]
|
||||
|
||||
def set_collection_name(self, name: str):
|
||||
"""
|
||||
@@ -170,7 +191,8 @@ class PineconeDB(BaseVectorDB):
|
||||
:return: number of documents
|
||||
:rtype: int
|
||||
"""
|
||||
return self.client.describe_index_stats()["total_vector_count"]
|
||||
data = self.pinecone_index.describe_index_stats()
|
||||
return data["total_vector_count"]
|
||||
|
||||
def _get_or_create_db(self):
|
||||
"""Called during initialization"""
|
||||
@@ -181,14 +203,26 @@ class PineconeDB(BaseVectorDB):
|
||||
Resets the database. Deletes all embeddings irreversibly.
|
||||
"""
|
||||
# Delete all data from the database
|
||||
pinecone.delete_index(self.index_name)
|
||||
self.client.delete_index(self.config.index_name)
|
||||
self._setup_pinecone_index()
|
||||
|
||||
# Pinecone only allows alphanumeric characters and "-" in the index name
|
||||
def _get_index_name(self) -> str:
|
||||
"""Get the Pinecone index for a collection
|
||||
@staticmethod
|
||||
def _generate_filter(where: dict):
|
||||
query = {}
|
||||
for k, v in where.items():
|
||||
query[k] = {"$eq": v}
|
||||
return query
|
||||
|
||||
:return: Pinecone index
|
||||
:rtype: str
|
||||
def delete(self, where: dict):
|
||||
"""Delete from database.
|
||||
:param ids: list of ids to delete
|
||||
:type ids: list[str]
|
||||
"""
|
||||
return f"{self.config.collection_name}-{self.config.vector_dimension}".lower().replace("_", "-")
|
||||
# Deleting with filters is not supported for `starter` index type.
|
||||
# Follow `https://docs.pinecone.io/docs/metadata-filtering#deleting-vectors-by-metadata-filter` for more details
|
||||
db_filter = self._generate_filter(where)
|
||||
try:
|
||||
self.pinecone_index.delete(filter=db_filter)
|
||||
except Exception as e:
|
||||
print(f"Failed to delete from Pinecone: {e}")
|
||||
return
|
||||
|
||||
@@ -11,6 +11,8 @@ try:
|
||||
except ImportError:
|
||||
raise ImportError("Qdrant requires extra dependencies. Install with `pip install embedchain[qdrant]`") from None
|
||||
|
||||
from tqdm import tqdm
|
||||
|
||||
from embedchain.config.vectordb.qdrant import QdrantDBConfig
|
||||
from embedchain.vectordb.base import BaseVectorDB
|
||||
|
||||
@@ -48,7 +50,6 @@ class QdrantDB(BaseVectorDB):
|
||||
raise ValueError("Embedder not set. Please set an embedder with `set_embedder` before initialization.")
|
||||
|
||||
self.collection_name = self._get_or_create_collection()
|
||||
self.metadata_keys = {"data_type", "doc_id", "url", "hash", "app_id", "text"}
|
||||
all_collections = self.client.get_collections()
|
||||
collection_names = [collection.name for collection in all_collections.collections]
|
||||
if self.collection_name not in collection_names:
|
||||
@@ -82,21 +83,23 @@ class QdrantDB(BaseVectorDB):
|
||||
:return: All the existing IDs
|
||||
:rtype: Set[str]
|
||||
"""
|
||||
if ids is None or len(ids) == 0:
|
||||
return {"ids": []}
|
||||
|
||||
keys = set(where.keys() if where is not None else set())
|
||||
|
||||
qdrant_must_filters = [
|
||||
models.FieldCondition(
|
||||
key="identifier",
|
||||
match=models.MatchAny(
|
||||
any=ids,
|
||||
),
|
||||
qdrant_must_filters = []
|
||||
|
||||
if ids:
|
||||
qdrant_must_filters.append(
|
||||
models.FieldCondition(
|
||||
key="identifier",
|
||||
match=models.MatchAny(
|
||||
any=ids,
|
||||
),
|
||||
)
|
||||
)
|
||||
]
|
||||
if len(keys.intersection(self.metadata_keys)) != 0:
|
||||
for key in keys.intersection(self.metadata_keys):
|
||||
|
||||
if len(keys) > 0:
|
||||
for key in keys:
|
||||
qdrant_must_filters.append(
|
||||
models.FieldCondition(
|
||||
key="metadata.{}".format(key),
|
||||
@@ -108,6 +111,7 @@ class QdrantDB(BaseVectorDB):
|
||||
|
||||
offset = 0
|
||||
existing_ids = []
|
||||
metadatas = []
|
||||
while offset is not None:
|
||||
response = self.client.scroll(
|
||||
collection_name=self.collection_name,
|
||||
@@ -118,7 +122,8 @@ class QdrantDB(BaseVectorDB):
|
||||
offset = response[1]
|
||||
for doc in response[0]:
|
||||
existing_ids.append(doc.payload["identifier"])
|
||||
return {"ids": existing_ids}
|
||||
metadatas.append(doc.payload["metadata"])
|
||||
return {"ids": existing_ids, "metadatas": metadatas}
|
||||
|
||||
def add(
|
||||
self,
|
||||
@@ -143,7 +148,8 @@ class QdrantDB(BaseVectorDB):
|
||||
metadata["text"] = document
|
||||
qdrant_ids.append(str(uuid.uuid4()))
|
||||
payloads.append({"identifier": id, "text": document, "metadata": copy.deepcopy(metadata)})
|
||||
for i in range(0, len(qdrant_ids), self.BATCH_SIZE):
|
||||
|
||||
for i in tqdm(range(0, len(qdrant_ids), self.BATCH_SIZE), desc="Adding data in batches"):
|
||||
self.client.upsert(
|
||||
collection_name=self.collection_name,
|
||||
points=Batch(
|
||||
@@ -180,16 +186,17 @@ class QdrantDB(BaseVectorDB):
|
||||
keys = set(where.keys() if where is not None else set())
|
||||
|
||||
qdrant_must_filters = []
|
||||
if len(keys.intersection(self.metadata_keys)) != 0:
|
||||
for key in keys.intersection(self.metadata_keys):
|
||||
if len(keys) > 0:
|
||||
for key in keys:
|
||||
qdrant_must_filters.append(
|
||||
models.FieldCondition(
|
||||
key="payload.metadata.{}".format(key),
|
||||
key="metadata.{}".format(key),
|
||||
match=models.MatchValue(
|
||||
value=where.get(key),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
results = self.client.search(
|
||||
collection_name=self.collection_name,
|
||||
query_filter=models.Filter(must=qdrant_must_filters),
|
||||
@@ -228,3 +235,21 @@ class QdrantDB(BaseVectorDB):
|
||||
raise TypeError("Collection name must be a string")
|
||||
self.config.collection_name = name
|
||||
self.collection_name = self._get_or_create_collection()
|
||||
|
||||
@staticmethod
|
||||
def _generate_query(where: dict):
|
||||
must_fields = []
|
||||
for key, value in where.items():
|
||||
must_fields.append(
|
||||
models.FieldCondition(
|
||||
key=f"metadata.{key}",
|
||||
match=models.MatchValue(
|
||||
value=value,
|
||||
),
|
||||
)
|
||||
)
|
||||
return models.Filter(must=must_fields)
|
||||
|
||||
def delete(self, where: dict):
|
||||
db_filter = self._generate_query(where)
|
||||
self.client.delete(collection_name=self.collection_name, points_selector=db_filter)
|
||||
|
||||
@@ -45,6 +45,9 @@ class WeaviateDB(BaseVectorDB):
|
||||
auth_client_secret=weaviate.AuthApiKey(api_key=os.environ.get("WEAVIATE_API_KEY")),
|
||||
**self.config.extra_params,
|
||||
)
|
||||
# Since weaviate uses graphQL, we need to keep track of metadata keys added in the vectordb.
|
||||
# This is needed to filter data while querying.
|
||||
self.metadata_keys = {"data_type", "doc_id", "url", "hash", "app_id"}
|
||||
|
||||
# Call parent init here because embedder is needed
|
||||
super().__init__(config=self.config)
|
||||
@@ -58,7 +61,6 @@ class WeaviateDB(BaseVectorDB):
|
||||
raise ValueError("Embedder not set. Please set an embedder with `set_embedder` before initialization.")
|
||||
|
||||
self.index_name = self._get_index_name()
|
||||
self.metadata_keys = {"data_type", "doc_id", "url", "hash", "app_id"}
|
||||
if not self.client.schema.exists(self.index_name):
|
||||
# id is a reserved field in Weaviate, hence we had to change the name of the id field to identifier
|
||||
# The none vectorizer is crucial as we have our own custom embedding function
|
||||
@@ -127,29 +129,64 @@ class WeaviateDB(BaseVectorDB):
|
||||
:return: ids
|
||||
:rtype: Set[str]
|
||||
"""
|
||||
weaviate_where_operands = []
|
||||
|
||||
if ids is None or len(ids) == 0:
|
||||
return {"ids": []}
|
||||
if ids:
|
||||
for doc_id in ids:
|
||||
weaviate_where_operands.append({"path": ["identifier"], "operator": "Equal", "valueText": doc_id})
|
||||
|
||||
keys = set(where.keys() if where is not None else set())
|
||||
if len(keys) > 0:
|
||||
for key in keys:
|
||||
weaviate_where_operands.append(
|
||||
{
|
||||
"path": ["metadata", self.index_name + "_metadata", key],
|
||||
"operator": "Equal",
|
||||
"valueText": where.get(key),
|
||||
}
|
||||
)
|
||||
|
||||
if len(weaviate_where_operands) == 1:
|
||||
weaviate_where_clause = weaviate_where_operands[0]
|
||||
else:
|
||||
weaviate_where_clause = {"operator": "And", "operands": weaviate_where_operands}
|
||||
|
||||
existing_ids = []
|
||||
metadatas = []
|
||||
cursor = None
|
||||
offset = 0
|
||||
has_iterated_once = False
|
||||
query_metadata_keys = self.metadata_keys.union(keys)
|
||||
while cursor is not None or not has_iterated_once:
|
||||
has_iterated_once = True
|
||||
results = self._query_with_cursor(
|
||||
self.client.query.get(self.index_name, ["identifier"])
|
||||
results = self._query_with_offset(
|
||||
self.client.query.get(
|
||||
self.index_name,
|
||||
[
|
||||
"identifier",
|
||||
weaviate.LinkTo("metadata", self.index_name + "_metadata", list(query_metadata_keys)),
|
||||
],
|
||||
)
|
||||
.with_where(weaviate_where_clause)
|
||||
.with_additional(["id"])
|
||||
.with_limit(self.BATCH_SIZE),
|
||||
cursor,
|
||||
.with_limit(limit or self.BATCH_SIZE),
|
||||
offset,
|
||||
)
|
||||
|
||||
fetched_results = results["data"]["Get"].get(self.index_name, [])
|
||||
if len(fetched_results) == 0:
|
||||
if not fetched_results:
|
||||
break
|
||||
|
||||
for result in fetched_results:
|
||||
existing_ids.append(result["identifier"])
|
||||
metadatas.append(result["metadata"][0])
|
||||
cursor = result["_additional"]["id"]
|
||||
offset += 1
|
||||
|
||||
return {"ids": existing_ids}
|
||||
if limit is not None and len(existing_ids) >= limit:
|
||||
break
|
||||
|
||||
return {"ids": existing_ids, "metadatas": metadatas}
|
||||
|
||||
def add(self, documents: list[str], metadatas: list[object], ids: list[str], **kwargs: Optional[dict[str, any]]):
|
||||
"""add data in vector database
|
||||
@@ -201,21 +238,20 @@ class WeaviateDB(BaseVectorDB):
|
||||
query_vector = self.embedder.embedding_fn([input_query])[0]
|
||||
keys = set(where.keys() if where is not None else set())
|
||||
data_fields = ["text"]
|
||||
|
||||
query_metadata_keys = self.metadata_keys.union(keys)
|
||||
if citations:
|
||||
data_fields.append(weaviate.LinkTo("metadata", self.index_name + "_metadata", list(self.metadata_keys)))
|
||||
data_fields.append(weaviate.LinkTo("metadata", self.index_name + "_metadata", list(query_metadata_keys)))
|
||||
|
||||
if len(keys.intersection(self.metadata_keys)) != 0:
|
||||
if len(keys) > 0:
|
||||
weaviate_where_operands = []
|
||||
for key in keys:
|
||||
if key in self.metadata_keys:
|
||||
weaviate_where_operands.append(
|
||||
{
|
||||
"path": ["metadata", self.index_name + "_metadata", key],
|
||||
"operator": "Equal",
|
||||
"valueText": where.get(key),
|
||||
}
|
||||
)
|
||||
weaviate_where_operands.append(
|
||||
{
|
||||
"path": ["metadata", self.index_name + "_metadata", key],
|
||||
"operator": "Equal",
|
||||
"valueText": where.get(key),
|
||||
}
|
||||
)
|
||||
if len(weaviate_where_operands) == 1:
|
||||
weaviate_where_clause = weaviate_where_operands[0]
|
||||
else:
|
||||
@@ -238,6 +274,9 @@ class WeaviateDB(BaseVectorDB):
|
||||
.do()
|
||||
)
|
||||
|
||||
if results["data"]["Get"].get(self.index_name) is None:
|
||||
return []
|
||||
|
||||
docs = results["data"]["Get"].get(self.index_name)
|
||||
contexts = []
|
||||
for doc in docs:
|
||||
@@ -289,11 +328,37 @@ class WeaviateDB(BaseVectorDB):
|
||||
:return: Weaviate index
|
||||
:rtype: str
|
||||
"""
|
||||
return f"{self.config.collection_name}_{self.embedder.vector_dimension}".capitalize()
|
||||
return f"{self.config.collection_name}_{self.embedder.vector_dimension}".capitalize().replace("-", "_")
|
||||
|
||||
@staticmethod
|
||||
def _query_with_cursor(query, cursor):
|
||||
if cursor is not None:
|
||||
query.with_after(cursor)
|
||||
def _query_with_offset(query, offset):
|
||||
if offset:
|
||||
query.with_offset(offset)
|
||||
results = query.do()
|
||||
return results
|
||||
|
||||
def _generate_query(self, where: dict):
|
||||
weaviate_where_operands = []
|
||||
for key, value in where.items():
|
||||
weaviate_where_operands.append(
|
||||
{
|
||||
"path": ["metadata", self.index_name + "_metadata", key],
|
||||
"operator": "Equal",
|
||||
"valueText": value,
|
||||
}
|
||||
)
|
||||
|
||||
if len(weaviate_where_operands) == 1:
|
||||
weaviate_where_clause = weaviate_where_operands[0]
|
||||
else:
|
||||
weaviate_where_clause = {"operator": "And", "operands": weaviate_where_operands}
|
||||
|
||||
return weaviate_where_clause
|
||||
|
||||
def delete(self, where: dict):
|
||||
"""Delete from database.
|
||||
:param where: to filter data
|
||||
:type where: dict[str, any]
|
||||
"""
|
||||
query = self._generate_query(where)
|
||||
self.client.batch.delete_objects(self.index_name, where=query)
|
||||
|
||||
@@ -69,6 +69,7 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
FieldSchema(name="id", dtype=DataType.VARCHAR, is_primary=True, max_length=512),
|
||||
FieldSchema(name="text", dtype=DataType.VARCHAR, max_length=2048),
|
||||
FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=self.embedder.vector_dimension),
|
||||
FieldSchema(name="metadata", dtype=DataType.JSON),
|
||||
]
|
||||
|
||||
schema = CollectionSchema(fields, enable_dynamic_field=True)
|
||||
@@ -94,17 +95,26 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
:return: Existing documents.
|
||||
:rtype: Set[str]
|
||||
"""
|
||||
if ids is None or len(ids) == 0 or self.collection.num_entities == 0:
|
||||
return {"ids": []}
|
||||
data_ids = []
|
||||
metadatas = []
|
||||
if self.collection.num_entities == 0 or self.collection.is_empty:
|
||||
return {"ids": data_ids, "metadatas": metadatas}
|
||||
|
||||
if not self.collection.is_empty:
|
||||
filter_ = f"id in {ids}"
|
||||
results = self.client.query(
|
||||
collection_name=self.config.collection_name, filter=filter_, output_fields=["id"]
|
||||
)
|
||||
results = [res["id"] for res in results]
|
||||
filter_ = ""
|
||||
if ids:
|
||||
filter_ = f'id in "{ids}"'
|
||||
|
||||
return {"ids": set(results)}
|
||||
if where:
|
||||
if filter_:
|
||||
filter_ += " and "
|
||||
filter_ = f"{self._generate_zilliz_filter(where)}"
|
||||
|
||||
results = self.client.query(collection_name=self.config.collection_name, filter=filter_, output_fields=["*"])
|
||||
for res in results:
|
||||
data_ids.append(res.get("id"))
|
||||
metadatas.append(res.get("metadata", {}))
|
||||
|
||||
return {"ids": data_ids, "metadatas": metadatas}
|
||||
|
||||
def add(
|
||||
self,
|
||||
@@ -117,7 +127,7 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
embeddings = self.embedder.embedding_fn(documents)
|
||||
|
||||
for id, doc, metadata, embedding in zip(ids, documents, metadatas, embeddings):
|
||||
data = {**metadata, "id": id, "text": doc, "embeddings": embedding}
|
||||
data = {"id": id, "text": doc, "embeddings": embedding, "metadata": metadata}
|
||||
self.client.insert(collection_name=self.config.collection_name, data=data, **kwargs)
|
||||
|
||||
self.collection.load()
|
||||
@@ -128,7 +138,7 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
self,
|
||||
input_query: list[str],
|
||||
n_results: int,
|
||||
where: dict[str, any],
|
||||
where: dict[str, Any],
|
||||
citations: bool = False,
|
||||
**kwargs: Optional[dict[str, Any]],
|
||||
) -> Union[list[tuple[str, dict]], list[str]]:
|
||||
@@ -140,7 +150,7 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
:param n_results: no of similar documents to fetch from database
|
||||
:type n_results: int
|
||||
:param where: to filter data
|
||||
:type where: str
|
||||
:type where: dict[str, Any]
|
||||
:raises InvalidDimensionException: Dimensions do not match.
|
||||
:param citations: we use citations boolean param to return context along with the answer.
|
||||
:type citations: bool, default is False.
|
||||
@@ -152,16 +162,15 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
if self.collection.is_empty:
|
||||
return []
|
||||
|
||||
if not isinstance(where, str):
|
||||
where = None
|
||||
|
||||
output_fields = ["*"]
|
||||
input_query_vector = self.embedder.embedding_fn([input_query])
|
||||
query_vector = input_query_vector[0]
|
||||
|
||||
query_filter = self._generate_zilliz_filter(where)
|
||||
query_result = self.client.search(
|
||||
collection_name=self.config.collection_name,
|
||||
data=[query_vector],
|
||||
filter=query_filter,
|
||||
limit=n_results,
|
||||
output_fields=output_fields,
|
||||
**kwargs,
|
||||
@@ -173,12 +182,10 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
score = query["distance"]
|
||||
context = data["text"]
|
||||
|
||||
if "embeddings" in data:
|
||||
data.pop("embeddings")
|
||||
|
||||
if citations:
|
||||
data["score"] = score
|
||||
contexts.append(tuple((context, data)))
|
||||
metadata = data.get("metadata", {})
|
||||
metadata["score"] = score
|
||||
contexts.append(tuple((context, metadata)))
|
||||
else:
|
||||
contexts.append(context)
|
||||
return contexts
|
||||
@@ -216,7 +223,13 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
raise TypeError("Collection name must be a string")
|
||||
self.config.collection_name = name
|
||||
|
||||
def delete(self, keys: Union[list, str, int]):
|
||||
def _generate_zilliz_filter(self, where: dict[str, str]):
|
||||
operands = []
|
||||
for key, value in where.items():
|
||||
operands.append(f'(metadata["{key}"] == "{value}")')
|
||||
return " and ".join(operands)
|
||||
|
||||
def delete(self, where: dict[str, Any]):
|
||||
"""
|
||||
Delete the embeddings from DB. Zilliz only support deleting with keys.
|
||||
|
||||
@@ -224,7 +237,7 @@ class ZillizVectorDB(BaseVectorDB):
|
||||
:param keys: Primary keys of the table entries to delete.
|
||||
:type keys: Union[list, str, int]
|
||||
"""
|
||||
self.client.delete(
|
||||
collection_name=self.config.collection_name,
|
||||
pks=keys,
|
||||
)
|
||||
data = self.get(where=where)
|
||||
keys = data.get("ids", [])
|
||||
if keys:
|
||||
self.client.delete(collection_name=self.config.collection_name, pks=keys)
|
||||
|
||||
@@ -72,13 +72,15 @@
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"app = App.from_config(config={\n",
|
||||
" \"provider\": \"chroma\",\n",
|
||||
" \"config\": {\n",
|
||||
" \"collection_name\": \"my-collection\",\n",
|
||||
" \"host\": \"your-chromadb-url.com\",\n",
|
||||
" \"port\": 5200,\n",
|
||||
" \"allow_reset\": True\n",
|
||||
" }\n",
|
||||
" \"vectordb\": {\n",
|
||||
" \"provider\": \"chroma\",\n",
|
||||
" \"config\": {\n",
|
||||
" \"collection_name\": \"my-collection\",\n",
|
||||
" \"host\": \"your-chromadb-url.com\",\n",
|
||||
" \"port\": 5200,\n",
|
||||
" \"allow_reset\": True\n",
|
||||
" }\n",
|
||||
" }\n",
|
||||
"})"
|
||||
]
|
||||
},
|
||||
|
||||
Generated
+379
-227
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiofiles"
|
||||
@@ -333,26 +333,6 @@ description = "The uncompromising code formatter."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"},
|
||||
{file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"},
|
||||
{file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"},
|
||||
{file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"},
|
||||
{file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"},
|
||||
{file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"},
|
||||
{file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"},
|
||||
{file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"},
|
||||
{file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"},
|
||||
{file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"},
|
||||
{file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"},
|
||||
{file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"},
|
||||
{file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"},
|
||||
{file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"},
|
||||
{file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"},
|
||||
{file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"},
|
||||
{file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"},
|
||||
{file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"},
|
||||
{file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"},
|
||||
{file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"},
|
||||
{file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"},
|
||||
{file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"},
|
||||
]
|
||||
@@ -383,6 +363,47 @@ files = [
|
||||
{file = "blinker-1.6.3.tar.gz", hash = "sha256:152090d27c1c5c722ee7e48504b02d76502811ce02e1523553b4cf8c8b3d3a8d"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "boto3"
|
||||
version = "1.34.22"
|
||||
description = "The AWS SDK for Python"
|
||||
optional = true
|
||||
python-versions = ">= 3.8"
|
||||
files = [
|
||||
{file = "boto3-1.34.22-py3-none-any.whl", hash = "sha256:5909cd1393143576265c692e908a9ae495492c04a0ffd4bae8578adc2e44729e"},
|
||||
{file = "boto3-1.34.22.tar.gz", hash = "sha256:a98c0b86f6044ff8314cc2361e1ef574d674318313ab5606ccb4a6651c7a3f8c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
botocore = ">=1.34.22,<1.35.0"
|
||||
jmespath = ">=0.7.1,<2.0.0"
|
||||
s3transfer = ">=0.10.0,<0.11.0"
|
||||
|
||||
[package.extras]
|
||||
crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
|
||||
|
||||
[[package]]
|
||||
name = "botocore"
|
||||
version = "1.34.22"
|
||||
description = "Low-level, data-driven core of boto 3."
|
||||
optional = true
|
||||
python-versions = ">= 3.8"
|
||||
files = [
|
||||
{file = "botocore-1.34.22-py3-none-any.whl", hash = "sha256:e5f7775975b9213507fbcf846a96b7a2aec2a44fc12a44585197b014a4ab0889"},
|
||||
{file = "botocore-1.34.22.tar.gz", hash = "sha256:c47ba4286c576150d1b6ca6df69a87b5deff3d23bd84da8bcf8431ebac3c40ba"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
jmespath = ">=0.7.1,<2.0.0"
|
||||
python-dateutil = ">=2.1,<3.0.0"
|
||||
urllib3 = [
|
||||
{version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""},
|
||||
{version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
crt = ["awscrt (==0.19.19)"]
|
||||
|
||||
[[package]]
|
||||
name = "brotli"
|
||||
version = "1.1.0"
|
||||
@@ -1219,25 +1240,6 @@ files = [
|
||||
{file = "distro-1.8.0.tar.gz", hash = "sha256:02e111d1dc6a50abb8eed6bf31c3e48ed8b0830d1ea2a1b78c61765c2513fdd8"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dnspython"
|
||||
version = "2.4.2"
|
||||
description = "DNS toolkit"
|
||||
optional = true
|
||||
python-versions = ">=3.8,<4.0"
|
||||
files = [
|
||||
{file = "dnspython-2.4.2-py3-none-any.whl", hash = "sha256:57c6fbaaeaaf39c891292012060beb141791735dbb4004798328fc2c467402d8"},
|
||||
{file = "dnspython-2.4.2.tar.gz", hash = "sha256:8dcfae8c7460a2f84b4072e26f1c9f4101ca20c071649cb7c34e8b6a93d58984"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dnssec = ["cryptography (>=2.6,<42.0)"]
|
||||
doh = ["h2 (>=4.1.0)", "httpcore (>=0.17.3)", "httpx (>=0.24.1)"]
|
||||
doq = ["aioquic (>=0.9.20)"]
|
||||
idna = ["idna (>=2.1,<4.0)"]
|
||||
trio = ["trio (>=0.14,<0.23)"]
|
||||
wmi = ["wmi (>=1.5.1,<2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "docx2txt"
|
||||
version = "0.8"
|
||||
@@ -1814,11 +1816,11 @@ files = [
|
||||
google-auth = ">=2.14.1,<3.0.dev0"
|
||||
googleapis-common-protos = ">=1.56.2,<2.0.dev0"
|
||||
grpcio = [
|
||||
{version = ">=1.33.2,<2.0dev", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""},
|
||||
{version = ">=1.33.2,<2.0dev", optional = true, markers = "extra == \"grpc\""},
|
||||
{version = ">=1.49.1,<2.0dev", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""},
|
||||
]
|
||||
grpcio-status = [
|
||||
{version = ">=1.33.2,<2.0.dev0", optional = true, markers = "python_version < \"3.11\" and extra == \"grpc\""},
|
||||
{version = ">=1.33.2,<2.0.dev0", optional = true, markers = "extra == \"grpc\""},
|
||||
{version = ">=1.49.1,<2.0.dev0", optional = true, markers = "python_version >= \"3.11\" and extra == \"grpc\""},
|
||||
]
|
||||
protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0"
|
||||
@@ -1905,13 +1907,13 @@ tool = ["click (>=6.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "google-cloud-aiplatform"
|
||||
version = "1.35.0"
|
||||
version = "1.41.0"
|
||||
description = "Vertex AI API client library"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "google-cloud-aiplatform-1.35.0.tar.gz", hash = "sha256:37fba7528739097463331d19695aab636286b029c7d0a0c021620d30d314015c"},
|
||||
{file = "google_cloud_aiplatform-1.35.0-py2.py3-none-any.whl", hash = "sha256:95c8e16d3beb296b2d47d3899226f1bfc9663bc4c9eea8260c5fb7612b9b44b9"},
|
||||
{file = "google-cloud-aiplatform-1.41.0.tar.gz", hash = "sha256:ffd049cffa5b53e354a25a5c0b5560d8b2aa6ba30b1f93a4bd1d75a3338a667e"},
|
||||
{file = "google_cloud_aiplatform-1.41.0-py2.py3-none-any.whl", hash = "sha256:0af867c0f175c2639f1b68eaf9293e2fe8435aaf3b261fde6ec11fb8243a0442"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -1929,7 +1931,7 @@ autologging = ["mlflow (>=1.27.0,<=2.1.1)"]
|
||||
cloud-profiler = ["tensorboard-plugin-profile (>=2.4.0,<3.0.0dev)", "tensorflow (>=2.4.0,<3.0.0dev)", "werkzeug (>=2.0.0,<2.1.0dev)"]
|
||||
datasets = ["pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)"]
|
||||
endpoint = ["requests (>=2.28.1)"]
|
||||
full = ["cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.103.1)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (==0.0.11)", "google-vizier (==0.0.11)", "google-vizier (==0.0.4)", "google-vizier (>=0.1.6)", "httpx (>=0.23.0,<0.25.0)", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyyaml (==5.3.1)", "ray[default] (>=2.4,<2.5)", "ray[default] (>=2.5,<2.5.1)", "requests (>=2.28.1)", "starlette (>=0.17.1)", "tensorflow (>=2.3.0,<3.0.0dev)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)"]
|
||||
full = ["cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.103.1)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (>=0.1.6)", "httpx (>=0.23.0,<0.25.0)", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyyaml (==5.3.1)", "ray[default] (>=2.4,<2.5)", "ray[default] (>=2.5,<2.5.1)", "requests (>=2.28.1)", "starlette (>=0.17.1)", "tensorflow (>=2.3.0,<2.15.0)", "tensorflow (>=2.3.0,<3.0.0dev)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)"]
|
||||
lit = ["explainable-ai-sdk (>=1.0.0)", "lit-nlp (==0.4.0)", "pandas (>=1.0.0)", "tensorflow (>=2.3.0,<3.0.0dev)"]
|
||||
metadata = ["numpy (>=1.15.0)", "pandas (>=1.0.0)"]
|
||||
pipelines = ["pyyaml (==5.3.1)"]
|
||||
@@ -1937,9 +1939,9 @@ prediction = ["docker (>=5.0.3)", "fastapi (>=0.71.0,<0.103.1)", "httpx (>=0.23.
|
||||
preview = ["cloudpickle (<3.0)", "google-cloud-logging (<4.0)"]
|
||||
private-endpoints = ["requests (>=2.28.1)", "urllib3 (>=1.21.1,<1.27)"]
|
||||
ray = ["google-cloud-bigquery", "google-cloud-bigquery-storage", "pandas (>=1.0.0)", "pyarrow (>=6.0.1)", "pydantic (<2)", "ray[default] (>=2.4,<2.5)", "ray[default] (>=2.5,<2.5.1)"]
|
||||
tensorboard = ["tensorflow (>=2.3.0,<3.0.0dev)"]
|
||||
testing = ["bigframes", "cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.103.1)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (==0.0.11)", "google-vizier (==0.0.11)", "google-vizier (==0.0.4)", "google-vizier (>=0.1.6)", "grpcio-testing", "httpx (>=0.23.0,<0.25.0)", "ipython", "kfp", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyfakefs", "pytest-asyncio", "pytest-xdist", "pyyaml (==5.3.1)", "ray[default] (>=2.4,<2.5)", "ray[default] (>=2.5,<2.5.1)", "requests (>=2.28.1)", "requests-toolbelt (<1.0.0)", "scikit-learn", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<3.0.0dev)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.3.0,<=2.12.0)", "tensorflow (>=2.4.0,<3.0.0dev)", "torch (>=2.0.0,<2.1.0)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0dev)", "xgboost", "xgboost-ray"]
|
||||
vizier = ["google-vizier (==0.0.11)", "google-vizier (==0.0.11)", "google-vizier (==0.0.4)", "google-vizier (>=0.1.6)"]
|
||||
tensorboard = ["tensorflow (>=2.3.0,<2.15.0)"]
|
||||
testing = ["bigframes", "cloudpickle (<3.0)", "docker (>=5.0.3)", "explainable-ai-sdk (>=1.0.0)", "fastapi (>=0.71.0,<0.103.1)", "google-cloud-bigquery", "google-cloud-bigquery-storage", "google-cloud-logging (<4.0)", "google-vizier (>=0.1.6)", "grpcio-testing", "httpx (>=0.23.0,<0.25.0)", "ipython", "kfp (>=2.6.0,<3.0.0)", "lit-nlp (==0.4.0)", "mlflow (>=1.27.0,<=2.1.1)", "numpy (>=1.15.0)", "pandas (>=1.0.0)", "pyarrow (>=10.0.1)", "pyarrow (>=3.0.0,<8.0dev)", "pyarrow (>=6.0.1)", "pydantic (<2)", "pyfakefs", "pytest-asyncio", "pytest-xdist", "pyyaml (==5.3.1)", "ray[default] (>=2.4,<2.5)", "ray[default] (>=2.5,<2.5.1)", "requests (>=2.28.1)", "requests-toolbelt (<1.0.0)", "scikit-learn", "starlette (>=0.17.1)", "tensorboard-plugin-profile (>=2.4.0,<3.0.0dev)", "tensorflow (>=2.3.0,<2.15.0)", "tensorflow (>=2.3.0,<3.0.0dev)", "tensorflow (>=2.3.0,<=2.12.0)", "tensorflow (>=2.4.0,<3.0.0dev)", "torch (>=2.0.0,<2.1.0)", "urllib3 (>=1.21.1,<1.27)", "uvicorn[standard] (>=0.16.0)", "werkzeug (>=2.0.0,<2.1.0dev)", "xgboost", "xgboost-ray"]
|
||||
vizier = ["google-vizier (>=0.1.6)"]
|
||||
xai = ["tensorflow (>=2.3.0,<3.0.0dev)"]
|
||||
|
||||
[[package]]
|
||||
@@ -2017,13 +2019,13 @@ protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4
|
||||
|
||||
[[package]]
|
||||
name = "google-cloud-storage"
|
||||
version = "2.12.0"
|
||||
version = "2.14.0"
|
||||
description = "Google Cloud Storage API client library"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "google-cloud-storage-2.12.0.tar.gz", hash = "sha256:57c0bcda2f5e11f008a155d8636d8381d5abab46b58e0cae0e46dd5e595e6b46"},
|
||||
{file = "google_cloud_storage-2.12.0-py2.py3-none-any.whl", hash = "sha256:bc52563439d42981b6e21b071a76da2791672776eda3ba99d13a8061ebbd6e5e"},
|
||||
{file = "google-cloud-storage-2.14.0.tar.gz", hash = "sha256:2d23fcf59b55e7b45336729c148bb1c464468c69d5efbaee30f7201dd90eb97e"},
|
||||
{file = "google_cloud_storage-2.14.0-py2.py3-none-any.whl", hash = "sha256:8641243bbf2a2042c16a6399551fbb13f062cbc9a2de38d6c0bb5426962e9dbd"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -2234,7 +2236,7 @@ files = [
|
||||
{file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b72b802496cccbd9b31acea72b6f87e7771ccfd7f7927437d592e5c92ed703c"},
|
||||
{file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:527cd90ba3d8d7ae7dceb06fda619895768a46a1b4e423bdb24c1969823b8362"},
|
||||
{file = "greenlet-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:37f60b3a42d8b5499be910d1267b24355c495064f271cfe74bf28b17b099133c"},
|
||||
{file = "greenlet-3.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1482fba7fbed96ea7842b5a7fc11d61727e8be75a077e603e8ab49d24e234383"},
|
||||
{file = "greenlet-3.0.0-cp311-universal2-macosx_10_9_universal2.whl", hash = "sha256:c3692ecf3fe754c8c0f2c95ff19626584459eab110eaab66413b1e7425cd84e9"},
|
||||
{file = "greenlet-3.0.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:be557119bf467d37a8099d91fbf11b2de5eb1fd5fc5b91598407574848dc910f"},
|
||||
{file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04"},
|
||||
{file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2"},
|
||||
@@ -2244,6 +2246,7 @@ files = [
|
||||
{file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:952256c2bc5b4ee8df8dfc54fc4de330970bf5d79253c863fb5e6761f00dda35"},
|
||||
{file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:269d06fa0f9624455ce08ae0179430eea61085e3cf6457f05982b37fd2cefe17"},
|
||||
{file = "greenlet-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9adbd8ecf097e34ada8efde9b6fec4dd2a903b1e98037adf72d12993a1c80b51"},
|
||||
{file = "greenlet-3.0.0-cp312-universal2-macosx_10_9_universal2.whl", hash = "sha256:553d6fb2324e7f4f0899e5ad2c427a4579ed4873f42124beba763f16032959af"},
|
||||
{file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6b5ce7f40f0e2f8b88c28e6691ca6806814157ff05e794cdd161be928550f4c"},
|
||||
{file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810"},
|
||||
{file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7"},
|
||||
@@ -2487,24 +2490,24 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "httpcore"
|
||||
version = "0.18.0"
|
||||
version = "1.0.2"
|
||||
description = "A minimal low-level HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "httpcore-0.18.0-py3-none-any.whl", hash = "sha256:adc5398ee0a476567bf87467063ee63584a8bce86078bf748e48754f60202ced"},
|
||||
{file = "httpcore-0.18.0.tar.gz", hash = "sha256:13b5e5cd1dca1a6636a6aaea212b19f4f85cd88c366a2b82304181b769aab3c9"},
|
||||
{file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"},
|
||||
{file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anyio = ">=3.0,<5.0"
|
||||
certifi = "*"
|
||||
h11 = ">=0.13,<0.15"
|
||||
sniffio = "==1.*"
|
||||
|
||||
[package.extras]
|
||||
asyncio = ["anyio (>=4.0,<5.0)"]
|
||||
http2 = ["h2 (>=3,<5)"]
|
||||
socks = ["socksio (==1.*)"]
|
||||
trio = ["trio (>=0.22.0,<0.23.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "httplib2"
|
||||
@@ -2569,21 +2572,22 @@ test = ["Cython (>=0.29.24,<0.30.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "httpx"
|
||||
version = "0.25.0"
|
||||
version = "0.25.2"
|
||||
description = "The next generation HTTP client."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "httpx-0.25.0-py3-none-any.whl", hash = "sha256:181ea7f8ba3a82578be86ef4171554dd45fec26a02556a744db029a0a27b7100"},
|
||||
{file = "httpx-0.25.0.tar.gz", hash = "sha256:47ecda285389cb32bb2691cc6e069e3ab0205956f681c5b2ad2325719751d875"},
|
||||
{file = "httpx-0.25.2-py3-none-any.whl", hash = "sha256:a05d3d052d9b2dfce0e3896636467f8a5342fb2b902c819428e1ac65413ca118"},
|
||||
{file = "httpx-0.25.2.tar.gz", hash = "sha256:8b8fcaa0c8ea7b05edd69a094e63a2094c4efcb48129fb757361bc423c0ad9e8"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anyio = "*"
|
||||
brotli = {version = "*", optional = true, markers = "platform_python_implementation == \"CPython\" and extra == \"brotli\""}
|
||||
brotlicffi = {version = "*", optional = true, markers = "platform_python_implementation != \"CPython\" and extra == \"brotli\""}
|
||||
certifi = "*"
|
||||
h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""}
|
||||
httpcore = ">=0.18.0,<0.19.0"
|
||||
httpcore = "==1.*"
|
||||
idna = "*"
|
||||
sniffio = "*"
|
||||
socksio = {version = "==1.*", optional = true, markers = "extra == \"socks\""}
|
||||
@@ -2809,6 +2813,17 @@ MarkupSafe = ">=2.0"
|
||||
[package.extras]
|
||||
i18n = ["Babel (>=2.7)"]
|
||||
|
||||
[[package]]
|
||||
name = "jmespath"
|
||||
version = "1.0.1"
|
||||
description = "JSON Matching Expressions"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "jmespath-1.0.1-py3-none-any.whl", hash = "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980"},
|
||||
{file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "joblib"
|
||||
version = "1.3.2"
|
||||
@@ -2986,22 +3001,23 @@ adal = ["adal (>=1.0.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "langchain"
|
||||
version = "0.0.336"
|
||||
version = "0.1.4"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain-0.0.336-py3-none-any.whl", hash = "sha256:cbc72c170c5eb67509bf44fb833412a3d4ccf4476136447abd4f10468ef7d4c4"},
|
||||
{file = "langchain-0.0.336.tar.gz", hash = "sha256:2cbb992b0a6975948d35616386d088c2920b66023cb94eb4f4b25e097fa1374d"},
|
||||
{file = "langchain-0.1.4-py3-none-any.whl", hash = "sha256:6befdd6221f5f326092e31a3c19efdc7ce3d7d1f2e2cab065141071451730ed7"},
|
||||
{file = "langchain-0.1.4.tar.gz", hash = "sha256:8767a9461e2b717ce9a35b1fa20659de89ea86ba9c2a4ff516e05d47ab2d195d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
aiohttp = ">=3.8.3,<4.0.0"
|
||||
anyio = "<4.0"
|
||||
async-timeout = {version = ">=4.0.0,<5.0.0", markers = "python_version < \"3.11\""}
|
||||
dataclasses-json = ">=0.5.7,<0.7"
|
||||
jsonpatch = ">=1.33,<2.0"
|
||||
langsmith = ">=0.0.63,<0.1.0"
|
||||
langchain-community = ">=0.0.14,<0.1"
|
||||
langchain-core = ">=0.1.16,<0.2"
|
||||
langsmith = ">=0.0.83,<0.1"
|
||||
numpy = ">=1,<2"
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
@@ -3010,20 +3026,119 @@ SQLAlchemy = ">=1.4,<3"
|
||||
tenacity = ">=8.1.0,<9.0.0"
|
||||
|
||||
[package.extras]
|
||||
all = ["O365 (>=2.0.26,<3.0.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "amadeus (>=8.1.0)", "arxiv (>=1.4,<2.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "awadb (>=0.3.9,<0.4.0)", "azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "beautifulsoup4 (>=4,<5)", "clarifai (>=9.1.0)", "clickhouse-connect (>=0.5.14,<0.6.0)", "cohere (>=4,<5)", "deeplake (>=3.8.3,<4.0.0)", "docarray[hnswlib] (>=0.32.0,<0.33.0)", "duckduckgo-search (>=3.8.3,<4.0.0)", "elasticsearch (>=8,<9)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "google-api-python-client (==2.70.0)", "google-auth (>=2.18.1,<3.0.0)", "google-search-results (>=2,<3)", "gptcache (>=0.1.7)", "html2text (>=2020.1.16,<2021.0.0)", "huggingface_hub (>=0,<1)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "lancedb (>=0.1,<0.2)", "langkit (>=0.0.6,<0.1.0)", "lark (>=1.1.5,<2.0.0)", "librosa (>=0.10.0.post2,<0.11.0)", "lxml (>=4.9.2,<5.0.0)", "manifest-ml (>=0.0.1,<0.0.2)", "marqo (>=1.2.4,<2.0.0)", "momento (>=1.13.0,<2.0.0)", "nebula3-python (>=3.4.0,<4.0.0)", "neo4j (>=5.8.1,<6.0.0)", "networkx (>=2.6.3,<4)", "nlpcloud (>=1,<2)", "nltk (>=3,<4)", "nomic (>=1.0.43,<2.0.0)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "opensearch-py (>=2.0.0,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pexpect (>=4.8.0,<5.0.0)", "pgvector (>=0.1.6,<0.2.0)", "pinecone-client (>=2,<3)", "pinecone-text (>=0.4.2,<0.5.0)", "psycopg2-binary (>=2.9.5,<3.0.0)", "pymongo (>=4.3.3,<5.0.0)", "pyowm (>=3.3.0,<4.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pytesseract (>=0.3.10,<0.4.0)", "python-arango (>=7.5.9,<8.0.0)", "pyvespa (>=0.33.0,<0.34.0)", "qdrant-client (>=1.3.1,<2.0.0)", "rdflib (>=6.3.2,<7.0.0)", "redis (>=4,<5)", "requests-toolbelt (>=1.0.0,<2.0.0)", "sentence-transformers (>=2,<3)", "singlestoredb (>=0.7.1,<0.8.0)", "tensorflow-text (>=2.11.0,<3.0.0)", "tigrisdb (>=1.0.0b6,<2.0.0)", "tiktoken (>=0.3.2,<0.6.0)", "torch (>=1,<3)", "transformers (>=4,<5)", "weaviate-client (>=3,<4)", "wikipedia (>=1,<2)", "wolframalpha (==5.0.0)"]
|
||||
azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"]
|
||||
azure = ["azure-ai-formrecognizer (>=3.2.1,<4.0.0)", "azure-ai-textanalytics (>=5.3.0,<6.0.0)", "azure-ai-vision (>=0.11.1b1,<0.12.0)", "azure-cognitiveservices-speech (>=1.28.0,<2.0.0)", "azure-core (>=1.26.4,<2.0.0)", "azure-cosmos (>=4.4.0b1,<5.0.0)", "azure-identity (>=1.12.0,<2.0.0)", "azure-search-documents (==11.4.0b8)", "openai (<2)"]
|
||||
clarifai = ["clarifai (>=9.1.0)"]
|
||||
cli = ["typer (>=0.9.0,<0.10.0)"]
|
||||
cohere = ["cohere (>=4,<5)"]
|
||||
docarray = ["docarray[hnswlib] (>=0.32.0,<0.33.0)"]
|
||||
embeddings = ["sentence-transformers (>=2,<3)"]
|
||||
extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "dashvector (>=1.0.1,<2.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.6.0,<0.7.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"]
|
||||
extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "couchbase (>=4.1.9,<5.0.0)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "langchain-openai (>=0.0.2,<0.1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)"]
|
||||
javascript = ["esprima (>=4.0.1,<5.0.0)"]
|
||||
llms = ["clarifai (>=9.1.0)", "cohere (>=4,<5)", "huggingface_hub (>=0,<1)", "manifest-ml (>=0.0.1,<0.0.2)", "nlpcloud (>=1,<2)", "openai (<2)", "openlm (>=0.0.5,<0.0.6)", "torch (>=1,<3)", "transformers (>=4,<5)"]
|
||||
openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"]
|
||||
qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"]
|
||||
text-helpers = ["chardet (>=5.1.0,<6.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "langchain-community"
|
||||
version = "0.0.16"
|
||||
description = "Community contributed LangChain integrations."
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain_community-0.0.16-py3-none-any.whl", hash = "sha256:0f1dfc1a6205ce8d39931d3515974a208a9f69c16157c649f83490a7cc830b73"},
|
||||
{file = "langchain_community-0.0.16.tar.gz", hash = "sha256:c06512a93013a06fba7679cd5a1254ff8b927cddd2d1fbe0cc444bf7bbdf0b8c"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
aiohttp = ">=3.8.3,<4.0.0"
|
||||
dataclasses-json = ">=0.5.7,<0.7"
|
||||
langchain-core = ">=0.1.16,<0.2"
|
||||
langsmith = ">=0.0.83,<0.1"
|
||||
numpy = ">=1,<2"
|
||||
PyYAML = ">=5.3"
|
||||
requests = ">=2,<3"
|
||||
SQLAlchemy = ">=1.4,<3"
|
||||
tenacity = ">=8.1.0,<9.0.0"
|
||||
|
||||
[package.extras]
|
||||
cli = ["typer (>=0.9.0,<0.10.0)"]
|
||||
extended-testing = ["aiosqlite (>=0.19.0,<0.20.0)", "aleph-alpha-client (>=2.15.0,<3.0.0)", "anthropic (>=0.3.11,<0.4.0)", "arxiv (>=1.4,<2.0)", "assemblyai (>=0.17.0,<0.18.0)", "atlassian-python-api (>=3.36.0,<4.0.0)", "azure-ai-documentintelligence (>=1.0.0b1,<2.0.0)", "beautifulsoup4 (>=4,<5)", "bibtexparser (>=1.4.0,<2.0.0)", "cassio (>=0.1.0,<0.2.0)", "chardet (>=5.1.0,<6.0.0)", "cohere (>=4,<5)", "dashvector (>=1.0.1,<2.0.0)", "databricks-vectorsearch (>=0.21,<0.22)", "datasets (>=2.15.0,<3.0.0)", "dgml-utils (>=0.3.0,<0.4.0)", "elasticsearch (>=8.12.0,<9.0.0)", "esprima (>=4.0.1,<5.0.0)", "faiss-cpu (>=1,<2)", "feedparser (>=6.0.10,<7.0.0)", "fireworks-ai (>=0.9.0,<0.10.0)", "geopandas (>=0.13.1,<0.14.0)", "gitpython (>=3.1.32,<4.0.0)", "google-cloud-documentai (>=2.20.1,<3.0.0)", "gql (>=3.4.1,<4.0.0)", "gradientai (>=1.4.0,<2.0.0)", "hdbcli (>=2.19.21,<3.0.0)", "hologres-vector (>=0.0.6,<0.0.7)", "html2text (>=2020.1.16,<2021.0.0)", "javelin-sdk (>=0.1.8,<0.2.0)", "jinja2 (>=3,<4)", "jq (>=1.4.1,<2.0.0)", "jsonschema (>1)", "lxml (>=4.9.2,<5.0.0)", "markdownify (>=0.11.6,<0.12.0)", "motor (>=3.3.1,<4.0.0)", "msal (>=1.25.0,<2.0.0)", "mwparserfromhell (>=0.6.4,<0.7.0)", "mwxml (>=0.3.3,<0.4.0)", "newspaper3k (>=0.2.8,<0.3.0)", "numexpr (>=2.8.6,<3.0.0)", "oci (>=2.119.1,<3.0.0)", "openai (<2)", "openapi-pydantic (>=0.3.2,<0.4.0)", "oracle-ads (>=2.9.1,<3.0.0)", "pandas (>=2.0.1,<3.0.0)", "pdfminer-six (>=20221105,<20221106)", "pgvector (>=0.1.6,<0.2.0)", "praw (>=7.7.1,<8.0.0)", "psychicapi (>=0.8.0,<0.9.0)", "py-trello (>=0.19.0,<0.20.0)", "pymupdf (>=1.22.3,<2.0.0)", "pypdf (>=3.4.0,<4.0.0)", "pypdfium2 (>=4.10.0,<5.0.0)", "pyspark (>=3.4.0,<4.0.0)", "rank-bm25 (>=0.2.2,<0.3.0)", "rapidfuzz (>=3.1.1,<4.0.0)", "rapidocr-onnxruntime (>=1.3.2,<2.0.0)", "requests-toolbelt (>=1.0.0,<2.0.0)", "rspace_client (>=2.5.0,<3.0.0)", "scikit-learn (>=1.2.2,<2.0.0)", "sqlite-vss (>=0.1.2,<0.2.0)", "streamlit (>=1.18.0,<2.0.0)", "sympy (>=1.12,<2.0)", "telethon (>=1.28.5,<2.0.0)", "timescale-vector (>=0.0.1,<0.0.2)", "tqdm (>=4.48.0)", "upstash-redis (>=0.15.0,<0.16.0)", "xata (>=1.0.0a7,<2.0.0)", "xmltodict (>=0.13.0,<0.14.0)", "zhipuai (>=1.0.7,<2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "langchain-core"
|
||||
version = "0.1.16"
|
||||
description = "Building applications with LLMs through composability"
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain_core-0.1.16-py3-none-any.whl", hash = "sha256:c1b2e7363771d64a72cb45032ed5a46facf67de005017fb5e74595cbf433f834"},
|
||||
{file = "langchain_core-0.1.16.tar.gz", hash = "sha256:8cb546eed318009ee1a8a381d108074eddf0395ae61eb243db00d76e1e265e89"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anyio = ">=3,<5"
|
||||
jsonpatch = ">=1.33,<2.0"
|
||||
langsmith = ">=0.0.83,<0.1"
|
||||
packaging = ">=23.2,<24.0"
|
||||
pydantic = ">=1,<3"
|
||||
PyYAML = ">=5.3"
|
||||
requests = ">=2,<3"
|
||||
tenacity = ">=8.1.0,<9.0.0"
|
||||
|
||||
[package.extras]
|
||||
extended-testing = ["jinja2 (>=3,<4)"]
|
||||
|
||||
[[package]]
|
||||
name = "langchain-google-vertexai"
|
||||
version = "0.0.5"
|
||||
description = "An integration package connecting GoogleVertexAI and LangChain"
|
||||
optional = true
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain_google_vertexai-0.0.5-py3-none-any.whl", hash = "sha256:7d20250a19262d8e7fc21ad63d891dde0b7b6362a117f182df428552289626fc"},
|
||||
{file = "langchain_google_vertexai-0.0.5.tar.gz", hash = "sha256:40cd9d5238722af2ba3c072b489d2dc95b8d4a03267bd64a8edff49c2d2f82c2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
google-cloud-aiplatform = ">=1.39.0,<2.0.0"
|
||||
google-cloud-storage = ">=2.14.0,<3.0.0"
|
||||
langchain-core = ">=0.1.7,<0.2"
|
||||
types-protobuf = ">=4.24.0.4,<5.0.0.0"
|
||||
types-requests = ">=2.31.0,<3.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "langchain-mistralai"
|
||||
version = "0.0.3"
|
||||
description = "An integration package connecting Mistral and LangChain"
|
||||
optional = true
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain_mistralai-0.0.3-py3-none-any.whl", hash = "sha256:ebb8ba3d7978b5ee16f7e09512ffa434e00bc9863f1537f1a5f5203882d99619"},
|
||||
{file = "langchain_mistralai-0.0.3.tar.gz", hash = "sha256:2e45ee0118df8e4b5577ce8c4f89743059801e473f40a8b7c89cb99dd715f423"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
langchain-core = ">=0.1,<0.2"
|
||||
mistralai = ">=0.0.11,<0.0.12"
|
||||
|
||||
[[package]]
|
||||
name = "langchain-openai"
|
||||
version = "0.0.5"
|
||||
description = "An integration package connecting OpenAI and LangChain"
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langchain_openai-0.0.5-py3-none-any.whl", hash = "sha256:93b37dfac274adad65e46d5d6e71411e00c6984bcc5e10f1d6bb58e7944dc01b"},
|
||||
{file = "langchain_openai-0.0.5.tar.gz", hash = "sha256:f317fee5b652949ad96ad7edf8ef7a044a6a3f0cc71d1e12f9d5261789fd68c4"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
langchain-core = ">=0.1.16,<0.2"
|
||||
numpy = ">=1,<2"
|
||||
openai = ">=1.10.0,<2.0.0"
|
||||
tiktoken = ">=0.5.2,<0.6.0"
|
||||
|
||||
[[package]]
|
||||
name = "langdetect"
|
||||
version = "1.0.9"
|
||||
@@ -3040,13 +3155,13 @@ six = "*"
|
||||
|
||||
[[package]]
|
||||
name = "langsmith"
|
||||
version = "0.0.65"
|
||||
version = "0.0.83"
|
||||
description = "Client library to connect to the LangSmith LLM Tracing and Evaluation Platform."
|
||||
optional = false
|
||||
python-versions = ">=3.8.1,<4.0"
|
||||
files = [
|
||||
{file = "langsmith-0.0.65-py3-none-any.whl", hash = "sha256:92450957d1c6b6be814f9b726f3bc751deca684535fb404508ccad7aec1bb049"},
|
||||
{file = "langsmith-0.0.65.tar.gz", hash = "sha256:ef20e2e32392fb1a0fc5d171e8de595d868b4153a10cc119d7bf8418192c06b6"},
|
||||
{file = "langsmith-0.0.83-py3-none-any.whl", hash = "sha256:a5bb7ac58c19a415a9d5f51db56dd32ee2cd7343a00825bbc2018312eb3d122a"},
|
||||
{file = "langsmith-0.0.83.tar.gz", hash = "sha256:94427846b334ad9bdbec3266fee12903fe9f5448f628667689d0412012aaf392"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -3112,24 +3227,6 @@ files = [
|
||||
{file = "lit-17.0.2.tar.gz", hash = "sha256:d6a551eab550f81023c82a260cd484d63970d2be9fd7588111208e7d2ff62212"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "loguru"
|
||||
version = "0.7.2"
|
||||
description = "Python logging made (stupidly) simple"
|
||||
optional = true
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "loguru-0.7.2-py3-none-any.whl", hash = "sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb"},
|
||||
{file = "loguru-0.7.2.tar.gz", hash = "sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""}
|
||||
win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""}
|
||||
|
||||
[package.extras]
|
||||
dev = ["Sphinx (==7.2.5)", "colorama (==0.4.5)", "colorama (==0.4.6)", "exceptiongroup (==1.1.3)", "freezegun (==1.1.0)", "freezegun (==1.2.2)", "mypy (==v0.910)", "mypy (==v0.971)", "mypy (==v1.4.1)", "mypy (==v1.5.1)", "pre-commit (==3.4.0)", "pytest (==6.1.2)", "pytest (==7.4.0)", "pytest-cov (==2.12.1)", "pytest-cov (==4.1.0)", "pytest-mypy-plugins (==1.9.3)", "pytest-mypy-plugins (==3.0.0)", "sphinx-autobuild (==2021.3.14)", "sphinx-rtd-theme (==1.3.0)", "tox (==3.27.1)", "tox (==4.11.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "lxml"
|
||||
version = "4.9.3"
|
||||
@@ -3306,16 +3403,6 @@ files = [
|
||||
{file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"},
|
||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
|
||||
{file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"},
|
||||
{file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"},
|
||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"},
|
||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"},
|
||||
{file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"},
|
||||
@@ -3458,6 +3545,22 @@ files = [
|
||||
certifi = "*"
|
||||
urllib3 = "*"
|
||||
|
||||
[[package]]
|
||||
name = "mistralai"
|
||||
version = "0.0.11"
|
||||
description = ""
|
||||
optional = true
|
||||
python-versions = ">=3.8,<4.0"
|
||||
files = [
|
||||
{file = "mistralai-0.0.11-py3-none-any.whl", hash = "sha256:fb2a240a3985420c4e7db48eb5077d6d6dbc5e83cac0dd948c20342fb48087ee"},
|
||||
{file = "mistralai-0.0.11.tar.gz", hash = "sha256:383072715531198305dab829ab3749b64933bbc2549354f3c9ebc43c17b912cf"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
httpx = ">=0.25.2,<0.26.0"
|
||||
orjson = ">=3.9.10,<4.0.0"
|
||||
pydantic = ">=2.5.2,<3.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "mock"
|
||||
version = "5.1.0"
|
||||
@@ -4116,22 +4219,23 @@ sympy = "*"
|
||||
|
||||
[[package]]
|
||||
name = "openai"
|
||||
version = "1.1.2"
|
||||
description = "Client library for the openai API"
|
||||
version = "1.10.0"
|
||||
description = "The official Python library for the openai API"
|
||||
optional = false
|
||||
python-versions = ">=3.7.1"
|
||||
files = [
|
||||
{file = "openai-1.1.2-py3-none-any.whl", hash = "sha256:72fa414378913ca74432ac618ca6cdfd78a502fcfad1e06cc499b9dba8ff2c8e"},
|
||||
{file = "openai-1.1.2.tar.gz", hash = "sha256:bcb4d1fd471cf616031053636841acdc820cd42cbc6cd3e4036c85f682752656"},
|
||||
{file = "openai-1.10.0-py3-none-any.whl", hash = "sha256:aa69e97d0223ace9835fbf9c997abe9ee95318f684fd2de6d02c870700c71ebc"},
|
||||
{file = "openai-1.10.0.tar.gz", hash = "sha256:208886cb501b930dc63f48d51db9c15e5380380f80516d07332adad67c9f1053"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
anyio = ">=3.5.0,<4"
|
||||
anyio = ">=3.5.0,<5"
|
||||
distro = ">=1.7.0,<2"
|
||||
httpx = ">=0.23.0,<1"
|
||||
pydantic = ">=1.9.0,<3"
|
||||
sniffio = "*"
|
||||
tqdm = ">4"
|
||||
typing-extensions = ">=4.5,<5"
|
||||
typing-extensions = ">=4.7,<5"
|
||||
|
||||
[package.extras]
|
||||
datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"]
|
||||
@@ -4154,10 +4258,12 @@ files = [
|
||||
|
||||
[package.dependencies]
|
||||
numpy = [
|
||||
{version = ">=1.21.0", markers = "python_version == \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""},
|
||||
{version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""},
|
||||
{version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""},
|
||||
{version = ">=1.19.3", markers = "platform_system == \"Linux\" and platform_machine == \"aarch64\" and python_version >= \"3.8\" and python_version < \"3.10\" or python_version > \"3.9\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_system != \"Darwin\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_machine != \"arm64\" and python_version < \"3.10\""},
|
||||
{version = ">=1.21.0", markers = "python_version <= \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""},
|
||||
{version = ">=1.19.3", markers = "python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\" or python_version >= \"3.9\""},
|
||||
{version = ">=1.17.0", markers = "python_version >= \"3.7\""},
|
||||
{version = ">=1.17.3", markers = "python_version >= \"3.8\""},
|
||||
{version = ">=1.21.2", markers = "python_version >= \"3.10\""},
|
||||
{version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\""},
|
||||
{version = ">=1.23.5", markers = "python_version >= \"3.11\""},
|
||||
]
|
||||
|
||||
@@ -4294,6 +4400,65 @@ files = [
|
||||
{file = "opentelemetry_semantic_conventions-0.42b0.tar.gz", hash = "sha256:44ae67a0a3252a05072877857e5cc1242c98d4cf12870159f1a94bec800d38ec"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "orjson"
|
||||
version = "3.9.12"
|
||||
description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "orjson-3.9.12-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:6b4e2bed7d00753c438e83b613923afdd067564ff7ed696bfe3a7b073a236e07"},
|
||||
{file = "orjson-3.9.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd1b8ec63f0bf54a50b498eedeccdca23bd7b658f81c524d18e410c203189365"},
|
||||
{file = "orjson-3.9.12-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab8add018a53665042a5ae68200f1ad14c7953fa12110d12d41166f111724656"},
|
||||
{file = "orjson-3.9.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:12756a108875526b76e505afe6d6ba34960ac6b8c5ec2f35faf73ef161e97e07"},
|
||||
{file = "orjson-3.9.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:890e7519c0c70296253660455f77e3a194554a3c45e42aa193cdebc76a02d82b"},
|
||||
{file = "orjson-3.9.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d664880d7f016efbae97c725b243b33c2cbb4851ddc77f683fd1eec4a7894146"},
|
||||
{file = "orjson-3.9.12-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cfdaede0fa5b500314ec7b1249c7e30e871504a57004acd116be6acdda3b8ab3"},
|
||||
{file = "orjson-3.9.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6492ff5953011e1ba9ed1bf086835fd574bd0a3cbe252db8e15ed72a30479081"},
|
||||
{file = "orjson-3.9.12-cp310-none-win32.whl", hash = "sha256:29bf08e2eadb2c480fdc2e2daae58f2f013dff5d3b506edd1e02963b9ce9f8a9"},
|
||||
{file = "orjson-3.9.12-cp310-none-win_amd64.whl", hash = "sha256:0fc156fba60d6b50743337ba09f052d8afc8b64595112996d22f5fce01ab57da"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:2849f88a0a12b8d94579b67486cbd8f3a49e36a4cb3d3f0ab352c596078c730c"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3186b18754befa660b31c649a108a915493ea69b4fc33f624ed854ad3563ac65"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cbbf313c9fb9d4f6cf9c22ced4b6682230457741daeb3d7060c5d06c2e73884a"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99e8cd005b3926c3db9b63d264bd05e1bf4451787cc79a048f27f5190a9a0311"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59feb148392d9155f3bfed0a2a3209268e000c2c3c834fb8fe1a6af9392efcbf"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a4ae815a172a1f073b05b9e04273e3b23e608a0858c4e76f606d2d75fcabde0c"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ed398f9a9d5a1bf55b6e362ffc80ac846af2122d14a8243a1e6510a4eabcb71e"},
|
||||
{file = "orjson-3.9.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d3cfb76600c5a1e6be91326b8f3b83035a370e727854a96d801c1ea08b708073"},
|
||||
{file = "orjson-3.9.12-cp311-none-win32.whl", hash = "sha256:a2b6f5252c92bcab3b742ddb3ac195c0fa74bed4319acd74f5d54d79ef4715dc"},
|
||||
{file = "orjson-3.9.12-cp311-none-win_amd64.whl", hash = "sha256:c95488e4aa1d078ff5776b58f66bd29d628fa59adcb2047f4efd3ecb2bd41a71"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:d6ce2062c4af43b92b0221ed4f445632c6bf4213f8a7da5396a122931377acd9"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:950951799967558c214cd6cceb7ceceed6f81d2c3c4135ee4a2c9c69f58aa225"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2dfaf71499d6fd4153f5c86eebb68e3ec1bf95851b030a4b55c7637a37bbdee4"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:659a8d7279e46c97661839035a1a218b61957316bf0202674e944ac5cfe7ed83"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af17fa87bccad0b7f6fd8ac8f9cbc9ee656b4552783b10b97a071337616db3e4"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd52dec9eddf4c8c74392f3fd52fa137b5f2e2bed1d9ae958d879de5f7d7cded"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:640e2b5d8e36b970202cfd0799d11a9a4ab46cf9212332cd642101ec952df7c8"},
|
||||
{file = "orjson-3.9.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:daa438bd8024e03bcea2c5a92cd719a663a58e223fba967296b6ab9992259dbf"},
|
||||
{file = "orjson-3.9.12-cp312-none-win_amd64.whl", hash = "sha256:1bb8f657c39ecdb924d02e809f992c9aafeb1ad70127d53fb573a6a6ab59d549"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:f4098c7674901402c86ba6045a551a2ee345f9f7ed54eeffc7d86d155c8427e5"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5586a533998267458fad3a457d6f3cdbddbcce696c916599fa8e2a10a89b24d3"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:54071b7398cd3f90e4bb61df46705ee96cb5e33e53fc0b2f47dbd9b000e238e1"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:67426651faa671b40443ea6f03065f9c8e22272b62fa23238b3efdacd301df31"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4a0cd56e8ee56b203abae7d482ac0d233dbfb436bb2e2d5cbcb539fe1200a312"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a84a0c3d4841a42e2571b1c1ead20a83e2792644c5827a606c50fc8af7ca4bee"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:09d60450cda3fa6c8ed17770c3a88473a16460cd0ff2ba74ef0df663b6fd3bb8"},
|
||||
{file = "orjson-3.9.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bc82a4db9934a78ade211cf2e07161e4f068a461c1796465d10069cb50b32a80"},
|
||||
{file = "orjson-3.9.12-cp38-none-win32.whl", hash = "sha256:61563d5d3b0019804d782137a4f32c72dc44c84e7d078b89d2d2a1adbaa47b52"},
|
||||
{file = "orjson-3.9.12-cp38-none-win_amd64.whl", hash = "sha256:410f24309fbbaa2fab776e3212a81b96a1ec6037259359a32ea79fbccfcf76aa"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:e773f251258dd82795fd5daeac081d00b97bacf1548e44e71245543374874bcf"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b159baecfda51c840a619948c25817d37733a4d9877fea96590ef8606468b362"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:975e72e81a249174840d5a8df977d067b0183ef1560a32998be340f7e195c730"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:06e42e899dde61eb1851a9fad7f1a21b8e4be063438399b63c07839b57668f6c"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c157e999e5694475a5515942aebeed6e43f7a1ed52267c1c93dcfde7d78d421"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dde1bc7c035f2d03aa49dc8642d9c6c9b1a81f2470e02055e76ed8853cfae0c3"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b0e9d73cdbdad76a53a48f563447e0e1ce34bcecef4614eb4b146383e6e7d8c9"},
|
||||
{file = "orjson-3.9.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:96e44b21fe407b8ed48afbb3721f3c8c8ce17e345fbe232bd4651ace7317782d"},
|
||||
{file = "orjson-3.9.12-cp39-none-win32.whl", hash = "sha256:cbd0f3555205bf2a60f8812133f2452d498dbefa14423ba90fe89f32276f7abf"},
|
||||
{file = "orjson-3.9.12-cp39-none-win_amd64.whl", hash = "sha256:03ea7ee7e992532c2f4a06edd7ee1553f0644790553a118e003e3c405add41fa"},
|
||||
{file = "orjson-3.9.12.tar.gz", hash = "sha256:da908d23a3b3243632b523344403b128722a5f45e278a8343c2bb67538dff0e4"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "overrides"
|
||||
version = "7.4.0"
|
||||
@@ -4513,25 +4678,20 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
|
||||
|
||||
[[package]]
|
||||
name = "pinecone-client"
|
||||
version = "2.2.4"
|
||||
version = "3.0.1"
|
||||
description = "Pinecone client and SDK"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
python-versions = ">=3.8,<3.13"
|
||||
files = [
|
||||
{file = "pinecone-client-2.2.4.tar.gz", hash = "sha256:2c1cc1d6648b2be66e944db2ffa59166a37b9164d1135ad525d9cd8b1e298168"},
|
||||
{file = "pinecone_client-2.2.4-py3-none-any.whl", hash = "sha256:5bf496c01c2f82f4e5c2dc977cc5062ecd7168b8ed90743b09afcc8c7eb242ec"},
|
||||
{file = "pinecone_client-3.0.1-py3-none-any.whl", hash = "sha256:c9bb21c23a9088c6198c839be5538ed3f733d152d5fbeaafcc020c1b70b62c2d"},
|
||||
{file = "pinecone_client-3.0.1.tar.gz", hash = "sha256:626a0055852c88f1462fc2e132f21d2b078f9a0a74c70b17fe07df3081c6615f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
dnspython = ">=2.0.0"
|
||||
loguru = ">=0.5.0"
|
||||
numpy = ">=1.22.0"
|
||||
python-dateutil = ">=2.5.3"
|
||||
pyyaml = ">=5.4"
|
||||
requests = ">=2.19.0"
|
||||
certifi = ">=2019.11.17"
|
||||
tqdm = ">=4.64.1"
|
||||
typing-extensions = ">=3.7.4"
|
||||
urllib3 = ">=1.21.1"
|
||||
urllib3 = ">=1.26.0"
|
||||
|
||||
[package.extras]
|
||||
grpc = ["googleapis-common-protos (>=1.53.0)", "grpc-gateway-protoc-gen-openapiv2 (==0.1.0)", "grpcio (>=1.44.0)", "lz4 (>=3.1.3)", "protobuf (>=3.20.0,<3.21.0)"]
|
||||
@@ -5538,7 +5698,6 @@ files = [
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
@@ -5546,15 +5705,8 @@ files = [
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
|
||||
{file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
||||
@@ -5571,7 +5723,6 @@ files = [
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||
@@ -5579,7 +5730,6 @@ files = [
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
@@ -5732,7 +5882,7 @@ full = ["numpy"]
|
||||
name = "regex"
|
||||
version = "2023.8.8"
|
||||
description = "Alternative regular expression module, to replace re."
|
||||
optional = true
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "regex-2023.8.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:88900f521c645f784260a8d346e12a1590f79e96403971241e64c3a265c8ecdb"},
|
||||
@@ -5976,6 +6126,23 @@ files = [
|
||||
{file = "ruff-0.1.11.tar.gz", hash = "sha256:f9d4d88cb6eeb4dfe20f9f0519bd2eaba8119bde87c3d5065c541dbae2b5a2cb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "s3transfer"
|
||||
version = "0.10.0"
|
||||
description = "An Amazon S3 Transfer Manager"
|
||||
optional = true
|
||||
python-versions = ">= 3.8"
|
||||
files = [
|
||||
{file = "s3transfer-0.10.0-py3-none-any.whl", hash = "sha256:3cdb40f5cfa6966e812209d0994f2a4709b561c88e90cf00c2696d2df4e56b2e"},
|
||||
{file = "s3transfer-0.10.0.tar.gz", hash = "sha256:d0c8bbf672d5eebbe4e57945e23b972d963f07d82f661cabf678a5c88831595b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
botocore = ">=1.33.2,<2.0a.0"
|
||||
|
||||
[package.extras]
|
||||
crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "safetensors"
|
||||
version = "0.4.0"
|
||||
@@ -6127,11 +6294,6 @@ files = [
|
||||
{file = "scikit_learn-1.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f66eddfda9d45dd6cadcd706b65669ce1df84b8549875691b1f403730bdef217"},
|
||||
{file = "scikit_learn-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6448c37741145b241eeac617028ba6ec2119e1339b1385c9720dae31367f2be"},
|
||||
{file = "scikit_learn-1.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:c413c2c850241998168bbb3bd1bb59ff03b1195a53864f0b80ab092071af6028"},
|
||||
{file = "scikit_learn-1.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ef540e09873e31569bc8b02c8a9f745ee04d8e1263255a15c9969f6f5caa627f"},
|
||||
{file = "scikit_learn-1.3.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:9147a3a4df4d401e618713880be023e36109c85d8569b3bf5377e6cd3fecdeac"},
|
||||
{file = "scikit_learn-1.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2cd3634695ad192bf71645702b3df498bd1e246fc2d529effdb45a06ab028b4"},
|
||||
{file = "scikit_learn-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c275a06c5190c5ce00af0acbb61c06374087949f643ef32d355ece12c4db043"},
|
||||
{file = "scikit_learn-1.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:0e1aa8f206d0de814b81b41d60c1ce31f7f2c7354597af38fae46d9c47c45122"},
|
||||
{file = "scikit_learn-1.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:52b77cc08bd555969ec5150788ed50276f5ef83abb72e6f469c5b91a0009bbca"},
|
||||
{file = "scikit_learn-1.3.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a683394bc3f80b7c312c27f9b14ebea7766b1f0a34faf1a2e9158d80e860ec26"},
|
||||
{file = "scikit_learn-1.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15d964d9eb181c79c190d3dbc2fff7338786bf017e9039571418a1d53dab236"},
|
||||
@@ -6474,59 +6636,18 @@ description = "Database Abstraction Library"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f146c61ae128ab43ea3a0955de1af7e1633942c2b2b4985ac51cc292daf33222"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:875de9414393e778b655a3d97d60465eb3fae7c919e88b70cc10b40b9f56042d"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13790cb42f917c45c9c850b39b9941539ca8ee7917dacf099cc0b569f3d40da7"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04ab55cf49daf1aeb8c622c54d23fa4bec91cb051a43cc24351ba97e1dd09f5"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a42c9fa3abcda0dcfad053e49c4f752eef71ecd8c155221e18b99d4224621176"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:14cd3bcbb853379fef2cd01e7c64a5d6f1d005406d877ed9509afb7a05ff40a5"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-win32.whl", hash = "sha256:d143c5a9dada696bcfdb96ba2de4a47d5a89168e71d05a076e88a01386872f97"},
|
||||
{file = "SQLAlchemy-2.0.22-cp310-cp310-win_amd64.whl", hash = "sha256:ccd87c25e4c8559e1b918d46b4fa90b37f459c9b4566f1dfbce0eb8122571547"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f6ff392b27a743c1ad346d215655503cec64405d3b694228b3454878bf21590"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f776c2c30f0e5f4db45c3ee11a5f2a8d9de68e81eb73ec4237de1e32e04ae81c"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8f1792d20d2f4e875ce7a113f43c3561ad12b34ff796b84002a256f37ce9437"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80eeb5189d7d4b1af519fc3f148fe7521b9dfce8f4d6a0820e8f5769b005051"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:69fd9e41cf9368afa034e1c81f3570afb96f30fcd2eb1ef29cb4d9371c6eece2"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54bcceaf4eebef07dadfde424f5c26b491e4a64e61761dea9459103ecd6ccc95"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-win32.whl", hash = "sha256:7ee7ccf47aa503033b6afd57efbac6b9e05180f492aeed9fcf70752556f95624"},
|
||||
{file = "SQLAlchemy-2.0.22-cp311-cp311-win_amd64.whl", hash = "sha256:b560f075c151900587ade06706b0c51d04b3277c111151997ea0813455378ae0"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2c9bac865ee06d27a1533471405ad240a6f5d83195eca481f9fc4a71d8b87df8"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:625b72d77ac8ac23da3b1622e2da88c4aedaee14df47c8432bf8f6495e655de2"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b39a6e21110204a8c08d40ff56a73ba542ec60bab701c36ce721e7990df49fb9"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a766cb0b468223cafdf63e2d37f14a4757476157927b09300c8c5832d88560"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0e1ce8ebd2e040357dde01a3fb7d30d9b5736b3e54a94002641dfd0aa12ae6ce"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:505f503763a767556fa4deae5194b2be056b64ecca72ac65224381a0acab7ebe"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-win32.whl", hash = "sha256:154a32f3c7b00de3d090bc60ec8006a78149e221f1182e3edcf0376016be9396"},
|
||||
{file = "SQLAlchemy-2.0.22-cp312-cp312-win_amd64.whl", hash = "sha256:129415f89744b05741c6f0b04a84525f37fbabe5dc3774f7edf100e7458c48cd"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3940677d341f2b685a999bffe7078697b5848a40b5f6952794ffcf3af150c301"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55914d45a631b81a8a2cb1a54f03eea265cf1783241ac55396ec6d735be14883"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2096d6b018d242a2bcc9e451618166f860bb0304f590d205173d317b69986c95"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:19c6986cf2fb4bc8e0e846f97f4135a8e753b57d2aaaa87c50f9acbe606bd1db"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ac28bd6888fe3c81fbe97584eb0b96804bd7032d6100b9701255d9441373ec1"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-win32.whl", hash = "sha256:cb9a758ad973e795267da334a92dd82bb7555cb36a0960dcabcf724d26299db8"},
|
||||
{file = "SQLAlchemy-2.0.22-cp37-cp37m-win_amd64.whl", hash = "sha256:40b1206a0d923e73aa54f0a6bd61419a96b914f1cd19900b6c8226899d9742ad"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3aa1472bf44f61dd27987cd051f1c893b7d3b17238bff8c23fceaef4f1133868"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:56a7e2bb639df9263bf6418231bc2a92a773f57886d371ddb7a869a24919face"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccca778c0737a773a1ad86b68bda52a71ad5950b25e120b6eb1330f0df54c3d0"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6c3e9350f9fb16de5b5e5fbf17b578811a52d71bb784cc5ff71acb7de2a7f9"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:564e9f9e4e6466273dbfab0e0a2e5fe819eec480c57b53a2cdee8e4fdae3ad5f"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:af66001d7b76a3fab0d5e4c1ec9339ac45748bc4a399cbc2baa48c1980d3c1f4"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-win32.whl", hash = "sha256:9e55dff5ec115316dd7a083cdc1a52de63693695aecf72bc53a8e1468ce429e5"},
|
||||
{file = "SQLAlchemy-2.0.22-cp38-cp38-win_amd64.whl", hash = "sha256:4e869a8ff7ee7a833b74868a0887e8462445ec462432d8cbeff5e85f475186da"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9886a72c8e6371280cb247c5d32c9c8fa141dc560124348762db8a8b236f8692"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a571bc8ac092a3175a1d994794a8e7a1f2f651e7c744de24a19b4f740fe95034"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8db5ba8b7da759b727faebc4289a9e6a51edadc7fc32207a30f7c6203a181592"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0b3f2686c3f162123adba3cb8b626ed7e9b8433ab528e36ed270b4f70d1cdb"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c1fea8c0abcb070ffe15311853abfda4e55bf7dc1d4889497b3403629f3bf00"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4bb062784f37b2d75fd9b074c8ec360ad5df71f933f927e9e95c50eb8e05323c"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-win32.whl", hash = "sha256:58a3aba1bfb32ae7af68da3f277ed91d9f57620cf7ce651db96636790a78b736"},
|
||||
{file = "SQLAlchemy-2.0.22-cp39-cp39-win_amd64.whl", hash = "sha256:92e512a6af769e4725fa5b25981ba790335d42c5977e94ded07db7d641490a85"},
|
||||
{file = "SQLAlchemy-2.0.22-py3-none-any.whl", hash = "sha256:3076740335e4aaadd7deb3fe6dcb96b3015f1613bd190a4e1634e1b99b02ec86"},
|
||||
{file = "SQLAlchemy-2.0.22.tar.gz", hash = "sha256:5434cc601aa17570d79e5377f5fd45ff92f9379e2abed0be5e8c2fba8d353d2b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""}
|
||||
greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""}
|
||||
typing-extensions = ">=4.2.0"
|
||||
|
||||
[package.extras]
|
||||
@@ -6691,40 +6812,47 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "tiktoken"
|
||||
version = "0.4.0"
|
||||
version = "0.5.2"
|
||||
description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models"
|
||||
optional = true
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "tiktoken-0.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:176cad7f053d2cc82ce7e2a7c883ccc6971840a4b5276740d0b732a2b2011f8a"},
|
||||
{file = "tiktoken-0.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:450d504892b3ac80207700266ee87c932df8efea54e05cefe8613edc963c1285"},
|
||||
{file = "tiktoken-0.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d662de1e7986d129139faf15e6a6ee7665ee103440769b8dedf3e7ba6ac37f"},
|
||||
{file = "tiktoken-0.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5727d852ead18b7927b8adf558a6f913a15c7766725b23dbe21d22e243041b28"},
|
||||
{file = "tiktoken-0.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c06cd92b09eb0404cedce3702fa866bf0d00e399439dad3f10288ddc31045422"},
|
||||
{file = "tiktoken-0.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9ec161e40ed44e4210d3b31e2ff426b4a55e8254f1023e5d2595cb60044f8ea6"},
|
||||
{file = "tiktoken-0.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:1e8fa13cf9889d2c928b9e258e9dbbbf88ab02016e4236aae76e3b4f82dd8288"},
|
||||
{file = "tiktoken-0.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bb2341836b725c60d0ab3c84970b9b5f68d4b733a7bcb80fb25967e5addb9920"},
|
||||
{file = "tiktoken-0.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2ca30367ad750ee7d42fe80079d3092bd35bb266be7882b79c3bd159b39a17b0"},
|
||||
{file = "tiktoken-0.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3dc3df19ddec79435bb2a94ee46f4b9560d0299c23520803d851008445671197"},
|
||||
{file = "tiktoken-0.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d980fa066e962ef0f4dad0222e63a484c0c993c7a47c7dafda844ca5aded1f3"},
|
||||
{file = "tiktoken-0.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:329f548a821a2f339adc9fbcfd9fc12602e4b3f8598df5593cfc09839e9ae5e4"},
|
||||
{file = "tiktoken-0.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b1a038cee487931a5caaef0a2e8520e645508cde21717eacc9af3fbda097d8bb"},
|
||||
{file = "tiktoken-0.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:08efa59468dbe23ed038c28893e2a7158d8c211c3dd07f2bbc9a30e012512f1d"},
|
||||
{file = "tiktoken-0.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f3020350685e009053829c1168703c346fb32c70c57d828ca3742558e94827a9"},
|
||||
{file = "tiktoken-0.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba16698c42aad8190e746cd82f6a06769ac7edd415d62ba027ea1d99d958ed93"},
|
||||
{file = "tiktoken-0.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c15d9955cc18d0d7ffcc9c03dc51167aedae98542238b54a2e659bd25fe77ed"},
|
||||
{file = "tiktoken-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64e1091c7103100d5e2c6ea706f0ec9cd6dc313e6fe7775ef777f40d8c20811e"},
|
||||
{file = "tiktoken-0.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e87751b54eb7bca580126353a9cf17a8a8eaadd44edaac0e01123e1513a33281"},
|
||||
{file = "tiktoken-0.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e063b988b8ba8b66d6cc2026d937557437e79258095f52eaecfafb18a0a10c03"},
|
||||
{file = "tiktoken-0.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9c6dd439e878172dc163fced3bc7b19b9ab549c271b257599f55afc3a6a5edef"},
|
||||
{file = "tiktoken-0.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8d1d97f83697ff44466c6bef5d35b6bcdb51e0125829a9c0ed1e6e39fb9a08fb"},
|
||||
{file = "tiktoken-0.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b6bce7c68aa765f666474c7c11a7aebda3816b58ecafb209afa59c799b0dd2d"},
|
||||
{file = "tiktoken-0.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5a73286c35899ca51d8d764bc0b4d60838627ce193acb60cc88aea60bddec4fd"},
|
||||
{file = "tiktoken-0.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0394967d2236a60fd0aacef26646b53636423cc9c70c32f7c5124ebe86f3093"},
|
||||
{file = "tiktoken-0.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:dae2af6f03ecba5f679449fa66ed96585b2fa6accb7fd57d9649e9e398a94f44"},
|
||||
{file = "tiktoken-0.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55e251b1da3c293432179cf7c452cfa35562da286786be5a8b1ee3405c2b0dd2"},
|
||||
{file = "tiktoken-0.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:c835d0ee1f84a5aa04921717754eadbc0f0a56cf613f78dfc1cf9ad35f6c3fea"},
|
||||
{file = "tiktoken-0.4.0.tar.gz", hash = "sha256:59b20a819969735b48161ced9b92f05dc4519c17be4015cfb73b65270a243620"},
|
||||
{file = "tiktoken-0.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c4e654282ef05ec1bd06ead22141a9a1687991cef2c6a81bdd1284301abc71d"},
|
||||
{file = "tiktoken-0.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7b3134aa24319f42c27718c6967f3c1916a38a715a0fa73d33717ba121231307"},
|
||||
{file = "tiktoken-0.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6092e6e77730929c8c6a51bb0d7cfdf1b72b63c4d033d6258d1f2ee81052e9e5"},
|
||||
{file = "tiktoken-0.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ad8ae2a747622efae75837abba59be6c15a8f31b4ac3c6156bc56ec7a8e631"},
|
||||
{file = "tiktoken-0.5.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:51cba7c8711afa0b885445f0637f0fcc366740798c40b981f08c5f984e02c9d1"},
|
||||
{file = "tiktoken-0.5.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:3d8c7d2c9313f8e92e987d585ee2ba0f7c40a0de84f4805b093b634f792124f5"},
|
||||
{file = "tiktoken-0.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:692eca18c5fd8d1e0dde767f895c17686faaa102f37640e884eecb6854e7cca7"},
|
||||
{file = "tiktoken-0.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:138d173abbf1ec75863ad68ca289d4da30caa3245f3c8d4bfb274c4d629a2f77"},
|
||||
{file = "tiktoken-0.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7388fdd684690973fdc450b47dfd24d7f0cbe658f58a576169baef5ae4658607"},
|
||||
{file = "tiktoken-0.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a114391790113bcff670c70c24e166a841f7ea8f47ee2fe0e71e08b49d0bf2d4"},
|
||||
{file = "tiktoken-0.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca96f001e69f6859dd52926d950cfcc610480e920e576183497ab954e645e6ac"},
|
||||
{file = "tiktoken-0.5.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:15fed1dd88e30dfadcdd8e53a8927f04e1f6f81ad08a5ca824858a593ab476c7"},
|
||||
{file = "tiktoken-0.5.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:93f8e692db5756f7ea8cb0cfca34638316dcf0841fb8469de8ed7f6a015ba0b0"},
|
||||
{file = "tiktoken-0.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:bcae1c4c92df2ffc4fe9f475bf8148dbb0ee2404743168bbeb9dcc4b79dc1fdd"},
|
||||
{file = "tiktoken-0.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b76a1e17d4eb4357d00f0622d9a48ffbb23401dcf36f9716d9bd9c8e79d421aa"},
|
||||
{file = "tiktoken-0.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:01d8b171bb5df4035580bc26d4f5339a6fd58d06f069091899d4a798ea279d3e"},
|
||||
{file = "tiktoken-0.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42adf7d4fb1ed8de6e0ff2e794a6a15005f056a0d83d22d1d6755a39bffd9e7f"},
|
||||
{file = "tiktoken-0.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3f894dbe0adb44609f3d532b8ea10820d61fdcb288b325a458dfc60fefb7db"},
|
||||
{file = "tiktoken-0.5.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:58ccfddb4e62f0df974e8f7e34a667981d9bb553a811256e617731bf1d007d19"},
|
||||
{file = "tiktoken-0.5.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58902a8bad2de4268c2a701f1c844d22bfa3cbcc485b10e8e3e28a050179330b"},
|
||||
{file = "tiktoken-0.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:5e39257826d0647fcac403d8fa0a474b30d02ec8ffc012cfaf13083e9b5e82c5"},
|
||||
{file = "tiktoken-0.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bde3b0fbf09a23072d39c1ede0e0821f759b4fa254a5f00078909158e90ae1f"},
|
||||
{file = "tiktoken-0.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2ddee082dcf1231ccf3a591d234935e6acf3e82ee28521fe99af9630bc8d2a60"},
|
||||
{file = "tiktoken-0.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35c057a6a4e777b5966a7540481a75a31429fc1cb4c9da87b71c8b75b5143037"},
|
||||
{file = "tiktoken-0.5.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c4a049b87e28f1dc60509f8eb7790bc8d11f9a70d99b9dd18dfdd81a084ffe6"},
|
||||
{file = "tiktoken-0.5.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5bf5ce759089f4f6521ea6ed89d8f988f7b396e9f4afb503b945f5c949c6bec2"},
|
||||
{file = "tiktoken-0.5.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0c964f554af1a96884e01188f480dad3fc224c4bbcf7af75d4b74c4b74ae0125"},
|
||||
{file = "tiktoken-0.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:368dd5726d2e8788e47ea04f32e20f72a2012a8a67af5b0b003d1e059f1d30a3"},
|
||||
{file = "tiktoken-0.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a2deef9115b8cd55536c0a02c0203512f8deb2447f41585e6d929a0b878a0dd2"},
|
||||
{file = "tiktoken-0.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2ed7d380195affbf886e2f8b92b14edfe13f4768ff5fc8de315adba5b773815e"},
|
||||
{file = "tiktoken-0.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c76fce01309c8140ffe15eb34ded2bb94789614b7d1d09e206838fc173776a18"},
|
||||
{file = "tiktoken-0.5.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60a5654d6a2e2d152637dd9a880b4482267dfc8a86ccf3ab1cec31a8c76bfae8"},
|
||||
{file = "tiktoken-0.5.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41d4d3228e051b779245a8ddd21d4336f8975563e92375662f42d05a19bdff41"},
|
||||
{file = "tiktoken-0.5.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c1cdec2c92fcde8c17a50814b525ae6a88e8e5b02030dc120b76e11db93f13"},
|
||||
{file = "tiktoken-0.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:84ddb36faedb448a50b246e13d1b6ee3437f60b7169b723a4b2abad75e914f3e"},
|
||||
{file = "tiktoken-0.5.2.tar.gz", hash = "sha256:f54c581f134a8ea96ce2023ab221d4d4d81ab614efa0b2fbce926387deb56c80"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -7206,6 +7334,17 @@ files = [
|
||||
{file = "types_certifi-2021.10.8.3-py3-none-any.whl", hash = "sha256:b2d1e325e69f71f7c78e5943d410e650b4707bb0ef32e4ddf3da37f54176e88a"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-protobuf"
|
||||
version = "4.24.0.20240129"
|
||||
description = "Typing stubs for protobuf"
|
||||
optional = true
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "types-protobuf-4.24.0.20240129.tar.gz", hash = "sha256:8a83dd3b9b76a33e08d8636c5daa212ace1396418ed91837635fcd564a624891"},
|
||||
{file = "types_protobuf-4.24.0.20240129-py3-none-any.whl", hash = "sha256:23be68cc29f3f5213b5c5878ac0151706182874040e220cfb11336f9ee642ead"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-pyyaml"
|
||||
version = "6.0.12.12"
|
||||
@@ -7217,6 +7356,20 @@ files = [
|
||||
{file = "types_PyYAML-6.0.12.12-py3-none-any.whl", hash = "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-requests"
|
||||
version = "2.31.0.6"
|
||||
description = "Typing stubs for requests"
|
||||
optional = true
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "types-requests-2.31.0.6.tar.gz", hash = "sha256:cd74ce3b53c461f1228a9b783929ac73a666658f223e28ed29753771477b3bd0"},
|
||||
{file = "types_requests-2.31.0.6-py3-none-any.whl", hash = "sha256:a2db9cb228a81da8348b49ad6db3f5519452dd20a9c1e1a868c83c5fe88fd1a9"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
types-urllib3 = "*"
|
||||
|
||||
[[package]]
|
||||
name = "types-toml"
|
||||
version = "0.10.8.7"
|
||||
@@ -7228,6 +7381,17 @@ files = [
|
||||
{file = "types_toml-0.10.8.7-py3-none-any.whl", hash = "sha256:61951da6ad410794c97bec035d59376ce1cbf4453dc9b6f90477e81e4442d631"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-urllib3"
|
||||
version = "1.26.25.14"
|
||||
description = "Typing stubs for urllib3"
|
||||
optional = true
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "types-urllib3-1.26.25.14.tar.gz", hash = "sha256:229b7f577c951b8c1b92c1bc2b2fdb0b49847bd2af6d1cc2a2e3dd340f3bda8f"},
|
||||
{file = "types_urllib3-1.26.25.14-py3-none-any.whl", hash = "sha256:9683bbb7fb72e32bfe9d2be6e04875fbe1b3eeec3cbb4ea231435aa7fd6b4f0e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.8.0"
|
||||
@@ -7835,20 +7999,6 @@ files = [
|
||||
[package.extras]
|
||||
test = ["pytest (>=6.0.0)", "setuptools (>=65)"]
|
||||
|
||||
[[package]]
|
||||
name = "win32-setctime"
|
||||
version = "1.1.0"
|
||||
description = "A small Python utility to set file creation time on Windows"
|
||||
optional = true
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"},
|
||||
{file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "1.15.0"
|
||||
@@ -8098,6 +8248,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link
|
||||
testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"]
|
||||
|
||||
[extras]
|
||||
aws-bedrock = ["boto3"]
|
||||
cohere = ["cohere"]
|
||||
dataloaders = ["docx2txt", "duckduckgo-search", "pytube", "sentence-transformers", "unstructured", "youtube-transcript-api"]
|
||||
discord = ["discord"]
|
||||
@@ -8110,6 +8261,7 @@ googledrive = ["google-api-python-client", "google-auth-httplib2", "google-auth-
|
||||
huggingface-hub = ["huggingface_hub"]
|
||||
llama2 = ["replicate"]
|
||||
milvus = ["pymilvus"]
|
||||
mistralai = ["langchain-mistralai"]
|
||||
modal = ["modal"]
|
||||
mysql = ["mysql-connector-python"]
|
||||
opensearch = ["opensearch-py"]
|
||||
@@ -8122,7 +8274,7 @@ rss-feed = ["feedparser", "listparser", "newspaper3k"]
|
||||
slack = ["flask", "slack-sdk"]
|
||||
streamlit = []
|
||||
together = ["together"]
|
||||
vertexai = ["google-cloud-aiplatform"]
|
||||
vertexai = ["langchain-google-vertexai"]
|
||||
weaviate = ["weaviate-client"]
|
||||
whatsapp = ["flask", "twilio"]
|
||||
youtube = ["youtube-transcript-api", "yt_dlp"]
|
||||
@@ -8130,4 +8282,4 @@ youtube = ["youtube-transcript-api", "yt_dlp"]
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.9,<3.12"
|
||||
content-hash = "02bd85e14374a9dc9b59523b8fb4baea7068251976ba7f87722cac94a9974ccc"
|
||||
content-hash = "1dbb690590123f505675544aa0e1b3668f0d3819f4832f3f3464ff16b69e39e9"
|
||||
|
||||
+12
-6
@@ -1,7 +1,7 @@
|
||||
[tool.poetry]
|
||||
name = "embedchain"
|
||||
version = "0.1.65"
|
||||
description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data"
|
||||
version = "0.1.79"
|
||||
description = "Simplest open source retrieval(RAG) framework"
|
||||
authors = [
|
||||
"Taranjeet Singh <taranjeet@embedchain.ai>",
|
||||
"Deshraj Yadav <deshraj@embedchain.ai>",
|
||||
@@ -93,7 +93,7 @@ color = true
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9,<3.12"
|
||||
python-dotenv = "^1.0.0"
|
||||
langchain = "^0.0.336"
|
||||
langchain = "^0.1.4"
|
||||
requests = "^2.31.0"
|
||||
openai = ">=1.1.1"
|
||||
chromadb = "^0.4.17"
|
||||
@@ -103,7 +103,7 @@ beautifulsoup4 = "^4.12.2"
|
||||
pypdf = "^3.11.0"
|
||||
gptcache = "^0.1.43"
|
||||
pysbd = "^0.3.4"
|
||||
tiktoken = { version = "^0.4.0", optional = true }
|
||||
tiktoken = { version = "^0.5.2", optional = true }
|
||||
youtube-transcript-api = { version = "^0.6.1", optional = true }
|
||||
pytube = { version = "^15.0.0", optional = true }
|
||||
duckduckgo-search = { version = "^3.8.5", optional = true }
|
||||
@@ -123,7 +123,7 @@ cohere = { version = "^4.27", optional = true }
|
||||
together = { version = "^0.2.8", optional = true }
|
||||
weaviate-client = { version = "^3.24.1", optional = true }
|
||||
docx2txt = { version = "^0.8", optional = true }
|
||||
pinecone-client = { version = "^2.2.4", optional = true }
|
||||
pinecone-client = { version = "^3.0.0", optional = true }
|
||||
qdrant-client = { version = "1.6.3", optional = true }
|
||||
unstructured = {extras = ["local-inference", "all-docs"], version = "^0.10.18", optional = true}
|
||||
huggingface_hub = { version = "^0.17.3", optional = true }
|
||||
@@ -149,6 +149,10 @@ google-auth-oauthlib = { version = "^1.2.0", optional = true }
|
||||
google-auth = { version = "^2.25.2", optional = true }
|
||||
google-auth-httplib2 = { version = "^0.2.0", optional = true }
|
||||
google-api-core = { version = "^2.15.0", optional = true }
|
||||
boto3 = { version = "^1.34.20", optional = true }
|
||||
langchain-mistralai = { version = "^0.0.3", optional = true }
|
||||
langchain-openai = "^0.0.5"
|
||||
langchain-google-vertexai = { version = "^0.0.5", optional = true }
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
black = "^23.3.0"
|
||||
@@ -188,7 +192,7 @@ dataloaders=[
|
||||
"sentence-transformers",
|
||||
"unstructured",
|
||||
]
|
||||
vertexai = ["google-cloud-aiplatform"]
|
||||
vertexai = ["langchain-google-vertexai"]
|
||||
llama2 = ["replicate"]
|
||||
gmail = [
|
||||
"requests",
|
||||
@@ -214,6 +218,8 @@ rss_feed = [
|
||||
google = ["google-generativeai"]
|
||||
modal = ["modal"]
|
||||
dropbox = ["dropbox"]
|
||||
aws_bedrock = ["boto3"]
|
||||
mistralai = ["langchain-mistralai"]
|
||||
|
||||
[tool.poetry.group.docs.dependencies]
|
||||
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from embedchain.config.evaluation.base import AnswerRelevanceConfig
|
||||
from embedchain.evaluation.metrics import AnswerRelevance
|
||||
from embedchain.utils.evaluation import EvalData, EvalMetric
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_data():
|
||||
return [
|
||||
EvalData(
|
||||
contexts=[
|
||||
"This is a test context 1.",
|
||||
],
|
||||
question="This is a test question 1.",
|
||||
answer="This is a test answer 1.",
|
||||
),
|
||||
EvalData(
|
||||
contexts=[
|
||||
"This is a test context 2-1.",
|
||||
"This is a test context 2-2.",
|
||||
],
|
||||
question="This is a test question 2.",
|
||||
answer="This is a test answer 2.",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_answer_relevance_metric(monkeypatch):
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test_api_key")
|
||||
metric = AnswerRelevance()
|
||||
return metric
|
||||
|
||||
|
||||
def test_answer_relevance_init(monkeypatch):
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test_api_key")
|
||||
metric = AnswerRelevance()
|
||||
assert metric.name == EvalMetric.ANSWER_RELEVANCY.value
|
||||
assert metric.config.model == "gpt-4"
|
||||
assert metric.config.embedder == "text-embedding-ada-002"
|
||||
assert metric.config.api_key is None
|
||||
assert metric.config.num_gen_questions == 1
|
||||
monkeypatch.delenv("OPENAI_API_KEY")
|
||||
|
||||
|
||||
def test_answer_relevance_init_with_config():
|
||||
metric = AnswerRelevance(config=AnswerRelevanceConfig(api_key="test_api_key"))
|
||||
assert metric.name == EvalMetric.ANSWER_RELEVANCY.value
|
||||
assert metric.config.model == "gpt-4"
|
||||
assert metric.config.embedder == "text-embedding-ada-002"
|
||||
assert metric.config.api_key == "test_api_key"
|
||||
assert metric.config.num_gen_questions == 1
|
||||
|
||||
|
||||
def test_answer_relevance_init_without_api_key(monkeypatch):
|
||||
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
||||
with pytest.raises(ValueError):
|
||||
AnswerRelevance()
|
||||
|
||||
|
||||
def test_generate_prompt(mock_answer_relevance_metric, mock_data):
|
||||
prompt = mock_answer_relevance_metric._generate_prompt(mock_data[0])
|
||||
assert "This is a test answer 1." in prompt
|
||||
|
||||
prompt = mock_answer_relevance_metric._generate_prompt(mock_data[1])
|
||||
assert "This is a test answer 2." in prompt
|
||||
|
||||
|
||||
def test_generate_questions(mock_answer_relevance_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type(
|
||||
"obj",
|
||||
(object,),
|
||||
{"message": type("obj", (object,), {"content": "This is a test question response.\n"})},
|
||||
)
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
prompt = mock_answer_relevance_metric._generate_prompt(mock_data[0])
|
||||
questions = mock_answer_relevance_metric._generate_questions(prompt)
|
||||
assert len(questions) == 1
|
||||
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type("obj", (object,), {"message": type("obj", (object,), {"content": "question 1?\nquestion2?"})})
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
prompt = mock_answer_relevance_metric._generate_prompt(mock_data[1])
|
||||
questions = mock_answer_relevance_metric._generate_questions(prompt)
|
||||
assert len(questions) == 2
|
||||
|
||||
|
||||
def test_generate_embedding(mock_answer_relevance_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.embeddings,
|
||||
"create",
|
||||
lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(),
|
||||
)
|
||||
embedding = mock_answer_relevance_metric._generate_embedding("This is a test question.")
|
||||
assert len(embedding) == 3
|
||||
|
||||
|
||||
def test_compute_similarity(mock_answer_relevance_metric, mock_data):
|
||||
original = np.array([1, 2, 3])
|
||||
generated = np.array([[1, 2, 3], [1, 2, 3]])
|
||||
similarity = mock_answer_relevance_metric._compute_similarity(original, generated)
|
||||
assert len(similarity) == 2
|
||||
assert similarity[0] == 1.0
|
||||
assert similarity[1] == 1.0
|
||||
|
||||
|
||||
def test_compute_score(mock_answer_relevance_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type(
|
||||
"obj",
|
||||
(object,),
|
||||
{"message": type("obj", (object,), {"content": "This is a test question response.\n"})},
|
||||
)
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.embeddings,
|
||||
"create",
|
||||
lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(),
|
||||
)
|
||||
score = mock_answer_relevance_metric._compute_score(mock_data[0])
|
||||
assert score == 1.0
|
||||
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type("obj", (object,), {"message": type("obj", (object,), {"content": "question 1?\nquestion2?"})})
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.embeddings,
|
||||
"create",
|
||||
lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(),
|
||||
)
|
||||
score = mock_answer_relevance_metric._compute_score(mock_data[1])
|
||||
assert score == 1.0
|
||||
|
||||
|
||||
def test_evaluate(mock_answer_relevance_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type(
|
||||
"obj",
|
||||
(object,),
|
||||
{"message": type("obj", (object,), {"content": "This is a test question response.\n"})},
|
||||
)
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.embeddings,
|
||||
"create",
|
||||
lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(),
|
||||
)
|
||||
score = mock_answer_relevance_metric.evaluate(mock_data)
|
||||
assert score == 1.0
|
||||
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type("obj", (object,), {"message": type("obj", (object,), {"content": "question 1?\nquestion2?"})})
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
mock_answer_relevance_metric.client.embeddings,
|
||||
"create",
|
||||
lambda input, model: type("obj", (object,), {"data": [type("obj", (object,), {"embedding": [1, 2, 3]})]})(),
|
||||
)
|
||||
score = mock_answer_relevance_metric.evaluate(mock_data)
|
||||
assert score == 1.0
|
||||
@@ -0,0 +1,100 @@
|
||||
import pytest
|
||||
|
||||
from embedchain.config.evaluation.base import ContextRelevanceConfig
|
||||
from embedchain.evaluation.metrics import ContextRelevance
|
||||
from embedchain.utils.evaluation import EvalData, EvalMetric
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_data():
|
||||
return [
|
||||
EvalData(
|
||||
contexts=[
|
||||
"This is a test context 1.",
|
||||
],
|
||||
question="This is a test question 1.",
|
||||
answer="This is a test answer 1.",
|
||||
),
|
||||
EvalData(
|
||||
contexts=[
|
||||
"This is a test context 2-1.",
|
||||
"This is a test context 2-2.",
|
||||
],
|
||||
question="This is a test question 2.",
|
||||
answer="This is a test answer 2.",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_context_relevance_metric(monkeypatch):
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test_api_key")
|
||||
metric = ContextRelevance()
|
||||
return metric
|
||||
|
||||
|
||||
def test_context_relevance_init(monkeypatch):
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test_api_key")
|
||||
metric = ContextRelevance()
|
||||
assert metric.name == EvalMetric.CONTEXT_RELEVANCY.value
|
||||
assert metric.config.model == "gpt-4"
|
||||
assert metric.config.api_key is None
|
||||
assert metric.config.language == "en"
|
||||
monkeypatch.delenv("OPENAI_API_KEY")
|
||||
|
||||
|
||||
def test_context_relevance_init_with_config():
|
||||
metric = ContextRelevance(config=ContextRelevanceConfig(api_key="test_api_key"))
|
||||
assert metric.name == EvalMetric.CONTEXT_RELEVANCY.value
|
||||
assert metric.config.model == "gpt-4"
|
||||
assert metric.config.api_key == "test_api_key"
|
||||
assert metric.config.language == "en"
|
||||
|
||||
|
||||
def test_context_relevance_init_without_api_key(monkeypatch):
|
||||
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
||||
with pytest.raises(ValueError):
|
||||
ContextRelevance()
|
||||
|
||||
|
||||
def test_sentence_segmenter(mock_context_relevance_metric):
|
||||
text = "This is a test sentence. This is another sentence."
|
||||
assert mock_context_relevance_metric._sentence_segmenter(text) == [
|
||||
"This is a test sentence. ",
|
||||
"This is another sentence.",
|
||||
]
|
||||
|
||||
|
||||
def test_compute_score(mock_context_relevance_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_context_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type("obj", (object,), {"message": type("obj", (object,), {"content": "This is a test reponse."})})
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
assert mock_context_relevance_metric._compute_score(mock_data[0]) == 1.0
|
||||
assert mock_context_relevance_metric._compute_score(mock_data[1]) == 0.5
|
||||
|
||||
|
||||
def test_evaluate(mock_context_relevance_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_context_relevance_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda model, messages: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type("obj", (object,), {"message": type("obj", (object,), {"content": "This is a test reponse."})})
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
assert mock_context_relevance_metric.evaluate(mock_data) == 0.75
|
||||
@@ -0,0 +1,152 @@
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from embedchain.config.evaluation.base import GroundednessConfig
|
||||
from embedchain.evaluation.metrics import Groundedness
|
||||
from embedchain.utils.evaluation import EvalData, EvalMetric
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_data():
|
||||
return [
|
||||
EvalData(
|
||||
contexts=[
|
||||
"This is a test context 1.",
|
||||
],
|
||||
question="This is a test question 1.",
|
||||
answer="This is a test answer 1.",
|
||||
),
|
||||
EvalData(
|
||||
contexts=[
|
||||
"This is a test context 2-1.",
|
||||
"This is a test context 2-2.",
|
||||
],
|
||||
question="This is a test question 2.",
|
||||
answer="This is a test answer 2.",
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_groundedness_metric(monkeypatch):
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test_api_key")
|
||||
metric = Groundedness()
|
||||
return metric
|
||||
|
||||
|
||||
def test_groundedness_init(monkeypatch):
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test_api_key")
|
||||
metric = Groundedness()
|
||||
assert metric.name == EvalMetric.GROUNDEDNESS.value
|
||||
assert metric.config.model == "gpt-4"
|
||||
assert metric.config.api_key is None
|
||||
monkeypatch.delenv("OPENAI_API_KEY")
|
||||
|
||||
|
||||
def test_groundedness_init_with_config():
|
||||
metric = Groundedness(config=GroundednessConfig(api_key="test_api_key"))
|
||||
assert metric.name == EvalMetric.GROUNDEDNESS.value
|
||||
assert metric.config.model == "gpt-4"
|
||||
assert metric.config.api_key == "test_api_key"
|
||||
|
||||
|
||||
def test_groundedness_init_without_api_key(monkeypatch):
|
||||
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
||||
with pytest.raises(ValueError):
|
||||
Groundedness()
|
||||
|
||||
|
||||
def test_generate_answer_claim_prompt(mock_groundedness_metric, mock_data):
|
||||
prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0])
|
||||
assert "This is a test question 1." in prompt
|
||||
assert "This is a test answer 1." in prompt
|
||||
|
||||
|
||||
def test_get_claim_statements(mock_groundedness_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_groundedness_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda *args, **kwargs: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"choices": [
|
||||
type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"message": type(
|
||||
"obj",
|
||||
(object,),
|
||||
{
|
||||
"content": """This is a test answer 1.
|
||||
This is a test answer 2.
|
||||
This is a test answer 3."""
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
]
|
||||
},
|
||||
)(),
|
||||
)
|
||||
prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0])
|
||||
claim_statements = mock_groundedness_metric._get_claim_statements(prompt=prompt)
|
||||
assert len(claim_statements) == 3
|
||||
assert "This is a test answer 1." in claim_statements
|
||||
|
||||
|
||||
def test_generate_claim_inference_prompt(mock_groundedness_metric, mock_data):
|
||||
prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0])
|
||||
claim_statements = [
|
||||
"This is a test claim 1.",
|
||||
"This is a test claim 2.",
|
||||
]
|
||||
prompt = mock_groundedness_metric._generate_claim_inference_prompt(
|
||||
data=mock_data[0], claim_statements=claim_statements
|
||||
)
|
||||
assert "This is a test context 1." in prompt
|
||||
assert "This is a test claim 1." in prompt
|
||||
|
||||
|
||||
def test_get_claim_verdict_scores(mock_groundedness_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_groundedness_metric.client.chat.completions,
|
||||
"create",
|
||||
lambda *args, **kwargs: type(
|
||||
"obj",
|
||||
(object,),
|
||||
{"choices": [type("obj", (object,), {"message": type("obj", (object,), {"content": "1\n0\n-1"})})]},
|
||||
)(),
|
||||
)
|
||||
prompt = mock_groundedness_metric._generate_answer_claim_prompt(data=mock_data[0])
|
||||
claim_statements = mock_groundedness_metric._get_claim_statements(prompt=prompt)
|
||||
prompt = mock_groundedness_metric._generate_claim_inference_prompt(
|
||||
data=mock_data[0], claim_statements=claim_statements
|
||||
)
|
||||
claim_verdict_scores = mock_groundedness_metric._get_claim_verdict_scores(prompt=prompt)
|
||||
assert len(claim_verdict_scores) == 3
|
||||
assert claim_verdict_scores[0] == 1
|
||||
assert claim_verdict_scores[1] == 0
|
||||
|
||||
|
||||
def test_compute_score(mock_groundedness_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
mock_groundedness_metric,
|
||||
"_get_claim_statements",
|
||||
lambda *args, **kwargs: np.array(
|
||||
[
|
||||
"This is a test claim 1.",
|
||||
"This is a test claim 2.",
|
||||
]
|
||||
),
|
||||
)
|
||||
monkeypatch.setattr(mock_groundedness_metric, "_get_claim_verdict_scores", lambda *args, **kwargs: np.array([1, 0]))
|
||||
score = mock_groundedness_metric._compute_score(data=mock_data[0])
|
||||
assert score == 0.5
|
||||
|
||||
|
||||
def test_evaluate(mock_groundedness_metric, mock_data, monkeypatch):
|
||||
monkeypatch.setattr(mock_groundedness_metric, "_compute_score", lambda *args, **kwargs: 0.5)
|
||||
score = mock_groundedness_metric.evaluate(dataset=mock_data)
|
||||
assert score == 0.5
|
||||
@@ -24,7 +24,7 @@ def test_get_llm_model_answer(anthropic_llm):
|
||||
|
||||
|
||||
def test_get_answer(anthropic_llm):
|
||||
with patch("langchain.chat_models.ChatAnthropic") as mock_chat:
|
||||
with patch("langchain_community.chat_models.ChatAnthropic") as mock_chat:
|
||||
mock_chat_instance = mock_chat.return_value
|
||||
mock_chat_instance.return_value = MagicMock(content="Test Response")
|
||||
|
||||
@@ -53,7 +53,7 @@ def test_get_messages(anthropic_llm):
|
||||
|
||||
|
||||
def test_get_answer_max_tokens_is_provided(anthropic_llm, caplog):
|
||||
with patch("langchain.chat_models.ChatAnthropic") as mock_chat:
|
||||
with patch("langchain_community.chat_models.ChatAnthropic") as mock_chat:
|
||||
mock_chat_instance = mock_chat.return_value
|
||||
mock_chat_instance.return_value = MagicMock(content="Test Response")
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import pytest
|
||||
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.llm.aws_bedrock import AWSBedrockLlm
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def config(monkeypatch):
|
||||
monkeypatch.setenv("AWS_ACCESS_KEY_ID", "test_access_key_id")
|
||||
monkeypatch.setenv("AWS_SECRET_ACCESS_KEY", "test_secret_access_key")
|
||||
monkeypatch.setenv("OPENAI_API_KEY", "test_api_key")
|
||||
config = BaseLlmConfig(
|
||||
model="amazon.titan-text-express-v1",
|
||||
model_kwargs={
|
||||
"temperature": 0.5,
|
||||
"topP": 1,
|
||||
"maxTokenCount": 1000,
|
||||
},
|
||||
)
|
||||
yield config
|
||||
monkeypatch.delenv("AWS_ACCESS_KEY_ID")
|
||||
monkeypatch.delenv("AWS_SECRET_ACCESS_KEY")
|
||||
monkeypatch.delenv("OPENAI_API_KEY")
|
||||
|
||||
|
||||
def test_get_llm_model_answer(config, mocker):
|
||||
mocked_get_answer = mocker.patch("embedchain.llm.aws_bedrock.AWSBedrockLlm._get_answer", return_value="Test answer")
|
||||
|
||||
llm = AWSBedrockLlm(config)
|
||||
answer = llm.get_llm_model_answer("Test query")
|
||||
|
||||
assert answer == "Test answer"
|
||||
mocked_get_answer.assert_called_once_with("Test query", config)
|
||||
|
||||
|
||||
def test_get_llm_model_answer_empty_prompt(config, mocker):
|
||||
mocked_get_answer = mocker.patch("embedchain.llm.aws_bedrock.AWSBedrockLlm._get_answer", return_value="Test answer")
|
||||
|
||||
llm = AWSBedrockLlm(config)
|
||||
answer = llm.get_llm_model_answer("")
|
||||
|
||||
assert answer == "Test answer"
|
||||
mocked_get_answer.assert_called_once_with("", config)
|
||||
|
||||
|
||||
def test_get_llm_model_answer_with_streaming(config, mocker):
|
||||
config.stream = True
|
||||
mocked_bedrock_chat = mocker.patch("embedchain.llm.aws_bedrock.Bedrock")
|
||||
|
||||
llm = AWSBedrockLlm(config)
|
||||
llm.get_llm_model_answer("Test query")
|
||||
|
||||
mocked_bedrock_chat.assert_called_once()
|
||||
callbacks = [callback[1]["callbacks"] for callback in mocked_bedrock_chat.call_args_list]
|
||||
assert any(isinstance(callback[0], StreamingStdOutCallbackHandler) for callback in callbacks)
|
||||
@@ -28,7 +28,7 @@ def test_get_llm_model_answer(azure_openai_llm):
|
||||
|
||||
|
||||
def test_get_answer(azure_openai_llm):
|
||||
with patch("langchain.chat_models.AzureChatOpenAI") as mock_chat:
|
||||
with patch("langchain_community.chat_models.AzureChatOpenAI") as mock_chat:
|
||||
mock_chat_instance = mock_chat.return_value
|
||||
mock_chat_instance.return_value = MagicMock(content="Test Response")
|
||||
|
||||
@@ -60,7 +60,7 @@ def test_get_messages(azure_openai_llm):
|
||||
|
||||
|
||||
def test_get_answer_top_p_is_provided(azure_openai_llm, caplog):
|
||||
with patch("langchain.chat_models.AzureChatOpenAI") as mock_chat:
|
||||
with patch("langchain_community.chat_models.AzureChatOpenAI") as mock_chat:
|
||||
mock_chat_instance = mock_chat.return_value
|
||||
mock_chat_instance.return_value = MagicMock(content="Test Response")
|
||||
|
||||
|
||||
@@ -66,5 +66,5 @@ class TestGeneratePrompt(unittest.TestCase):
|
||||
self.app.llm.set_history(["Past context 1", "Past context 2"])
|
||||
prompt = self.app.llm.generate_prompt("Test query", ["Test context"])
|
||||
|
||||
expected_prompt = "Context: Test context | Query: Test query | History: ['Past context 1', 'Past context 2']"
|
||||
expected_prompt = "Context: Test context | Query: Test query | History: Past context 1\nPast context 2"
|
||||
self.assertEqual(prompt, expected_prompt)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import pytest
|
||||
from langchain.llms.gpt4all import GPT4All as LangchainGPT4All
|
||||
from langchain_community.llms.gpt4all import GPT4All as LangchainGPT4All
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.llm.gpt4all import GPT4ALLLlm
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import pytest
|
||||
|
||||
from embedchain.config import BaseLlmConfig
|
||||
from embedchain.llm.mistralai import MistralAILlm
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mistralai_llm_config(monkeypatch):
|
||||
monkeypatch.setenv("MISTRAL_API_KEY", "fake_api_key")
|
||||
yield BaseLlmConfig(model="mistral-tiny", max_tokens=100, temperature=0.7, top_p=0.5, stream=False)
|
||||
monkeypatch.delenv("MISTRAL_API_KEY", raising=False)
|
||||
|
||||
|
||||
def test_mistralai_llm_init_missing_api_key(monkeypatch):
|
||||
monkeypatch.delenv("MISTRAL_API_KEY", raising=False)
|
||||
with pytest.raises(ValueError, match="Please set the MISTRAL_API_KEY environment variable."):
|
||||
MistralAILlm()
|
||||
|
||||
|
||||
def test_mistralai_llm_init(monkeypatch):
|
||||
monkeypatch.setenv("MISTRAL_API_KEY", "fake_api_key")
|
||||
llm = MistralAILlm()
|
||||
assert llm is not None
|
||||
|
||||
|
||||
def test_get_llm_model_answer(monkeypatch, mistralai_llm_config):
|
||||
def mock_get_answer(prompt, config):
|
||||
return "Generated Text"
|
||||
|
||||
monkeypatch.setattr(MistralAILlm, "_get_answer", mock_get_answer)
|
||||
llm = MistralAILlm(config=mistralai_llm_config)
|
||||
result = llm.get_llm_model_answer("test prompt")
|
||||
|
||||
assert result == "Generated Text"
|
||||
|
||||
|
||||
def test_get_llm_model_answer_with_system_prompt(monkeypatch, mistralai_llm_config):
|
||||
mistralai_llm_config.system_prompt = "Test system prompt"
|
||||
monkeypatch.setattr(MistralAILlm, "_get_answer", lambda prompt, config: "Generated Text")
|
||||
llm = MistralAILlm(config=mistralai_llm_config)
|
||||
result = llm.get_llm_model_answer("test prompt")
|
||||
|
||||
assert result == "Generated Text"
|
||||
|
||||
|
||||
def test_get_llm_model_answer_empty_prompt(monkeypatch, mistralai_llm_config):
|
||||
monkeypatch.setattr(MistralAILlm, "_get_answer", lambda prompt, config: "Generated Text")
|
||||
llm = MistralAILlm(config=mistralai_llm_config)
|
||||
result = llm.get_llm_model_answer("")
|
||||
|
||||
assert result == "Generated Text"
|
||||
|
||||
|
||||
def test_get_llm_model_answer_without_system_prompt(monkeypatch, mistralai_llm_config):
|
||||
mistralai_llm_config.system_prompt = None
|
||||
monkeypatch.setattr(MistralAILlm, "_get_answer", lambda prompt, config: "Generated Text")
|
||||
llm = MistralAILlm(config=mistralai_llm_config)
|
||||
result = llm.get_llm_model_answer("test prompt")
|
||||
|
||||
assert result == "Generated Text"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user