Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f3553040bc | |||
| 2b13984e11 | |||
| 0de9491c61 | |||
| c9df7a2020 | |||
| a7222e8c50 | |||
| 0373fa231c | |||
| 5f653e69ae | |||
| 2496ed133e | |||
| 62c0c52e31 | |||
| e36198dcc2 | |||
| 5fa6221f91 | |||
| f7696d1dc1 | |||
| 1878f8d4fc | |||
| 6c69ddef9b | |||
| 0c45020d81 | |||
| 4dfce44c1a | |||
| 1b661bb2fd | |||
| 73e726f6e3 | |||
| f58bbeffce | |||
| 99261e5fb5 | |||
| b4a59d1bd5 | |||
| 5c1f78879f | |||
| 94ba82f2a2 | |||
| b4ec14382b | |||
| 38ad57a22c | |||
| 60bbc180ba | |||
| a67d902b85 | |||
| ae2e9cb890 | |||
| 1976d38b25 | |||
| f5e3410e9a | |||
| 2f6ba642c7 | |||
| dd9b72dc62 | |||
| dd258c14b5 | |||
| 295cd3fac6 | |||
| c62663f2e4 | |||
| 367d6b70e2 | |||
| 27236bd1b2 | |||
| 6a82eb4287 | |||
| bd88fe3980 | |||
| 4f70fea6df | |||
| aee5bbb44b | |||
| a304ded500 | |||
| a54dde0509 | |||
| 52b4577d3b | |||
| e199f57279 | |||
| dec12b33a6 | |||
| 04daa1b206 | |||
| a7e1520d08 | |||
| 9e2b232c13 | |||
| 404e73af77 | |||
| a544b4d3ff | |||
| 6df63d9ca7 | |||
| 904baac153 | |||
| a926bcc640 | |||
| c0aafd38c9 | |||
| 19d80914df | |||
| d9d529987e | |||
| 12e6eaf802 | |||
| 7a026ea282 | |||
| 97dc90169b | |||
| 64c02f374a | |||
| 6c1ea7799e | |||
| 6be29f5bed | |||
| 68737da7a2 | |||
| da388b679f | |||
| 11f0d719f5 | |||
| e90673ae5b | |||
| f055028c6b | |||
| 106a338371 | |||
| 9fe80c5cca | |||
| 050706e95e | |||
| 6d2389de1c | |||
| dd97fad5a4 | |||
| 0f73ba9677 | |||
| 210fe9bb80 | |||
| ec8549d0e1 |
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
#### Before submitting a bug, please make sure the issue hasn't been already addressed by searching through [the existing and past issues](https://github.com/gventuri/pandas-ai/issues?q=is%3Aissue+sort%3Acreated-desc+).
|
||||
#### Before submitting a bug, please make sure the issue hasn't been already addressed by searching through [the existing and past issues](https://github.com/embedchain/embedchain/issues?q=is%3Aissue+sort%3Acreated-desc+).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 🐛 Describe the bug
|
||||
|
||||
@@ -175,3 +175,6 @@ notebooks/*.yaml
|
||||
.ipynb_checkpoints/
|
||||
|
||||
!configs/*.yaml
|
||||
|
||||
# cache db
|
||||
*.db
|
||||
|
||||
@@ -13,17 +13,17 @@
|
||||
<a href="https://pepy.tech/project/embedchain">
|
||||
<img src="https://static.pepy.tech/badge/embedchain" alt="Downloads">
|
||||
</a>
|
||||
<a href="https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw">
|
||||
<a href="https://embedchain.ai/slack">
|
||||
<img src="https://img.shields.io/badge/slack-embedchain-brightgreen.svg?logo=slack" alt="Slack">
|
||||
</a>
|
||||
<a href="https://discord.gg/CUU9FPhRNt">
|
||||
<a href="https://embedchain.ai/discord">
|
||||
<img src="https://dcbadge.vercel.app/api/server/6PzXDgEjG5?style=flat" alt="Discord">
|
||||
</a>
|
||||
<a href="https://twitter.com/embedchain">
|
||||
<img src="https://img.shields.io/twitter/follow/embedchain" alt="Twitter">
|
||||
</a>
|
||||
<a href="https://colab.research.google.com/drive/138lMWhENGeEu7Q1-6lNbNTHGLZXBBz_B?usp=sharing">
|
||||
<img src="https://camo.githubusercontent.com/84f0493939e0c4de4e6dbe113251b4bfb5353e57134ffd9fcab6b8714514d4d1/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open in Colab">
|
||||
<img src="https://colab.research.google.com/assets/colab-badge.svg" alt="Open in Colab">
|
||||
</a>
|
||||
<a href="https://codecov.io/gh/embedchain/embedchain">
|
||||
<img src="https://codecov.io/gh/embedchain/embedchain/graph/badge.svg?token=EMRRHZXW1Q" alt="codecov">
|
||||
@@ -39,16 +39,21 @@
|
||||
|
||||
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.
|
||||
|
||||
Embedchain streamlines the creation of RAG applications, offering a seamless process for managing various types of unstructured data. It efficiently segments data into manageable chunks, generates relevant embeddings, and stores them in a vector database for optimized retrieval. With a suite of diverse APIs, it enables users to extract contextual information, find precise answers, or engage in interactive chat conversations, all tailored to their own data.
|
||||
Embedchain streamlines the creation of Retrieval-Augmented Generation (RAG) applications, offering a seamless process for managing various types of unstructured data. It efficiently segments data into manageable chunks, generates relevant embeddings, and stores them in a vector database for optimized retrieval. With a suite of diverse APIs, it enables users to extract contextual information, find precise answers, or engage in interactive chat conversations, all tailored to their own data.
|
||||
|
||||
## 🔧 Quick install
|
||||
|
||||
### Python API
|
||||
|
||||
```bash
|
||||
pip install embedchain
|
||||
```
|
||||
|
||||
## 🔍 Usage and Demo
|
||||
## ✨ Live demo
|
||||
|
||||
Checkout the [Chat with PDF](https://embedchain.ai/demo/chat-pdf) live demo we created using Embedchain. You can find the source code [here](https://github.com/embedchain/embedchain/tree/main/examples/chat-pdf).
|
||||
|
||||
## 🔍 Usage
|
||||
|
||||
<!-- Demo GIF or Image -->
|
||||
<p align="center">
|
||||
@@ -76,7 +81,7 @@ elon_bot.query("How many companies does Elon Musk run and name those?")
|
||||
|
||||
You can also try it in your browser with Google Colab:
|
||||
|
||||
[](https://colab.research.google.com/drive/17ON1LPonnXAtLaZEebnOktstB_1cJJmh?usp=sharing)
|
||||
[](https://colab.research.google.com/drive/17ON1LPonnXAtLaZEebnOktstB_1cJJmh?usp=sharing)
|
||||
|
||||
## 📖 Documentation
|
||||
Comprehensive guides and API documentation are available to help you get the most out of Embedchain:
|
||||
@@ -88,7 +93,9 @@ Comprehensive guides and API documentation are available to help you get the mos
|
||||
|
||||
## 🔗 Join the Community
|
||||
|
||||
Connect with fellow developers and users by joining our [Slack Workspace](https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw) or [Discord Community](https://discord.gg/CUU9FPhRNt). Dive into discussions, ask questions, and share your experiences.
|
||||
* Connect with fellow developers by joining our [Slack Community](https://embedchain.ai/slack) or [Discord Community](https://embedchain.ai/discord).
|
||||
|
||||
* Dive into [GitHub Discussions](https://github.com/embedchain/embedchain/discussions), ask questions, or share your experiences.
|
||||
|
||||
## 🤝 Schedule a 1-on-1 Session
|
||||
|
||||
@@ -116,7 +123,7 @@ If you utilize this repository, please consider citing it with:
|
||||
```
|
||||
@misc{embedchain,
|
||||
author = {Taranjeet Singh, Deshraj Yadav},
|
||||
title = {Embedchain: Data platform for LLMs - load, index, retrieve, and sync any unstructured data},
|
||||
title = {Embedchain: The Open Source RAG Framework},
|
||||
year = {2023},
|
||||
publisher = {GitHub},
|
||||
journal = {GitHub repository},
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
app:
|
||||
config:
|
||||
id: 'my-app'
|
||||
collection_name: 'my-app'
|
||||
|
||||
llm:
|
||||
provider: openai
|
||||
|
||||
@@ -15,7 +15,7 @@ llm:
|
||||
max_tokens: 1000
|
||||
top_p: 1
|
||||
stream: false
|
||||
template: |
|
||||
prompt: |
|
||||
Use the following pieces of context to answer the query at the end.
|
||||
If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
llm:
|
||||
provider: ollama
|
||||
config:
|
||||
model: 'llama2'
|
||||
temperature: 0.5
|
||||
top_p: 1
|
||||
stream: true
|
||||
|
||||
embedder:
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'BAAI/bge-small-en-v1.5'
|
||||
@@ -1,7 +1,6 @@
|
||||
app:
|
||||
config:
|
||||
id: 'open-source-app'
|
||||
collection_name: 'open-source-app'
|
||||
collect_metrics: false
|
||||
|
||||
llm:
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
llm:
|
||||
provider: together
|
||||
config:
|
||||
model: mistralai/Mixtral-8x7B-Instruct-v0.1
|
||||
temperature: 0.5
|
||||
max_tokens: 1000
|
||||
@@ -0,0 +1,14 @@
|
||||
llm:
|
||||
provider: vllm
|
||||
config:
|
||||
model: 'meta-llama/Llama-2-70b-hf'
|
||||
temperature: 0.5
|
||||
top_p: 1
|
||||
top_k: 10
|
||||
stream: true
|
||||
trust_remote_code: true
|
||||
|
||||
embedder:
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'BAAI/bge-small-en-v1.5'
|
||||
@@ -25,7 +25,8 @@ llm:
|
||||
max_tokens: 1000
|
||||
top_p: 1
|
||||
stream: false
|
||||
template: |
|
||||
api_key: sk-xxx
|
||||
prompt: |
|
||||
Use the following pieces of context to answer the query at the end.
|
||||
If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||
|
||||
@@ -48,12 +49,21 @@ embedder:
|
||||
provider: openai
|
||||
config:
|
||||
model: 'text-embedding-ada-002'
|
||||
api_key: sk-xxx
|
||||
|
||||
chunker:
|
||||
chunk_size: 2000
|
||||
chunk_overlap: 100
|
||||
length_function: 'len'
|
||||
min_chunk_size: 0
|
||||
|
||||
cache:
|
||||
similarity_evaluation:
|
||||
strategy: distance
|
||||
max_distance: 1.0
|
||||
config:
|
||||
similarity_threshold: 0.8
|
||||
auto_flush: 50
|
||||
```
|
||||
|
||||
```json config.json
|
||||
@@ -71,8 +81,9 @@ chunker:
|
||||
"max_tokens": 1000,
|
||||
"top_p": 1,
|
||||
"stream": false,
|
||||
"template": "Use the following pieces of context to answer the query at the end.\nIf you don't know the answer, just say that you don't know, don't try to make up an answer.\n$context\n\nQuery: $query\n\nHelpful Answer:",
|
||||
"system_prompt": "Act as William Shakespeare. Answer the following questions in the style of William Shakespeare."
|
||||
"prompt": "Use the following pieces of context to answer the query at the end.\nIf you don't know the answer, just say that you don't know, don't try to make up an answer.\n$context\n\nQuery: $query\n\nHelpful Answer:",
|
||||
"system_prompt": "Act as William Shakespeare. Answer the following questions in the style of William Shakespeare.",
|
||||
"api_key": "sk-xxx"
|
||||
}
|
||||
},
|
||||
"vectordb": {
|
||||
@@ -86,7 +97,8 @@ chunker:
|
||||
"embedder": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"model": "text-embedding-ada-002"
|
||||
"model": "text-embedding-ada-002",
|
||||
"api_key": "sk-xxx"
|
||||
}
|
||||
},
|
||||
"chunker": {
|
||||
@@ -94,7 +106,17 @@ chunker:
|
||||
"chunk_overlap": 100,
|
||||
"length_function": "len",
|
||||
"min_chunk_size": 0
|
||||
}
|
||||
},
|
||||
"cache": {
|
||||
"similarity_evaluation": {
|
||||
"strategy": "distance",
|
||||
"max_distance": 1.0,
|
||||
},
|
||||
"config": {
|
||||
"similarity_threshold": 0.8,
|
||||
"auto_flush": 50,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
@@ -113,14 +135,15 @@ config = {
|
||||
'max_tokens': 1000,
|
||||
'top_p': 1,
|
||||
'stream': False,
|
||||
'template': (
|
||||
'prompt': (
|
||||
"Use the following pieces of context to answer the query at the end.\n"
|
||||
"If you don't know the answer, just say that you don't know, don't try to make up an answer.\n"
|
||||
"$context\n\nQuery: $query\n\nHelpful Answer:"
|
||||
),
|
||||
'system_prompt': (
|
||||
"Act as William Shakespeare. Answer the following questions in the style of William Shakespeare."
|
||||
)
|
||||
),
|
||||
'api_key': 'sk-xxx'
|
||||
}
|
||||
},
|
||||
'vectordb': {
|
||||
@@ -134,7 +157,8 @@ config = {
|
||||
'embedder': {
|
||||
'provider': 'openai',
|
||||
'config': {
|
||||
'model': 'text-embedding-ada-002'
|
||||
'model': 'text-embedding-ada-002',
|
||||
'api_key': 'sk-xxx'
|
||||
}
|
||||
},
|
||||
'chunker': {
|
||||
@@ -142,7 +166,17 @@ config = {
|
||||
'chunk_overlap': 100,
|
||||
'length_function': 'len',
|
||||
'min_chunk_size': 0
|
||||
}
|
||||
},
|
||||
'cache': {
|
||||
'similarity_evaluation': {
|
||||
'strategy': 'distance',
|
||||
'max_distance': 1.0,
|
||||
},
|
||||
'config': {
|
||||
'similarity_threshold': 0.8,
|
||||
'auto_flush': 50,
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
@@ -164,10 +198,11 @@ Alright, let's dive into what each key means in the yaml config above:
|
||||
- `max_tokens` (Integer): Controls how many tokens are used in the response.
|
||||
- `top_p` (Float): Controls the diversity of word selection. A higher value (closer to 1) makes word selection more diverse.
|
||||
- `stream` (Boolean): Controls if the response is streamed back to the user (set to false).
|
||||
- `template` (String): A custom template for the prompt that the model uses to generate responses.
|
||||
- `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).
|
||||
- `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.
|
||||
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`:
|
||||
@@ -179,12 +214,23 @@ 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'.
|
||||
- `api_key` (String): The API key for the embedding model.
|
||||
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.
|
||||
- `length_function` (String): The function used to calculate the length of each chunk of text. In this case, it's set to 'len'. You can also use any function import directly as a string here.
|
||||
- `min_chunk_size` (Integer): The minimum size of each chunk of text that is sent to the language model. Must be less than `chunk_size`, and greater than `chunk_overlap`.
|
||||
|
||||
6. `cache` Section: (Optional)
|
||||
- `similarity_evaluation` (Optional): The config for similarity evaluation strategy. If not provided, the default `distance` based similarity evaluation strategy is used.
|
||||
- `strategy` (String): The strategy to use for similarity evaluation. Currently, only `distance` and `exact` based similarity evaluation is supported. Defaults to `distance`.
|
||||
- `max_distance` (Float): The bound of maximum distance. Defaults to `1.0`.
|
||||
- `positive` (Boolean): If the larger distance indicates more similar of two entities, set it `True`, otherwise `False`. Defaults to `False`.
|
||||
- `config` (Optional): The config for initializing the cache. If not provided, sensible default values are used as mentioned below.
|
||||
- `similarity_threshold` (Float): The threshold for similarity evaluation. Defaults to `0.8`.
|
||||
- `auto_flush` (Integer): The number of queries after which the cache is flushed. Defaults to `20`.
|
||||
<Note>
|
||||
If you provide a cache section, the app will automatically configure and use a cache to store the results of the language model. This is useful if you want to speed up the response time and save inference cost of your app.
|
||||
</Note>
|
||||
If you have questions about the configuration above, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -21,7 +21,7 @@ title: '📊 add'
|
||||
### Load data from webpage
|
||||
|
||||
```python Code example
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
@@ -32,7 +32,7 @@ app.add("https://www.forbes.com/profile/elon-musk")
|
||||
### Load data from sitemap
|
||||
|
||||
```python Code example
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("https://python.langchain.com/sitemap.xml", data_type="sitemap")
|
||||
|
||||
@@ -18,6 +18,9 @@ title: '💬 chat'
|
||||
<ParamField path="where" type="dict" optional>
|
||||
A dictionary of key-value pairs to filter the chunks from the vector database. Defaults to `None`
|
||||
</ParamField>
|
||||
<ParamField path="session_id" type="str" optional>
|
||||
Session ID of the chat. This can be used to maintain chat history of different user sessions. Default value: `default`
|
||||
</ParamField>
|
||||
<ParamField path="citations" type="bool" optional>
|
||||
Return citations along with the LLM answer. Defaults to `False`
|
||||
</ParamField>
|
||||
@@ -36,7 +39,7 @@ title: '💬 chat'
|
||||
If you want to get the answer to question and return both answer and citations, use the following code snippet:
|
||||
|
||||
```python With Citations
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
@@ -53,27 +56,39 @@ print(sources)
|
||||
# [
|
||||
# (
|
||||
# 'Elon Musk PROFILEElon MuskCEO, Tesla$247.1B$2.3B (0.96%)Real Time Net Worthas of 12/7/23 ...',
|
||||
# 'https://www.forbes.com/profile/elon-musk',
|
||||
# '4651b266--4aa78839fe97'
|
||||
# {
|
||||
# 'url': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'score': 0.89,
|
||||
# ...
|
||||
# }
|
||||
# ),
|
||||
# (
|
||||
# '74% of the company, which is now called X.Wealth HistoryHOVER TO REVEAL NET WORTH BY YEARForbes ...',
|
||||
# 'https://www.forbes.com/profile/elon-musk',
|
||||
# '4651b266--4aa78839fe97'
|
||||
# {
|
||||
# 'url': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'score': 0.81,
|
||||
# ...
|
||||
# }
|
||||
# ),
|
||||
# (
|
||||
# 'founded in 2002, is worth nearly $150 billion after a $750 million tender offer in June 2023 ...',
|
||||
# 'https://www.forbes.com/profile/elon-musk',
|
||||
# '4651b266--4aa78839fe97'
|
||||
# {
|
||||
# 'url': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'score': 0.73,
|
||||
# ...
|
||||
# }
|
||||
# )
|
||||
# ]
|
||||
```
|
||||
|
||||
<Note>
|
||||
When `citations=True`, note that the returned `sources` are a list of tuples where each tuple has three elements (in the following order):
|
||||
When `citations=True`, note that the returned `sources` are a list of tuples where each tuple has two elements (in the following order):
|
||||
1. source chunk
|
||||
2. link of the source document
|
||||
3. document id (used for book keeping purposes)
|
||||
2. dictionary with metadata about the source chunk
|
||||
- `url`: url of the source
|
||||
- `doc_id`: document id (used for book keeping purposes)
|
||||
- `score`: score of the source chunk with respect to the question
|
||||
- other metadata you might have added at the time of adding the source
|
||||
</Note>
|
||||
|
||||
|
||||
@@ -82,7 +97,7 @@ When `citations=True`, note that the returned `sources` are a list of tuples whe
|
||||
If you just want to return answers and don't want to return citations, you can use the following example:
|
||||
|
||||
```python Without Citations
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
@@ -95,3 +110,22 @@ answer = app.chat("What is the net worth of Elon?")
|
||||
print(answer)
|
||||
# Answer: The net worth of Elon Musk is $221.9 billion.
|
||||
```
|
||||
|
||||
### With session id
|
||||
|
||||
If you want to maintain chat sessions for different users, you can simply pass the `session_id` keyword argument. See the example below:
|
||||
|
||||
```python With session id
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
|
||||
# Chat on your data using `.chat()`
|
||||
app.chat("What is the net worth of Elon Musk?", session_id="user1")
|
||||
# 'The net worth of Elon Musk is $250.8 billion.'
|
||||
app.chat("What is the net worth of Bill Gates?", session_id="user2")
|
||||
# "I don't know the current net worth of Bill Gates."
|
||||
app.chat("What was my last question", session_id="user1")
|
||||
# 'Your last question was "What is the net worth of Elon Musk?"'
|
||||
```
|
||||
|
||||
@@ -7,7 +7,7 @@ title: 🗑 delete
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ The `deploy()` method not only deploys your pipeline but also efficiently manage
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
|
||||
@@ -41,7 +41,7 @@ You can create an embedchain pipeline instance using the following methods:
|
||||
### Default setting
|
||||
|
||||
```python Code Example
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
app = App()
|
||||
```
|
||||
|
||||
@@ -49,7 +49,7 @@ app = App()
|
||||
### Python Dict
|
||||
|
||||
```python Code Example
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
config_dict = {
|
||||
'llm': {
|
||||
@@ -76,7 +76,7 @@ app = App.from_config(config=config_dict)
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load llm configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -103,7 +103,7 @@ embedder:
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load llm configuration from config.json file
|
||||
app = App.from_config(config_path="config.json")
|
||||
|
||||
@@ -36,7 +36,7 @@ title: '❓ query'
|
||||
If you want to get the answer to question and return both answer and citations, use the following code snippet:
|
||||
|
||||
```python With Citations
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
@@ -53,27 +53,39 @@ print(sources)
|
||||
# [
|
||||
# (
|
||||
# 'Elon Musk PROFILEElon MuskCEO, Tesla$247.1B$2.3B (0.96%)Real Time Net Worthas of 12/7/23 ...',
|
||||
# 'https://www.forbes.com/profile/elon-musk',
|
||||
# '4651b266--4aa78839fe97'
|
||||
# {
|
||||
# 'url': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'score': 0.89,
|
||||
# ...
|
||||
# }
|
||||
# ),
|
||||
# (
|
||||
# '74% of the company, which is now called X.Wealth HistoryHOVER TO REVEAL NET WORTH BY YEARForbes ...',
|
||||
# 'https://www.forbes.com/profile/elon-musk',
|
||||
# '4651b266--4aa78839fe97'
|
||||
# {
|
||||
# 'url': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'score': 0.81,
|
||||
# ...
|
||||
# }
|
||||
# ),
|
||||
# (
|
||||
# 'founded in 2002, is worth nearly $150 billion after a $750 million tender offer in June 2023 ...',
|
||||
# 'https://www.forbes.com/profile/elon-musk',
|
||||
# '4651b266--4aa78839fe97'
|
||||
# {
|
||||
# 'url': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'score': 0.73,
|
||||
# ...
|
||||
# }
|
||||
# )
|
||||
# ]
|
||||
```
|
||||
|
||||
<Note>
|
||||
When `citations=True`, note that the returned `sources` are a list of tuples where each tuple has three elements (in the following order):
|
||||
When `citations=True`, note that the returned `sources` are a list of tuples where each tuple has two elements (in the following order):
|
||||
1. source chunk
|
||||
2. link of the source document
|
||||
3. document id (used for book keeping purposes)
|
||||
2. dictionary with metadata about the source chunk
|
||||
- `url`: url of the source
|
||||
- `doc_id`: document id (used for book keeping purposes)
|
||||
- `score`: score of the source chunk with respect to the question
|
||||
- other metadata you might have added at the time of adding the source
|
||||
</Note>
|
||||
|
||||
### Without citations
|
||||
@@ -81,7 +93,7 @@ When `citations=True`, note that the returned `sources` are a list of tuples whe
|
||||
If you just want to return answers and don't want to return citations, you can use the following example:
|
||||
|
||||
```python Without Citations
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
|
||||
@@ -7,7 +7,7 @@ title: 🔄 reset
|
||||
## Usage
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
|
||||
@@ -24,7 +24,7 @@ title: '🔍 search'
|
||||
Refer to the following example on how to use the search api:
|
||||
|
||||
```python Code example
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# Initialize app
|
||||
app = App()
|
||||
@@ -38,14 +38,20 @@ print(context)
|
||||
# Context:
|
||||
# [
|
||||
# {
|
||||
# 'context': 'Elon Musk PROFILEElon MuskCEO, Tesla$221.9BReal Time Net Worthas of 10/29/23Reflects change since 5 pm ET of prior trading day. 1 in the world todayPhoto by Martin Schoeller for ForbesAbout Elon MuskElon Musk cofounded six companies, including electric car maker Tesla, rocket producer SpaceX and tunneling startup Boring Company.He owns about 21% of Tesla between stock and options, but has pledged more than half his shares as collateral for personal loans of up to $3.5 billion.SpaceX, founded in',
|
||||
# 'source': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'document_id': 'some_document_id'
|
||||
# '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 BY YEARForbes Lists 1Forbes 400 (2023)The Richest Person In Every State (2023) 2Billionaires (2023) 1Innovative Leaders (2019) 25Powerful People (2018) 12Richest In Tech (2017)Global Game Changers (2016)More ListsPersonal StatsAge52Source of WealthTesla, SpaceX, Self MadeSelf-Made Score8Philanthropy Score1ResidenceAustin, TexasCitizenshipUnited StatesMarital StatusSingleChildren11EducationBachelor of Arts/Science, University',
|
||||
# 'source': 'https://www.forbes.com/profile/elon-musk',
|
||||
# 'document_id': 'some_document_id'
|
||||
# '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,
|
||||
# }
|
||||
# }
|
||||
# ]
|
||||
```
|
||||
|
||||
@@ -5,7 +5,7 @@ title: "🐝 Beehiiv"
|
||||
To add any Beehiiv data sources to your app, just add the base url as the source and set the data_type to `beehiiv`.
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -2,18 +2,27 @@
|
||||
title: '📊 CSV'
|
||||
---
|
||||
|
||||
To add any csv file, use the data_type as `csv`. `csv` allows remote urls and conventional file paths. Headers are included for each line, so if you have an `age` column, `18` will be added as `age: 18`. Eg:
|
||||
You can load any csv file from your local file system or through a URL. Headers are included for each line, so if you have an `age` column, `18` will be added as `age: 18`.
|
||||
|
||||
## Usage
|
||||
|
||||
### Load from a local file
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
|
||||
from embedchain import App
|
||||
app = App()
|
||||
app.add('https://people.sc.fsu.edu/~jburkardt/data/csv/airtravel.csv', data_type="csv")
|
||||
# Or add using the local file path
|
||||
# app.add('/path/to/file.csv', data_type="csv")
|
||||
|
||||
app.query("Summarize the air travel data")
|
||||
# Answer: The air travel data shows the number of flights for the months of July in the years 1958, 1959, and 1960. In July 1958, there were 491 flights, in July 1959 there were 548 flights, and in July 1960 there were 622 flights.
|
||||
app.add('/path/to/file.csv', data_type='csv')
|
||||
```
|
||||
|
||||
Note: There is a size limit allowed for csv file beyond which it can throw error. This limit is set by the LLMs. Please consider chunking large csv files into smaller csv files.
|
||||
### Load from URL
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
app = App()
|
||||
app.add('https://people.sc.fsu.edu/~jburkardt/data/csv/airtravel.csv', data_type="csv")
|
||||
```
|
||||
|
||||
<Note>
|
||||
There is a size limit allowed for csv file beyond which it can throw error. This limit is set by the LLMs. Please consider chunking large csv files into smaller csv files.
|
||||
</Note>
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ title: '⚙️ Custom'
|
||||
When we say "custom", we mean that you can customize the loader and chunker to your needs. This is done by passing a custom loader and chunker to the `add` method.
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
import your_loader
|
||||
import your_chunker
|
||||
|
||||
@@ -27,7 +27,7 @@ app.add("source", data_type="custom", loader=loader, chunker=chunker)
|
||||
Example:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
from embedchain.loaders.github import GithubLoader
|
||||
|
||||
app = App()
|
||||
|
||||
@@ -35,7 +35,7 @@ Default behavior is to create a persistent vector db in the directory **./db**.
|
||||
Create a local index:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
naval_chat_bot = App()
|
||||
naval_chat_bot.add("https://www.youtube.com/watch?v=3qHkcs3kG44")
|
||||
@@ -45,7 +45,7 @@ naval_chat_bot.add("https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Alma
|
||||
You can reuse the local index with the same code, but without adding new documents:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
naval_chat_bot = App()
|
||||
print(naval_chat_bot.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?"))
|
||||
@@ -56,7 +56,7 @@ print(naval_chat_bot.query("What unique capacity does Naval argue humans possess
|
||||
You can reset the app by simply calling the `reset` method. This will delete the vector database and all other app related files.
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("https://www.youtube.com/watch?v=3qHkcs3kG44")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: '📁 Directory'
|
||||
title: '📁 Directory/Folder'
|
||||
---
|
||||
|
||||
To use an entire directory as data source, just add `data_type` as `directory` and pass in the path of the local directory.
|
||||
@@ -8,7 +8,7 @@ To use an entire directory as data source, just add `data_type` as `directory` a
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
|
||||
@@ -23,7 +23,7 @@ print(response)
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
from embedchain.loaders.directory_loader import DirectoryLoader
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
|
||||
@@ -12,7 +12,7 @@ To add any Discord channel messages to your app, just add the `channel_id` as th
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# add your discord "BOT" token
|
||||
os.environ["DISCORD_TOKEN"] = "xxx"
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
title: '📚 Code documentation'
|
||||
title: '📚 Code Docs website'
|
||||
---
|
||||
|
||||
To add any code documentation website as a loader, use the data_type as `docs_site`. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("https://docs.embedchain.ai/", data_type="docs_site")
|
||||
app.query("What is Embedchain?")
|
||||
# Answer: Embedchain is a platform that utilizes various components, including paid/proprietary ones, to provide what is believed to be the best configuration available. It uses LLM (Language Model) providers such as OpenAI, Anthpropic, Vertex_AI, GPT4ALL, Azure_OpenAI, LLAMA2, JINA, and COHERE. Embedchain allows users to import and utilize these LLM providers for their applications.'
|
||||
# Answer: Embedchain is a platform that utilizes various components, including paid/proprietary ones, to provide what is believed to be the best configuration available. It uses LLM (Language Model) providers such as OpenAI, Anthpropic, Vertex_AI, GPT4ALL, Azure_OpenAI, LLAMA2, JINA, Ollama, Together and COHERE. Embedchain allows users to import and utilize these LLM providers for their applications.'
|
||||
```
|
||||
|
||||
@@ -7,7 +7,7 @@ title: '📄 Docx file'
|
||||
To add any doc/docx file, use the data_type as `docx`. `docx` allows remote urls and conventional file paths. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add('https://example.com/content/intro.docx', data_type="docx")
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: '💾 Dropbox'
|
||||
---
|
||||
|
||||
To load folders or files from your Dropbox account, configure the `data_type` parameter as `dropbox` and specify the path to the desired file or folder, starting from the root directory of your Dropbox account.
|
||||
|
||||
For Dropbox access, an **access token** is required. Obtain this token by visiting [Dropbox Developer Apps](https://www.dropbox.com/developers/apps). There, create a new app and generate an access token for it.
|
||||
|
||||
Ensure your app has the following settings activated:
|
||||
|
||||
- In the Permissions section, enable `files.content.read` and `files.metadata.read`.
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
|
||||
os.environ["DROPBOX_ACCESS_TOKEN"] = "sl.xxx"
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
|
||||
app = App()
|
||||
|
||||
# any path from the root of your dropbox account, you can leave it "" for the root folder
|
||||
app.add("/test", data_type="dropbox")
|
||||
|
||||
print(app.query("Which two celebrities are mentioned here?"))
|
||||
# The two celebrities mentioned in the given context are Elon Musk and Jeff Bezos.
|
||||
```
|
||||
@@ -24,7 +24,7 @@ To use this you need to save `credentials.json` in the directory from where you
|
||||
12. Put the `.json` file in your current directory and rename it to `credentials.json`
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
title: 'Google Drive'
|
||||
---
|
||||
|
||||
To use GoogleDriveLoader you must install the extra dependencies with `pip install --upgrade embedchain[googledrive]`.
|
||||
|
||||
The data_type must be `google_drive`. Otherwise, it will be considered a regular web page.
|
||||
|
||||
Google Drive requires the setup of credentials. This can be done by following the steps below:
|
||||
|
||||
1. Go to the [Google Cloud Console](https://console.cloud.google.com/apis/credentials).
|
||||
2. Create a project if you don't have one already.
|
||||
3. Enable the [Google Drive API](https://console.cloud.google.com/flows/enableapi?apiid=drive.googleapis.com)
|
||||
4. [Authorize credentials for desktop app](https://developers.google.com/drive/api/quickstart/python#authorize_credentials_for_a_desktop_application)
|
||||
5. When done, you will be able to download the credentials in `json` format. Rename the downloaded file to `credentials.json` and save it in `~/.credentials/credentials.json`
|
||||
6. Set the environment variable `GOOGLE_APPLICATION_CREDENTIALS=~/.credentials/credentials.json`
|
||||
|
||||
The first time you use the loader, you will be prompted to enter your Google account credentials.
|
||||
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
|
||||
app = App()
|
||||
|
||||
url = "https://drive.google.com/drive/u/0/folders/xxx-xxx"
|
||||
app.add(url, data_type="google_drive")
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: "🖼️ Image"
|
||||
---
|
||||
|
||||
|
||||
To use an image as data source, just add `data_type` as `image` and pass in the path of the image (local or hosted).
|
||||
|
||||
We use [GPT4 Vision](https://platform.openai.com/docs/guides/vision) to generate meaning of the image using a custom prompt, and then use the generated text as the data source.
|
||||
|
||||
You would require an OpenAI API key with access to `gpt-4-vision-preview` model to use this feature.
|
||||
|
||||
### Without customization
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import App
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
|
||||
app = App()
|
||||
app.add("./Elon-Musk.webp", data_type="image")
|
||||
response = app.query("Describe the man in the image.")
|
||||
print(response)
|
||||
# Answer: The man in the image is dressed in formal attire, wearing a dark suit jacket and a white collared shirt. He has short hair and is standing. He appears to be gazing off to the side with a reflective expression. The background is dark with faint, warm-toned vertical lines, possibly from a lit environment behind the individual or reflections. The overall atmosphere is somewhat moody and introspective.
|
||||
```
|
||||
|
||||
### Customization
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import App
|
||||
from embedchain.loaders.image import ImageLoader
|
||||
|
||||
image_loader = ImageLoader(
|
||||
max_tokens=100,
|
||||
api_key="sk-xxx",
|
||||
prompt="Is the person looking wealthy? Structure your thoughts around what you see in the image.",
|
||||
)
|
||||
|
||||
app = App()
|
||||
app.add("./Elon-Musk.webp", data_type="image", loader=image_loader)
|
||||
response = app.query("Describe the man in the image.")
|
||||
print(response)
|
||||
# Answer: The man in the image appears to be well-dressed in a suit and shirt, suggesting that he may be in a professional or formal setting. His composed demeanor and confident posture further indicate a sense of self-assurance. Based on these visual cues, one could infer that the man may have a certain level of economic or social status, possibly indicating wealth or professional success.
|
||||
```
|
||||
@@ -21,7 +21,7 @@ If you would like to add other data structures (e.g. list, dict etc.), convert i
|
||||
<CodeGroup>
|
||||
|
||||
```python python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ title: '📝 Mdx file'
|
||||
To add any `.mdx` file to your app, use the data_type (first argument to `.add()` method) as `mdx`. Note that this supports support mdx file present on machine, so this should be a file path. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add('path/to/file.mdx', data_type='mdx')
|
||||
|
||||
@@ -8,7 +8,7 @@ To load a notion page, use the data_type as `notion`. Since it is hard to automa
|
||||
The next argument must **end** with the `notion page id`. The id is a 32-character string. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ title: 🙌 OpenAPI
|
||||
To add any OpenAPI spec yaml file (currently the json file will be detected as JSON data type), use the data_type as 'openapi'. 'openapi' allows remote urls and conventional file paths.
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -8,28 +8,31 @@ Embedchain comes with built-in support for various data sources. We handle the c
|
||||
<Card title="📰 PDF file" href="/components/data-sources/pdf-file"></Card>
|
||||
<Card title="📊 CSV file" href="/components/data-sources/csv"></Card>
|
||||
<Card title="📃 JSON file" href="/components/data-sources/json"></Card>
|
||||
<Card title="📺 Youtube" href="/components/data-sources/youtube-video"></Card>
|
||||
<Card title="📝 Text" href="/components/data-sources/text"></Card>
|
||||
<Card title="📚 Documentation website" href="/components/data-sources/docs-site"></Card>
|
||||
<Card title="📄 DOCX file" href="/components/data-sources/docx"></Card>
|
||||
<Card title="📁 Directory/ Folder" href="/components/data-sources/directory"></Card>
|
||||
<Card title="🌐 HTML Web page" href="/components/data-sources/web-page"></Card>
|
||||
<Card title="📽️ Youtube Channel" href="/components/data-sources/youtube-channel"></Card>
|
||||
<Card title="📺 Youtube Video" href="/components/data-sources/youtube-video"></Card>
|
||||
<Card title="📚 Docs website" href="/components/data-sources/docs-site"></Card>
|
||||
<Card title="📝 MDX file" href="/components/data-sources/mdx"></Card>
|
||||
<Card title="📄 DOCX file" href="/components/data-sources/docx"></Card>
|
||||
<Card title="📓 Notion" href="/components/data-sources/notion"></Card>
|
||||
<Card title="❓💬 Q&A pair" href="/components/data-sources/qna"></Card>
|
||||
<Card title="🗺️ Sitemap" href="/components/data-sources/sitemap"></Card>
|
||||
<Card title="🌐 Web page" href="/components/data-sources/web-page"></Card>
|
||||
<Card title="🧾 XML file" href="/components/data-sources/xml"></Card>
|
||||
<Card title="❓💬 Q&A pair" href="/components/data-sources/qna"></Card>
|
||||
<Card title="🙌 OpenAPI" href="/components/data-sources/openapi"></Card>
|
||||
<Card title="📬 Gmail" href="/components/data-sources/gmail"></Card>
|
||||
<Card title="📝 Github" href="/components/data-sources/github"></Card>
|
||||
<Card title="🐘 Postgres" href="/components/data-sources/postgres"></Card>
|
||||
<Card title="🐬 MySQL" href="/components/data-sources/mysql"></Card>
|
||||
<Card title="🤖 Slack" href="/components/data-sources/slack"></Card>
|
||||
<Card title="🗨️ Discourse" href="/components/data-sources/discourse"></Card>
|
||||
<Card title="💬 Discord" href="/components/data-sources/discord"></Card>
|
||||
<Card title="📝 Github" href="/components/data-sources/github"></Card>
|
||||
<Card title="⚙️ Custom" href="/components/data-sources/custom"></Card>
|
||||
<Card title="🗨️ Discourse" href="/components/data-sources/discourse"></Card>
|
||||
<Card title="📝 Substack" href="/components/data-sources/substack"></Card>
|
||||
<Card title="🐝 Beehiiv" href="/components/data-sources/beehiiv"></Card>
|
||||
<Card title="📁 Directory" href="/components/data-sources/directory"></Card>
|
||||
<Card title="💾 Dropbox" href="/components/data-sources/dropbox"></Card>
|
||||
<Card title="🖼️ Image" href="/components/data-sources/image"></Card>
|
||||
<Card title="⚙️ Custom" href="/components/data-sources/custom"></Card>
|
||||
</CardGroup>
|
||||
|
||||
<br/ >
|
||||
|
||||
@@ -1,17 +1,50 @@
|
||||
---
|
||||
title: '📰 PDF file'
|
||||
title: '📰 PDF'
|
||||
---
|
||||
|
||||
To add any pdf file, use the data_type as `pdf_file`. Eg:
|
||||
You can load any pdf file from your local file system or through a URL.
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
## Setup
|
||||
Install the following packages for loading youtube videos which help in transcription.
|
||||
|
||||
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?")
|
||||
# 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 moving away from complex recurrent or convolutional neural networks and instead using attention mechanisms to connect the encoder and decoder in sequence transduction models.
|
||||
```bash
|
||||
pip install pytube youtube-transcript-api
|
||||
```
|
||||
|
||||
Note that we do not support password protected pdfs.
|
||||
## Usage
|
||||
|
||||
### Load from a local file
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
app = App()
|
||||
app.add('/path/to/file.pdf', data_type='pdf_file')
|
||||
```
|
||||
|
||||
### Load from URL
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
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:
|
||||
# [
|
||||
# (
|
||||
# 'Provided proper attribution is ...',
|
||||
# {
|
||||
# 'page': 0,
|
||||
# 'url': 'https://arxiv.org/pdf/1706.03762.pdf',
|
||||
# 'score': 0.3676220203221626,
|
||||
# ...
|
||||
# }
|
||||
# ),
|
||||
# ]
|
||||
```
|
||||
|
||||
We also store the page number under the key `page` with each chunk that helps understand where the answer is coming from. You can fetch the `page` key while during retrieval (refer to the example given above).
|
||||
|
||||
<Note>
|
||||
Note that we do not support password protected pdf files.
|
||||
</Note>
|
||||
|
||||
@@ -5,7 +5,7 @@ title: '❓💬 Queston and answer pair'
|
||||
QnA pair is a local data type. To supply your own QnA pair, use the data_type as `qna_pair` and enter a tuple. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ title: '🗺️ Sitemap'
|
||||
Add all web pages from an xml-sitemap. Filters non-text files. Use the data_type as `sitemap`. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ This will automatically retrieve data from the workspace associated with the use
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["SLACK_USER_TOKEN"] = "xoxp-xxx"
|
||||
app = App()
|
||||
|
||||
@@ -5,7 +5,7 @@ title: "📝 Substack"
|
||||
To add any Substack data sources to your app, just add the main base url as the source and set the data_type to `substack`.
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ title: '📝 Text'
|
||||
Text is a local data type. To supply your own text, use the data_type as `text` and enter a string. The text is not processed, this can be very versatile. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
---
|
||||
title: '🌐 Web page'
|
||||
title: '🌐 HTML Web page'
|
||||
---
|
||||
|
||||
To add any web page, use the data_type as `web_page`. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ title: '🧾 XML file'
|
||||
To add any xml file, use the data_type as `xml`. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: '📽️ Youtube Channel'
|
||||
---
|
||||
|
||||
To add all the videos from a youtube channel to your app, use the data_type as `youtube_channel`.
|
||||
|
||||
<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]"
|
||||
```
|
||||
</Note>
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("@channel_name", data_type="youtube_channel")
|
||||
```
|
||||
@@ -1,12 +1,11 @@
|
||||
---
|
||||
title: '📺 Youtube'
|
||||
title: '📺 Youtube Video'
|
||||
---
|
||||
|
||||
|
||||
To add any youtube video to your app, use the data_type (first argument to `.add()` method) as `youtube_video`. Eg:
|
||||
To add any youtube video to your app, use the data_type as `youtube_video`. Eg:
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add('a_valid_youtube_url_here', data_type='youtube_video')
|
||||
|
||||
@@ -25,7 +25,7 @@ Once you have obtained the key, you can use it like this:
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||
|
||||
@@ -52,7 +52,7 @@ To use Google AI embedding function, you have to set the `GOOGLE_API_KEY` enviro
|
||||
<CodeGroup>
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["GOOGLE_API_KEY"] = "xxx"
|
||||
|
||||
@@ -81,7 +81,7 @@ To use Azure OpenAI embedding model, you have to set some of the azure openai re
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["OPENAI_API_TYPE"] = "azure"
|
||||
os.environ["AZURE_OPENAI_ENDPOINT"] = "https://xxx.openai.azure.com/"
|
||||
@@ -119,7 +119,7 @@ GPT4All supports generating high quality embeddings of arbitrary length document
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load embedding model configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -148,7 +148,7 @@ Hugging Face supports generating embeddings of arbitrary length documents of tex
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load embedding model configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -179,7 +179,7 @@ Embedchain supports Google's VertexAI embeddings model through a simple interfac
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load embedding model configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: 🧩 Introduction
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
You can configure following components
|
||||
|
||||
* [Data Source](/components/data-sources/overview)
|
||||
* [LLM](/components/llms)
|
||||
* [Embedding Model](/components/embedding-models)
|
||||
* [Vector Database](/components/vector-databases)
|
||||
@@ -12,6 +12,9 @@ Embedchain comes with built-in support for various popular large language models
|
||||
<Card title="Azure OpenAI" href="#azure-openai"></Card>
|
||||
<Card title="Anthropic" href="#anthropic"></Card>
|
||||
<Card title="Cohere" href="#cohere"></Card>
|
||||
<Card title="Together" href="#together"></Card>
|
||||
<Card title="Ollama" href="#ollama"></Card>
|
||||
<Card title="vLLM" href="#vllm"></Card>
|
||||
<Card title="GPT4All" href="#gpt4all"></Card>
|
||||
<Card title="JinaChat" href="#jinachat"></Card>
|
||||
<Card title="Hugging Face" href="#hugging-face"></Card>
|
||||
@@ -27,7 +30,7 @@ Once you have obtained the key, you can use it like this:
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||
|
||||
@@ -42,7 +45,7 @@ If you are looking to configure the different parameters of the LLM, you can do
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||
|
||||
@@ -69,7 +72,7 @@ Examples:
|
||||
<Accordion title="Using Pydantic Models">
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
import requests
|
||||
from pydantic import BaseModel, Field, ValidationError, field_validator
|
||||
@@ -121,7 +124,7 @@ print(result)
|
||||
<Accordion title="Using OpenAI JSON schema">
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
import requests
|
||||
from pydantic import BaseModel, Field, ValidationError, field_validator
|
||||
@@ -156,7 +159,7 @@ print(result)
|
||||
<Accordion title="Using actual python functions">
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
import requests
|
||||
from pydantic import BaseModel, Field, ValidationError, field_validator
|
||||
@@ -190,7 +193,7 @@ To use Google AI model, you have to set the `GOOGLE_API_KEY` environment variabl
|
||||
<CodeGroup>
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["GOOGLE_API_KEY"] = "xxx"
|
||||
|
||||
@@ -233,7 +236,7 @@ To use Azure OpenAI model, you have to set some of the azure openai related envi
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["OPENAI_API_TYPE"] = "azure"
|
||||
os.environ["OPENAI_API_BASE"] = "https://xxx.openai.azure.com/"
|
||||
@@ -272,7 +275,7 @@ To use anthropic's model, please set the `ANTHROPIC_API_KEY` which you find on t
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["ANTHROPIC_API_KEY"] = "xxx"
|
||||
|
||||
@@ -309,7 +312,7 @@ Once you have the API key, you are all set to use it with Embedchain.
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["COHERE_API_KEY"] = "xxx"
|
||||
|
||||
@@ -329,6 +332,97 @@ llm:
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Together
|
||||
|
||||
Install related dependencies using the following command:
|
||||
|
||||
```bash
|
||||
pip install --upgrade 'embedchain[together]'
|
||||
```
|
||||
|
||||
Set the `TOGETHER_API_KEY` as environment variable which you can find on their [Account settings page](https://api.together.xyz/settings/api-keys).
|
||||
|
||||
Once you have the API key, you are all set to use it with Embedchain.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import App
|
||||
|
||||
os.environ["TOGETHER_API_KEY"] = "xxx"
|
||||
|
||||
# load llm configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
```
|
||||
|
||||
```yaml config.yaml
|
||||
llm:
|
||||
provider: together
|
||||
config:
|
||||
model: togethercomputer/RedPajama-INCITE-7B-Base
|
||||
temperature: 0.5
|
||||
max_tokens: 1000
|
||||
top_p: 1
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Ollama
|
||||
|
||||
Setup Ollama using https://github.com/jmorganca/ollama
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import App
|
||||
|
||||
# load llm configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
```
|
||||
|
||||
```yaml config.yaml
|
||||
llm:
|
||||
provider: ollama
|
||||
config:
|
||||
model: 'llama2'
|
||||
temperature: 0.5
|
||||
top_p: 1
|
||||
stream: true
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
|
||||
## vLLM
|
||||
|
||||
Setup vLLM by following instructions given in [their docs](https://docs.vllm.ai/en/latest/getting_started/installation.html).
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import App
|
||||
|
||||
# load llm configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
```
|
||||
|
||||
```yaml config.yaml
|
||||
llm:
|
||||
provider: vllm
|
||||
config:
|
||||
model: 'meta-llama/Llama-2-70b-hf'
|
||||
temperature: 0.5
|
||||
top_p: 1
|
||||
top_k: 10
|
||||
stream: true
|
||||
trust_remote_code: true
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## GPT4ALL
|
||||
|
||||
Install related dependencies using the following command:
|
||||
@@ -342,7 +436,7 @@ GPT4all is a free-to-use, locally running, privacy-aware chatbot. No GPU or inte
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load llm configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -374,7 +468,7 @@ Once you have the key, load the app using the config yaml file:
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["JINACHAT_API_KEY"] = "xxx"
|
||||
# load llm configuration from config.yaml file
|
||||
@@ -410,7 +504,7 @@ Once you have the token, load the app using the config yaml file:
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "xxx"
|
||||
|
||||
@@ -430,6 +524,49 @@ llm:
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Custom Endpoints
|
||||
|
||||
|
||||
You can also use [Hugging Face Inference Endpoints](https://huggingface.co/docs/inference-endpoints/index#-inference-endpoints) to access custom endpoints. First, set the `HUGGINGFACE_ACCESS_TOKEN` as above.
|
||||
|
||||
Then, load the app using the config yaml file:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import App
|
||||
|
||||
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "xxx"
|
||||
|
||||
# load llm configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
```
|
||||
|
||||
```yaml config.yaml
|
||||
llm:
|
||||
provider: huggingface
|
||||
config:
|
||||
endpoint: https://api-inference.huggingface.co/models/gpt2 # replace with your personal endpoint
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
If your endpoint requires additional parameters, you can pass them in the `model_kwargs` field:
|
||||
|
||||
```
|
||||
llm:
|
||||
provider: huggingface
|
||||
config:
|
||||
endpoint: <YOUR_ENDPOINT_URL_HERE>
|
||||
model_kwargs:
|
||||
max_new_tokens: 100
|
||||
temperature: 0.5
|
||||
```
|
||||
|
||||
Currently only supports `text-generation` and `text2text-generation` for now [[ref](https://api.python.langchain.com/en/latest/llms/langchain_community.llms.huggingface_endpoint.HuggingFaceEndpoint.html?highlight=huggingfaceendpoint#)].
|
||||
|
||||
See langchain's [hugging face endpoint](https://python.langchain.com/docs/integrations/chat/huggingface#huggingfaceendpoint) for more information.
|
||||
|
||||
## Llama2
|
||||
|
||||
Llama2 is integrated through [Replicate](https://replicate.com/). Set `REPLICATE_API_TOKEN` in environment variable which you can obtain from [their platform](https://replicate.com/account/api-tokens).
|
||||
@@ -440,7 +577,7 @@ Once you have the token, load the app using the config yaml file:
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["REPLICATE_API_TOKEN"] = "xxx"
|
||||
|
||||
@@ -467,7 +604,7 @@ Setup Google Cloud Platform application credentials by following the instruction
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load llm configuration from config.yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
|
||||
@@ -22,7 +22,7 @@ Utilizing a vector database alongside Embedchain is a seamless process. All you
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load chroma configuration from yaml file
|
||||
app = App.from_config(config_path="config1.yaml")
|
||||
@@ -67,7 +67,7 @@ You can authorize the connection to Elasticsearch by providing either `basic_aut
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load elasticsearch configuration from yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -97,7 +97,7 @@ pip install --upgrade 'embedchain[opensearch]'
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load opensearch configuration from yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -133,7 +133,7 @@ Set the Zilliz environment variables `ZILLIZ_CLOUD_URI` and `ZILLIZ_CLOUD_TOKEN`
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['ZILLIZ_CLOUD_URI'] = 'https://xxx.zillizcloud.com'
|
||||
os.environ['ZILLIZ_CLOUD_TOKEN'] = 'xxx'
|
||||
@@ -172,7 +172,7 @@ In order to use Pinecone as vector database, set the environment variables `PINE
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load pinecone configuration from yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -195,7 +195,7 @@ In order to use Qdrant as a vector database, set the environment variables `QDRA
|
||||
|
||||
<CodeGroup>
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load qdrant configuration from yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
@@ -215,7 +215,7 @@ In order to use Weaviate as a vector database, set the environment variables `WE
|
||||
|
||||
<CodeGroup>
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load weaviate configuration from yaml file
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
|
||||
@@ -27,7 +27,7 @@ make lint format
|
||||
### Authors
|
||||
|
||||
- Taranjeet Singh ([@taranjeetio](https://twitter.com/taranjeetio))
|
||||
- Deshraj Yadav ([@deshrajdry](https://twitter.com/taranjeetio))
|
||||
- Deshraj Yadav ([@deshrajdry](https://twitter.com/deshrajdry))
|
||||
|
||||
### Citation
|
||||
|
||||
@@ -36,7 +36,7 @@ If you utilize this repository, please consider citing it with:
|
||||
```
|
||||
@misc{embedchain,
|
||||
author = {Taranjeet Singh, Deshraj Yadav},
|
||||
title = {Embechain: Data platform for LLMs - Load, index, retrieve and sync any unstructured data},
|
||||
title = {Embechain: The Open Source RAG Framework},
|
||||
year = {2023},
|
||||
publisher = {GitHub},
|
||||
journal = {GitHub repository},
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
title: 'Embedchain.ai'
|
||||
description: 'Deploy your RAG application to embedchain.ai platform'
|
||||
---
|
||||
|
||||
## Deploy on Embedchain 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):
|
||||
|
||||
```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?
|
||||
|
||||
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" />
|
||||
@@ -0,0 +1,59 @@
|
||||
---
|
||||
title: 'Gradio.app'
|
||||
description: 'Deploy your RAG application to gradio.app platform'
|
||||
---
|
||||
|
||||
Embedchain offers a Streamlit template to facilitate the development of RAG chatbot applications in just three easy steps.
|
||||
|
||||
Follow the instructions given below to deploy your first application quickly:
|
||||
|
||||
## Step-1: Create RAG app
|
||||
|
||||
We provide a command line utility called `ec` in embedchain that inherits the template for `gradio.app` platform and help you deploy the app. Follow the instructions to create a gradio.app app using the template provided:
|
||||
|
||||
```bash Install embedchain
|
||||
pip install embedchain
|
||||
```
|
||||
|
||||
```bash Create application
|
||||
mkdir my-rag-app
|
||||
ec create --template=gradio.app
|
||||
```
|
||||
|
||||
This will generate a directory structure like this:
|
||||
|
||||
```bash
|
||||
├── app.py
|
||||
├── embedchain.json
|
||||
└── requirements.txt
|
||||
```
|
||||
|
||||
Feel free to edit the files as required.
|
||||
- `app.py`: Contains API app code
|
||||
- `embedchain.json`: Contains embedchain specific configuration for deployment (you don't need to configure this)
|
||||
- `requirements.txt`: Contains python dependencies for your application
|
||||
|
||||
## Step-2: Test app locally
|
||||
|
||||
You can run the app locally by simply doing:
|
||||
|
||||
```bash Run locally
|
||||
pip install -r requirements.txt
|
||||
ec dev
|
||||
```
|
||||
|
||||
## Step-3: Deploy to gradio.app
|
||||
|
||||
```bash Deploy to gradio.app
|
||||
ec deploy
|
||||
```
|
||||
|
||||
This will run `gradio deploy` which will prompt you questions and deploy your app directly to huggingface spaces.
|
||||
|
||||
<img src="/images/gradio_app.png" alt="gradio app" />
|
||||
|
||||
## 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" />
|
||||
@@ -0,0 +1,103 @@
|
||||
---
|
||||
title: 'Huggingface.co'
|
||||
description: 'Deploy your RAG application to huggingface.co platform'
|
||||
---
|
||||
|
||||
With Embedchain, you can directly host your apps in just three steps to huggingface spaces where you can view and deploy your app to the world.
|
||||
|
||||
We support two types of deployment to huggingface spaces:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="" href="#using-streamlit-io">
|
||||
Streamlit.io
|
||||
</Card>
|
||||
<Card title="" href="#using-gradio-app">
|
||||
Gradio.app
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Using streamlit.io
|
||||
|
||||
### Step 1: Create a new RAG app
|
||||
|
||||
Create a new RAG app using the following command:
|
||||
|
||||
```bash
|
||||
mkdir my-rag-app
|
||||
ec create --template=hf/streamlit.io # inside my-rag-app directory
|
||||
```
|
||||
|
||||
When you run this for the first time, you'll be asked to login to huggingface.co. Once you login, you'll need to create a **write** token. You can create a write token by going to [huggingface.co settings](https://huggingface.co/settings/token). Once you create a token, you'll be asked to enter the token in the terminal.
|
||||
|
||||
This will also create an `embedchain.json` file in your app directory. Add a `name` key into the `embedchain.json` file. This will be the "repo-name" of your app in huggingface spaces.
|
||||
|
||||
```json embedchain.json
|
||||
{
|
||||
"name": "my-rag-app",
|
||||
"provider": "hf/streamlit.io"
|
||||
}
|
||||
```
|
||||
|
||||
### Step-2: Test app locally
|
||||
|
||||
You can run the app locally by simply doing:
|
||||
|
||||
```bash Run locally
|
||||
pip install -r requirements.txt
|
||||
ec dev
|
||||
```
|
||||
|
||||
### Step-3: Deploy to huggingface spaces
|
||||
|
||||
```bash Deploy to huggingface spaces
|
||||
ec deploy
|
||||
```
|
||||
|
||||
This will deploy your app to huggingface spaces. You can view your app at `https://huggingface.co/spaces/<your-username>/my-rag-app`. This will get prompted in the terminal once the app is deployed.
|
||||
|
||||
## Using gradio.app
|
||||
|
||||
Similar to streamlit.io, you can deploy your app to gradio.app in just three steps.
|
||||
|
||||
### Step 1: Create a new RAG app
|
||||
|
||||
Create a new RAG app using the following command:
|
||||
|
||||
```bash
|
||||
mkdir my-rag-app
|
||||
ec create --template=hf/gradio.app # inside my-rag-app directory
|
||||
```
|
||||
|
||||
When you run this for the first time, you'll be asked to login to huggingface.co. Once you login, you'll need to create a **write** token. You can create a write token by going to [huggingface.co settings](https://huggingface.co/settings/token). Once you create a token, you'll be asked to enter the token in the terminal.
|
||||
|
||||
This will also create an `embedchain.json` file in your app directory. Add a `name` key into the `embedchain.json` file. This will be the "repo-name" of your app in huggingface spaces.
|
||||
|
||||
```json embedchain.json
|
||||
{
|
||||
"name": "my-rag-app",
|
||||
"provider": "hf/gradio.app"
|
||||
}
|
||||
```
|
||||
|
||||
### Step-2: Test app locally
|
||||
|
||||
You can run the app locally by simply doing:
|
||||
|
||||
```bash Run locally
|
||||
pip install -r requirements.txt
|
||||
ec dev
|
||||
```
|
||||
|
||||
### Step-3: Deploy to huggingface spaces
|
||||
|
||||
```bash Deploy to huggingface spaces
|
||||
ec deploy
|
||||
```
|
||||
|
||||
This will deploy your app to huggingface spaces. You can view your app at `https://huggingface.co/spaces/<your-username>/my-rag-app`. This will get prompted in the terminal once the app is deployed.
|
||||
|
||||
## 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" />
|
||||
@@ -0,0 +1,32 @@
|
||||
### Embedchain Chat with PDF App
|
||||
|
||||
You can easily create and deploy your own `chat-pdf` App using Embedchain.
|
||||
|
||||
Here are few simple steps for you to create and deploy your app:
|
||||
|
||||
1. Fork the embedchain repo from [Github](https://github.com/embedchain/embedchain).
|
||||
|
||||
<Note>
|
||||
If you run into problems with forking, please refer to [github docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) for forking a repo.
|
||||
</Note>
|
||||
|
||||
2. Navigate to `chat-pdf` example app from your forked repo:
|
||||
|
||||
```bash
|
||||
cd <your_fork_repo>/examples/chat-pdf
|
||||
```
|
||||
|
||||
3. Run your app in development environment with simple commands
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
ec dev
|
||||
```
|
||||
|
||||
Feel free to improve our simple `chat-pdf` streamlit app and create pull request to showcase your app [here](https://docs.embedchain.ai/examples/showcase)
|
||||
|
||||
4. You can easily deploy your app using Streamlit interface
|
||||
|
||||
Connect your Github account with Streamlit and refer this [guide](https://docs.streamlit.io/streamlit-community-cloud/deploy-your-app) to deploy your app.
|
||||
|
||||
You can also use the deploy button from your streamlit website you see when running `ec dev` command.
|
||||
@@ -0,0 +1,124 @@
|
||||
Fork the Embedchain repo on [Github](https://github.com/embedchain/embedchain) to create your own NextJS discord and slack bot powered by Embedchain.
|
||||
|
||||
If you run into problems with forking, please refer to [github docs](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) for forking a repo.
|
||||
|
||||
We will work from the `examples/nextjs` folder so change your current working directory by running the command - `cd <your_forked_repo>/examples/nextjs`
|
||||
|
||||
# Installation
|
||||
|
||||
First, lets start by install all the required packages and dependencies.
|
||||
|
||||
- Install all the required python packages by running ```pip install -r requirements.txt```
|
||||
|
||||
- We will use [Fly.io](https://fly.io/) to deploy our embedchain app, discord and slack bot. Follow the step one to install [Fly.io CLI](https://docs.embedchain.ai/deployment/fly_io#step-1-install-flyctl-command-line)
|
||||
|
||||
# Developement
|
||||
|
||||
## Embedchain App
|
||||
|
||||
First, we need an Embedchain app powered with the knowledge of NextJS. We have already created an embedchain app using FastAPI in `ec_app` folder for you. Feel free to ingest data of your choice to power the App.
|
||||
|
||||
<Note>
|
||||
Navigate to `ec_app` folder and create `.env` file in this folder and set your OpenAI API key as shown in `.env.example` file. If you want to use other open-source models, feel free to use the app config in `app.py`. More details for using custom configuration for Embedchain app is [available here](https://docs.embedchain.ai/api-reference/advanced/configuration).
|
||||
</Note>
|
||||
|
||||
Before running the ec commands to develope the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names.
|
||||
|
||||
Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io:
|
||||
```bash
|
||||
fly launch --no-deploy
|
||||
```
|
||||
|
||||
To run the app in development, run the following command:
|
||||
|
||||
```bash
|
||||
ec dev
|
||||
```
|
||||
|
||||
Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, save the endpoint on which our discord and slack bot will send requests.
|
||||
|
||||
|
||||
## Discord bot
|
||||
|
||||
For discord bot, you will need to create the bot on discord developer portal and get the discord bot token and your discord bot name.
|
||||
|
||||
While keeping in mind the following note, create the discord bot by following the instructions from our [discord bot docs](https://docs.embedchain.ai/examples/discord_bot) and get discord bot token.
|
||||
|
||||
<Note>
|
||||
You do not need to set `OPENAI_API_KEY` to run this discord bot. Follow the remaining instructions to create a discord bot app. We recommend you to give the following sets of bot permissions to run the discord bot without errors:
|
||||
|
||||
```
|
||||
(General Permissions)
|
||||
Read Message/View Channels
|
||||
|
||||
(Text Permissions)
|
||||
Send Messages
|
||||
Create Public Thread
|
||||
Create Private Thread
|
||||
Send Messages in Thread
|
||||
Manage Threads
|
||||
Embed Links
|
||||
Read Message History
|
||||
```
|
||||
</Note>
|
||||
|
||||
Once you have your discord bot token and discord app name. Navigate to `nextjs_discord` folder and create `.env` file and define your discord bot token, discord bot name and endpoint of your embedchain app as shown in `.env.example` file.
|
||||
|
||||
To run the app in development:
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
Before deploying the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names.
|
||||
|
||||
Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io:
|
||||
```bash
|
||||
fly launch --no-deploy
|
||||
```
|
||||
|
||||
Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, your discord bot will be live!
|
||||
|
||||
|
||||
## Slack bot
|
||||
|
||||
For Slack bot, you will need to create the bot on slack developer portal and get the slack bot token and slack app token.
|
||||
|
||||
### Setup
|
||||
|
||||
- Create a workspace on Slack if you don't have one already by clicking [here](https://slack.com/intl/en-in/).
|
||||
- Create a new App on your Slack account by going [here](https://api.slack.com/apps).
|
||||
- Select `From Scratch`, then enter the Bot Name and select your workspace.
|
||||
- Go to `App Credentials` section on the `Basic Information` tab from the left sidebar, create your app token and save it in your `.env` file as `SLACK_APP_TOKEN`.
|
||||
- Go to `Socket Mode` tab from the left sidebar and enable the socket mode to listen to slack message from your workspace.
|
||||
- (Optional) Under the `App Home` tab you can change your App display name and default name.
|
||||
- Navigate to `Event Subscription` tab, and enable the event subscription so that we can listen to slack events.
|
||||
- Once you enable the event subscription, you will need to subscribe to bot events to authorize the bot to listen to app mention events of the bot. Do that by tapping on `Add Bot User Event` button and select `app_mention`.
|
||||
- On the left Sidebar, go to `OAuth and Permissions` and add the following scopes under `Bot Token Scopes`:
|
||||
```text
|
||||
app_mentions:read
|
||||
channels:history
|
||||
channels:read
|
||||
chat:write
|
||||
emoji:read
|
||||
reactions:write
|
||||
reactions:read
|
||||
```
|
||||
- Now select the option `Install to Workspace` and after it's done, copy the `Bot User OAuth Token` and set it in your `.env` file as `SLACK_BOT_TOKEN`.
|
||||
|
||||
Once you have your slack bot token and slack app token. Navigate to `nextjs_slack` folder and create `.env` file and define your slack bot token, slack app token and endpoint of your embedchain app as shown in `.env.example` file.
|
||||
|
||||
To run the app in development:
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
Before deploying the app, open `fly.toml` file and update the `name` variable to something unique. This is important as `fly.io` requires users to provide a globally unique deployment app names.
|
||||
|
||||
Now, we need to launch this application with fly.io. You can see your app on [fly.io dashboard](https://fly.io/dashboard). Run the following command to launch your app on fly.io:
|
||||
```bash
|
||||
fly launch --no-deploy
|
||||
```
|
||||
|
||||
Run `ec deploy` to deploy your app on Fly.io. Once you deploy your app, your slack bot will be live!
|
||||
@@ -44,6 +44,14 @@ Get started with Embedchain by trying out the examples below. You can run the ex
|
||||
<td className="align-middle"><a target="_blank" href="https://colab.research.google.com/github/embedchain/embedchain/blob/main/notebooks/cohere.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" noZoom alt="Open In Colab"/></a></td>
|
||||
<td className="align-middle"><a target="_blank" href="https://replit.com/@taranjeetio/cohere#main.py"><img src="https://replit.com/badge?caption=Try%20with%20Replit&variant=small" noZoom alt="Try with Replit Badge"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="align-middle">Together</td>
|
||||
<td className="align-middle"><a target="_blank" href="https://colab.research.google.com/github/embedchain/embedchain/blob/main/notebooks/together.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" noZoom alt="Open In Colab"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="align-middle">Ollama</td>
|
||||
<td className="align-middle"><a target="_blank" href="https://colab.research.google.com/github/embedchain/embedchain/blob/main/notebooks/ollama.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" noZoom alt="Open In Colab"/></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="align-middle">Hugging Face</td>
|
||||
<td className="align-middle"><a target="_blank" href="https://colab.research.google.com/github/embedchain/embedchain/blob/main/notebooks/hugging_face_hub.ipynb"><img src="https://colab.research.google.com/assets/colab-badge.svg" noZoom alt="Open In Colab"/></a></td>
|
||||
|
||||
@@ -37,7 +37,7 @@ llm:
|
||||
max_tokens: 1000
|
||||
top_p: 1
|
||||
stream: false
|
||||
template: |
|
||||
prompt: |
|
||||
Use the following pieces of context to answer the query at the end.
|
||||
If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||
|
||||
@@ -81,6 +81,7 @@ curl --request POST \
|
||||
| `OPENAI_API_BASE` | Azure OpenAI |
|
||||
| `OPENAI_API_VERSION` | Azure OpenAI |
|
||||
| `COHERE_API_KEY` | Cohere |
|
||||
| `TOGETHER_API_KEY` | Together |
|
||||
| `ANTHROPIC_API_KEY` | Anthropic |
|
||||
| `JINACHAT_API_KEY` | Jina |
|
||||
| `HUGGINGFACE_ACCESS_TOKEN` | Huggingface |
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
[Embedchain Examples Repo](https://github.com/embedchain/examples) contains code on how to build your own Slack AI to chat with the unstructured data lying in your slack channels.
|
||||
|
||||

|
||||
|
||||
## Getting started
|
||||
|
||||
Create a Slack AI involves 3 steps
|
||||
|
||||
* Create slack user
|
||||
* Set environment variables
|
||||
* Run the app locally
|
||||
|
||||
### Step 1: Create Slack user token
|
||||
|
||||
Follow the steps given below to fetch your slack user token to get data through Slack APIs:
|
||||
|
||||
1. Create a workspace on Slack if you don’t have one already by clicking [here](https://slack.com/intl/en-in/).
|
||||
2. Create a new App on your Slack account by going [here](https://api.slack.com/apps).
|
||||
3. Select `From Scratch`, then enter the App Name and select your workspace.
|
||||
4. Navigate to `OAuth & Permissions` tab from the left sidebar and go to the `scopes` section. Add the following scopes under `User Token Scopes`:
|
||||
|
||||
```
|
||||
# Following scopes are needed for reading channel history
|
||||
channels:history
|
||||
channels:read
|
||||
|
||||
# Following scopes are needed to fetch list of channels from slack
|
||||
groups:read
|
||||
mpim:read
|
||||
im:read
|
||||
```
|
||||
|
||||
5. Click on the `Install to Workspace` button under `OAuth Tokens for Your Workspace` section in the same page and install the app in your slack workspace.
|
||||
6. After installing the app you will see the `User OAuth Token`, save that token as you will need to configure it as `SLACK_USER_TOKEN` for this demo.
|
||||
|
||||
### Step 2: Set environment variables
|
||||
|
||||
Navigate to `api` folder and set your `HUGGINGFACE_ACCESS_TOKEN` and `SLACK_USER_TOKEN` in `.env.example` file. Then rename the `.env.example` file to `.env`.
|
||||
|
||||
|
||||
<Note>
|
||||
By default, we use `Mixtral` model from Hugging Face. However, if you prefer to use OpenAI model, then set `OPENAI_API_KEY` instead of `HUGGINGFACE_ACCESS_TOKEN` along with `SLACK_USER_TOKEN` in `.env` file, and update the code in `api/utils/app.py` file to use OpenAI model instead of Hugging Face model.
|
||||
</Note>
|
||||
|
||||
### Step 3: Run app locally
|
||||
|
||||
Follow the instructions given below to run app locally based on your development setup (with docker or without docker):
|
||||
|
||||
#### With docker
|
||||
|
||||
```bash
|
||||
docker-compose build
|
||||
ec start --docker
|
||||
```
|
||||
|
||||
#### Without docker
|
||||
|
||||
```bash
|
||||
ec install-reqs
|
||||
ec start
|
||||
```
|
||||
|
||||
Finally, you will have the Slack AI frontend running on http://localhost:3000. You can also access the REST APIs on http://localhost:8000.
|
||||
|
||||
## Credits
|
||||
|
||||
This demo was built using the Embedchain's [full stack demo template](https://docs.embedchain.ai/get-started/full-stack). Follow the instructions [given here](https://docs.embedchain.ai/get-started/full-stack) to create your own full stack RAG application.
|
||||
@@ -10,51 +10,11 @@ After successfully setting up and testing your RAG app locally, the next step is
|
||||
<Card title="Modal.com" href="/deployment/modal_com"></Card>
|
||||
<Card title="Render.com" href="/deployment/render_com"></Card>
|
||||
<Card title="Streamlit.io" href="/deployment/streamlit_io"></Card>
|
||||
<Card title="Embedchain Platform" href="#option-1-deploy-on-embedchain-platform"></Card>
|
||||
<Card title="Self-hosting" href="#option-2-self-hosting"></Card>
|
||||
<Card title="Gradio.app" href="/deployment/gradio_app"></Card>
|
||||
<Card title="Huggingface.co" href="/deployment/huggingface_spaces"></Card>
|
||||
<Card title="Embedchain.ai" href="/deployment/embedchain_ai"></Card>
|
||||
</CardGroup>
|
||||
|
||||
## Deploy on Embedchain 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):
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as 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.
|
||||
```
|
||||
|
||||
## Self-hosting
|
||||
|
||||
You can also deploy Embedchain as a self-hosted service using the dockerized REST API service that we provide. Please follow the [guide here](/examples/rest-api) on how to use the REST API service. Here are some tutorials on how to deploy a containerized application to different platforms like AWS, GCP, Azure etc:
|
||||
|
||||
- [Fly.io](/deployment/fly_io)
|
||||
- [Render.com](https://render.com/docs/deploy-an-image)
|
||||
- [Huggingface Spaces](https://huggingface.co/new-space)
|
||||
- [AWS EKS](https://docs.aws.amazon.com/eks/latest/userguide/sample-deployment.html)
|
||||
- [AWS ECS](https://docs.aws.amazon.com/codecatalyst/latest/userguide/deploy-tut-ecs.html)
|
||||
- [Google GKE](https://cloud.google.com/kubernetes-engine/docs/tutorials/hello-app)
|
||||
- [Azure App Service](https://learn.microsoft.com/en-us/training/modules/deploy-run-container-app-service/)
|
||||
|
||||
|
||||
## Seeking help?
|
||||
|
||||
If you run into issues with deployment, please feel free to reach out to us via any of the following methods:
|
||||
|
||||
@@ -11,7 +11,7 @@ Use the model provided on huggingface: `mistralai/Mistral-7B-v0.1`
|
||||
<CodeGroup>
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "hf_your_token"
|
||||
|
||||
@@ -40,7 +40,7 @@ Use the model `gpt-4-turbo` provided my openai.
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||
|
||||
@@ -65,7 +65,7 @@ llm:
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||
|
||||
@@ -90,7 +90,7 @@ llm:
|
||||
<CodeGroup>
|
||||
|
||||
```python main.py
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
# load llm configuration from opensource.yaml file
|
||||
app = App.from_config(config_path="opensource.yaml")
|
||||
@@ -131,7 +131,7 @@ llm:
|
||||
|
||||
```python main.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
@@ -149,7 +149,7 @@ response = app.query("What is the net worth of Elon Musk?")
|
||||
Set up the app by adding an `id` in the config file. This keeps the data for future use. You can include this `id` in the yaml config or input it directly in `config` dict.
|
||||
```python app1.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
@@ -167,7 +167,7 @@ response = app.query("What is the net worth of Elon Musk?")
|
||||
```
|
||||
```python app2.py
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: '💻 Full stack'
|
||||
---
|
||||
|
||||
Get started with full-stack RAG applications using Embedchain's easy-to-use CLI tool. Set up everything with just a few commands, whether you prefer Docker or not.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Choose your setup method:
|
||||
|
||||
### Without Docker
|
||||
|
||||
Ensure these are installed:
|
||||
|
||||
- Embedchain python package (`pip install embedchain`)
|
||||
- [Node.js](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) and [Yarn](https://classic.yarnpkg.com/lang/en/docs/install/)
|
||||
|
||||
### With Docker
|
||||
|
||||
Install Docker from [Docker's official website](https://docs.docker.com/engine/install/).
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
### 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.
|
||||
|
||||
### Installation Commands
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash without docker
|
||||
ec create-app my-app
|
||||
cd my-app
|
||||
ec start
|
||||
```
|
||||
|
||||
```bash with docker
|
||||
ec create-app my-app --docker
|
||||
cd my-app
|
||||
ec start --docker
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### What Happens Next?
|
||||
|
||||
1. Embedchain fetches a full stack template (FastAPI backend, Next.JS frontend).
|
||||
2. Installs required components.
|
||||
3. Launches both frontend and backend servers.
|
||||
|
||||
### See It In Action
|
||||
|
||||
Open http://localhost:3000 to view the chat UI.
|
||||
|
||||

|
||||
|
||||
### Admin Panel
|
||||
|
||||
Check out the Embedchain admin panel to see the document chunks for your RAG application.
|
||||
|
||||

|
||||
@@ -1,85 +1,83 @@
|
||||
---
|
||||
title: '⚡ Quickstart'
|
||||
description: '💡 Start building ChatGPT like apps in a minute on your own data'
|
||||
description: '💡 Create a RAG app on your own data in a minute'
|
||||
---
|
||||
|
||||
Install python package:
|
||||
## Installation
|
||||
|
||||
First install the Python package:
|
||||
|
||||
```bash
|
||||
pip install embedchain
|
||||
```
|
||||
|
||||
Creating an app involves 3 steps:
|
||||
Once you have installed the package, depending upon your preference you can either use:
|
||||
|
||||
<Steps>
|
||||
<Step title="⚙️ Import app instance">
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
app = App()
|
||||
```
|
||||
<Accordion title="Customize your app by a simple YAML config" icon="gear-complex">
|
||||
Embedchain provides a wide range of options to customize your app. You can customize the model, data sources, and much more.
|
||||
Explore the custom configurations [here](https://docs.embedchain.ai/advanced/configuration).
|
||||
<CodeGroup>
|
||||
```python yaml_app.py
|
||||
from embedchain import Pipeline as App
|
||||
app = App.from_config(config_path="config.yaml")
|
||||
```
|
||||
```python json_app.py
|
||||
from embedchain import Pipeline as App
|
||||
app = App.from_config(config_path="config.json")
|
||||
```
|
||||
```python app.py
|
||||
from embedchain import Pipeline as App
|
||||
config = {} # Add your config here
|
||||
app = App.from_config(config=config)
|
||||
```
|
||||
</CodeGroup>
|
||||
</Accordion>
|
||||
</Step>
|
||||
<Step title="🗃️ Add data sources">
|
||||
```python
|
||||
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
# app.add("path/to/file/elon_musk.pdf")
|
||||
```
|
||||
<Accordion title="Embedchain supports adding data from many data sources." icon="files">
|
||||
Embedchain supports adding data from many data sources including web pages, PDFs, databases, and more.
|
||||
Explore the list of supported [data sources](https://docs.embedchain.ai/data-sources/overview).
|
||||
</Accordion>
|
||||
</Step>
|
||||
<Step title="💬 Ask questions, chat, or search through your data with ease">
|
||||
```python
|
||||
app.query("What is the net worth of Elon Musk today?")
|
||||
# Answer: The net worth of Elon Musk today is $258.7 billion.
|
||||
```
|
||||
<hr />
|
||||
<Accordion title="Want to chat with your app?" icon="face-thinking">
|
||||
Embedchain provides a wide range of features to interact with your app. You can chat with your app, ask questions, search through your data, and much more.
|
||||
```python
|
||||
app.chat("How many companies does Elon Musk run? Name those")
|
||||
# Answer: Elon Musk runs 3 companies: Tesla, SpaceX, and Neuralink.
|
||||
app.chat("What is his net worth today?")
|
||||
# Answer: The net worth of Elon Musk today is $258.7 billion.
|
||||
```
|
||||
To learn about other features, click [here](https://docs.embedchain.ai/get-started/introduction)
|
||||
</Accordion>
|
||||
</Step>
|
||||
<Step title="🚀 Seamlessly launch your App on the Embedchain Platform!">
|
||||
```python
|
||||
app.deploy()
|
||||
# 🔑 Enter your Embedchain API key. You can find the API key at https://app.embedchain.ai/settings/keys/
|
||||
# ec-xxxxxx
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Open Source Models" icon="osi" href="#open-source-models">
|
||||
This includes Open source LLMs like Mistral, Llama, etc.<br/>
|
||||
Free to use, and runs locally on your machine.
|
||||
</Card>
|
||||
<Card title="Paid Models" icon="dollar-sign" href="#paid-models" color="#4A154B">
|
||||
This includes paid LLMs like GPT 4, Claude, etc.<br/>
|
||||
Cost money and are accessible via an API.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
# 🛠️ Creating pipeline on the platform...
|
||||
# 🎉🎉🎉 Pipeline created successfully! View your pipeline: https://app.embedchain.ai/pipelines/xxxxx
|
||||
## Open Source Models
|
||||
|
||||
# 🛠️ Adding data to your pipeline...
|
||||
# ✅ Data of type: web_page, value: https://www.forbes.com/profile/elon-musk added successfully.
|
||||
```
|
||||
<Accordion title="Share your app with others" icon="laptop-mobile">
|
||||
You can now share your app with others from our platform.
|
||||
Access your app on our [platform](https://app.embedchain.ai/).
|
||||
</Accordion>
|
||||
</Step>
|
||||
</Steps>
|
||||
This section gives a quickstart example of using Mistral as the Open source LLM and Sentence transformers as the Open source embedding model. These models are free and run mostly on your local machine.
|
||||
|
||||
We are using Mistral hosted at Hugging Face, so will you need a Hugging Face token to run this example. Its *free* and you can create one [here](https://huggingface.co/docs/hub/security-tokens).
|
||||
|
||||
<CodeGroup>
|
||||
```python quickstart.py
|
||||
import os
|
||||
# replace this with your HF key
|
||||
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "hf_xxxx"
|
||||
|
||||
from embedchain import App
|
||||
app = App.from_config("mistral.yaml")
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
app.query("What is the net worth of Elon Musk today?")
|
||||
# Answer: The net worth of Elon Musk today is $258.7 billion.
|
||||
```
|
||||
```yaml mistral.yaml
|
||||
llm:
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'mistralai/Mistral-7B-v0.1'
|
||||
top_p: 0.5
|
||||
embedder:
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'sentence-transformers/all-mpnet-base-v2'
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Paid Models
|
||||
|
||||
In this section, we will use both LLM and embedding model from OpenAI.
|
||||
|
||||
```python quickstart.py
|
||||
import os
|
||||
# replace this with your OpenAI key
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxxx"
|
||||
|
||||
from embedchain import App
|
||||
app = App()
|
||||
app.add("https://www.forbes.com/profile/elon-musk")
|
||||
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
app.query("What is the net worth of Elon Musk today?")
|
||||
# Answer: The net worth of Elon Musk today is $258.7 billion.
|
||||
```
|
||||
|
||||
# Next Steps
|
||||
|
||||
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)
|
||||
|
After Width: | Height: | Size: 758 KiB |
|
After Width: | Height: | Size: 605 KiB |
|
After Width: | Height: | Size: 354 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
@@ -21,7 +21,7 @@ Create a new file called `app.py` and add the following code:
|
||||
|
||||
```python
|
||||
import chainlit as cl
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
import os
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ os.environ['LANGCHAIN_PROJECT] = <your-project>
|
||||
|
||||
|
||||
```python
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
|
||||
app = App()
|
||||
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
|
||||
@@ -17,7 +17,7 @@ pip install embedchain streamlit
|
||||
<Tab title="app.py">
|
||||
```python
|
||||
import os
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
import streamlit as st
|
||||
|
||||
with st.sidebar:
|
||||
@@ -85,22 +85,22 @@ pip install embedchain streamlit
|
||||
<Tab title="config.yaml">
|
||||
```yaml
|
||||
app:
|
||||
config:
|
||||
name: 'mistral-streamlit-app'
|
||||
config:
|
||||
name: 'mistral-streamlit-app'
|
||||
|
||||
llm:
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'mistralai/Mixtral-8x7B-Instruct-v0.1'
|
||||
temperature: 0.1
|
||||
max_tokens: 250
|
||||
top_p: 0.1
|
||||
stream: true
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'mistralai/Mixtral-8x7B-Instruct-v0.1'
|
||||
temperature: 0.1
|
||||
max_tokens: 250
|
||||
top_p: 0.1
|
||||
stream: true
|
||||
|
||||
embedder:
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'sentence-transformers/all-mpnet-base-v2'
|
||||
provider: huggingface
|
||||
config:
|
||||
model: 'sentence-transformers/all-mpnet-base-v2'
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<svg width="1371" height="249" viewBox="0 0 1371 249" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M66.248 1V248.8H158.996V210.214H120.41V148.264H158.996V101.89H120.41V39.94H158.996V1H66.248ZM169.655 1V248.8H223.817V124.9L246.827 248.8H262.403L285.767 124.9V248.8H339.929V1H277.979L254.615 148.264L231.251 1H169.655ZM404.661 210.214V148.264H412.449C416.697 148.264 419.883 151.804 419.883 156.052V202.426C419.883 206.674 416.697 210.214 412.449 210.214H404.661ZM443.955 125.254L443.247 124.9C460.239 124.9 474.399 111.094 474.399 94.102V32.152C474.399 15.16 460.239 1 443.247 1H350.499V248.8H443.247C460.239 248.8 474.399 234.994 474.399 218.002V156.052C474.399 139.06 460.947 125.608 443.955 125.254ZM412.449 101.89H404.661V39.94H412.449C416.697 39.94 419.883 43.48 419.883 47.728V94.102C419.883 98.35 416.697 101.89 412.449 101.89ZM577.421 1H484.673V248.8H577.421V210.214H538.835V148.264H577.421V101.89H538.835V39.94H577.421V1ZM642.242 210.214V39.94H649.676C654.278 39.94 657.464 43.48 657.464 47.728V202.426C657.464 206.674 654.278 210.214 649.676 210.214H642.242ZM711.98 218.002V32.152C711.98 15.16 697.82 1 680.828 1H588.08V248.8H680.828C697.82 248.8 711.98 234.994 711.98 218.002ZM88 164.8H70V182.8H88V164.8Z" fill="white"/>
|
||||
<rect x="17" y="164.8" width="18" height="18" fill="white"/>
|
||||
<rect y="141.8" width="11" height="18" fill="white"/>
|
||||
<rect x="26" y="64.7998" width="30" height="30" fill="white"/>
|
||||
<rect x="1334.52" y="90.3779" width="26.6955" height="26.6955" fill="white"/>
|
||||
<rect x="1360.32" y="133.091" width="10.6782" height="16.0173" fill="white"/>
|
||||
<rect x="1334.52" y="148.219" width="16.0173" height="16.0173" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M723 217.646V31.2444C723 14.202 736.847 0 753.889 0H816.023C833.066 0 847.268 14.202 847.268 31.2444V85.5672H792.59V46.8667C792.59 42.6061 789.394 39.0556 784.779 39.0556C780.518 39.0556 777.323 42.6061 777.323 46.8667V202.024C777.323 206.284 780.518 209.835 784.779 209.835C789.394 209.835 792.59 206.284 792.59 202.024V163.323H847.268V217.646C847.268 234.688 833.066 248.535 816.023 248.535H753.889C736.847 248.535 723 234.688 723 217.646ZM856.144 248.535V0H910.467V101.189H925.734V0H980.057V248.535H925.734V147.701H910.467V248.535H856.144ZM1066.34 248.535L1062.79 209.835H1039.36L1035.45 248.535H988.941L1019.83 0H1081.96L1113.21 248.535H1066.34ZM1043.62 163.323H1058.18L1050.72 85.5672L1043.62 163.323ZM1176.06 248.535H1121.74V0H1176.06V248.535ZM1184.84 248.535V0H1239.17L1262.24 124.268V0H1308.76V75.2506H1302.48V101.946H1308.76V153.557H1294.47V169.575H1308.76V248.535H1254.43L1231.35 124.268V248.535H1184.84Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -1,24 +1,11 @@
|
||||
<svg width="1161" height="212" viewBox="0 0 1161 212" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1010.3 212V0H1056.64L1076.33 106V0H1116V212H1069.66L1049.98 106V212H1010.3Z" fill="white"/>
|
||||
<path d="M1001.3 212H954.958V0H1001.3V212Z" fill="white"/>
|
||||
<path d="M906.196 212L903.167 178.989H883.179L879.847 212H840.173L866.522 0H919.522L946.173 212H906.196ZM886.813 139.314H899.23L892.87 72.9886L886.813 139.314Z" fill="white"/>
|
||||
<path d="M725.385 212V0H771.722V86.3143H784.745V0H831.082V212H784.745V125.989H771.722V212H725.385Z" fill="white"/>
|
||||
<path d="M610.298 185.651V26.6514C610.298 12.1143 622.109 0 636.646 0H689.646C704.183 0 716.298 12.1143 716.298 26.6514V72.9886H669.658V39.9771C669.658 36.3429 666.932 33.3143 662.995 33.3143C659.36 33.3143 656.635 36.3429 656.635 39.9771V172.326C656.635 175.96 659.36 178.989 662.995 178.989C666.932 178.989 669.658 175.96 669.658 172.326V139.314H716.298V185.651C716.298 200.189 704.183 212 689.646 212H636.646C622.109 212 610.298 200.189 610.298 185.651Z" fill="white"/>
|
||||
<path d="M541.841 33.3143V178.989H548.201C552.138 178.989 554.864 175.96 554.864 172.326V39.9771C554.864 36.3429 552.138 33.3143 548.201 33.3143H541.841ZM601.504 26.6514V185.651C601.504 200.189 589.389 212 574.852 212H495.504V0H574.852C589.389 0 601.504 12.1143 601.504 26.6514Z" fill="white"/>
|
||||
<path d="M407.037 212V0H486.385V33.3143H453.374V86.3143H486.385V125.989H453.374V178.989H486.385V212H407.037Z" fill="white"/>
|
||||
<path d="M338.587 125.989V178.989H345.249C348.884 178.989 351.609 175.96 351.609 172.326V132.651C351.609 129.017 348.884 125.989 345.249 125.989H338.587ZM371.598 106L372.204 106.303C386.741 106.606 398.249 118.114 398.249 132.651V185.651C398.249 200.189 386.135 212 371.598 212H292.249V0H371.598C386.135 0 398.249 12.1143 398.249 26.6514V79.6514C398.249 94.1886 386.135 106 371.598 106ZM338.587 86.3143H345.249C348.884 86.3143 351.609 83.2857 351.609 79.6514V39.9771C351.609 36.3429 348.884 33.3143 345.249 33.3143H338.587V86.3143Z" fill="white"/>
|
||||
<path d="M137.532 212V0H190.23L210.218 125.989L230.207 0H283.207V212H236.87V106L216.881 212H203.555L183.87 106V212H137.532Z" fill="white"/>
|
||||
<path d="M49.0637 212V0H128.412V33.3143H95.4008V86.3143H128.412V125.989H95.4008V178.989H128.412V212H49.0637Z" fill="white"/>
|
||||
<rect x="1125.62" y="65.6279" width="25.2381" height="25.238" fill="white"/>
|
||||
<path d="M1150.86 106H1160.95V121.143H1150.86V106Z" fill="white"/>
|
||||
<rect x="1125.62" y="121.118" width="15.1428" height="15.1429" fill="white"/>
|
||||
<rect x="1095.33" y="50.5068" width="25.2381" height="25.238" fill="#010312"/>
|
||||
<rect x="1105.43" y="111.022" width="15.1428" height="15.1429" fill="#010312"/>
|
||||
<rect x="1085.23" y="126.23" width="15.1428" height="15.1429" fill="#010312"/>
|
||||
<rect x="42.9069" y="55.4932" width="10.0952" height="25.238" fill="#010312"/>
|
||||
<rect x="45.4301" y="121.118" width="10.0952" height="20.1904" fill="#010312"/>
|
||||
<rect x="22.7124" y="55.5215" width="25.2381" height="25.238" fill="white"/>
|
||||
<path d="M0 121.148H10.0952V136.291H0V121.148Z" fill="white"/>
|
||||
<rect x="15.1404" y="141.375" width="15.1428" height="15.1429" fill="white"/>
|
||||
<rect x="60.5702" y="141.375" width="15.1428" height="15.1429" fill="#010312"/>
|
||||
<svg width="2052" height="549" viewBox="0 0 2052 549" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="2052" height="549" fill="#2A2B4C"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M406.248 151V398.8H498.996V360.214H460.41V298.264H498.996V251.89H460.41V189.94H498.996V151H406.248ZM509.655 151V398.8H563.817V274.9L586.827 398.8H602.403L625.767 274.9V398.8H679.929V151H617.979L594.615 298.264L571.251 151H509.655ZM744.661 360.214V298.264H752.449C756.697 298.264 759.883 301.804 759.883 306.052V352.426C759.883 356.674 756.697 360.214 752.449 360.214H744.661ZM783.955 275.254L783.247 274.9C800.239 274.9 814.399 261.094 814.399 244.102V182.152C814.399 165.16 800.239 151 783.247 151H690.499V398.8H783.247C800.239 398.8 814.399 384.994 814.399 368.002V306.052C814.399 289.06 800.947 275.608 783.955 275.254ZM752.449 251.89H744.661V189.94H752.449C756.697 189.94 759.883 193.48 759.883 197.728V244.102C759.883 248.35 756.697 251.89 752.449 251.89ZM917.421 151H824.673V398.8H917.421V360.214H878.835V298.264H917.421V251.89H878.835V189.94H917.421V151ZM982.242 360.214V189.94H989.676C994.278 189.94 997.464 193.48 997.464 197.728V352.426C997.464 356.674 994.278 360.214 989.676 360.214H982.242ZM1051.98 368.002V182.152C1051.98 165.16 1037.82 151 1020.83 151H928.08V398.8H1020.83C1037.82 398.8 1051.98 384.994 1051.98 368.002ZM428 314.8H410V332.8H428V314.8Z" fill="white"/>
|
||||
<rect x="357" y="314.8" width="18" height="18" fill="white"/>
|
||||
<rect x="340" y="291.8" width="11" height="18" fill="white"/>
|
||||
<rect x="366" y="214.8" width="30" height="30" fill="white"/>
|
||||
<rect x="1674.52" y="240.378" width="26.6955" height="26.6955" fill="white"/>
|
||||
<rect x="1700.32" y="283.091" width="10.6782" height="16.0173" fill="white"/>
|
||||
<rect x="1674.52" y="298.218" width="16.0173" height="16.0173" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1063 367.646V181.244C1063 164.202 1076.85 150 1093.89 150H1156.02C1173.07 150 1187.27 164.202 1187.27 181.244V235.567H1132.59V196.867C1132.59 192.606 1129.39 189.056 1124.78 189.056C1120.52 189.056 1117.32 192.606 1117.32 196.867V352.024C1117.32 356.284 1120.52 359.835 1124.78 359.835C1129.39 359.835 1132.59 356.284 1132.59 352.024V313.323H1187.27V367.646C1187.27 384.688 1173.07 398.535 1156.02 398.535H1093.89C1076.85 398.535 1063 384.688 1063 367.646ZM1196.14 398.535V150H1250.47V251.189H1265.73V150H1320.06V398.535H1265.73V297.701H1250.47V398.535H1196.14ZM1406.34 398.535L1402.79 359.835H1379.36L1375.45 398.535H1328.94L1359.83 150H1421.96L1453.21 398.535H1406.34ZM1383.62 313.323H1398.18L1390.72 235.567L1383.62 313.323ZM1516.06 398.535H1461.74V150H1516.06V398.535ZM1524.84 398.535V150H1579.17L1602.24 274.268V150H1648.76V225.251H1642.48V251.946H1648.76V303.557H1634.47V319.575H1648.76V398.535H1594.43L1571.35 274.268V398.535H1524.84Z" fill="white"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg width="1371" height="249" viewBox="0 0 1371 249" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M66.248 1V248.8H158.996V210.214H120.41V148.264H158.996V101.89H120.41V39.94H158.996V1H66.248ZM169.655 1V248.8H223.817V124.9L246.827 248.8H262.403L285.767 124.9V248.8H339.929V1H277.979L254.615 148.264L231.251 1H169.655ZM404.661 210.214V148.264H412.449C416.697 148.264 419.883 151.804 419.883 156.052V202.426C419.883 206.674 416.697 210.214 412.449 210.214H404.661ZM443.955 125.254L443.247 124.9C460.239 124.9 474.399 111.094 474.399 94.102V32.152C474.399 15.16 460.239 1 443.247 1H350.499V248.8H443.247C460.239 248.8 474.399 234.994 474.399 218.002V156.052C474.399 139.06 460.947 125.608 443.955 125.254ZM412.449 101.89H404.661V39.94H412.449C416.697 39.94 419.883 43.48 419.883 47.728V94.102C419.883 98.35 416.697 101.89 412.449 101.89ZM577.421 1H484.673V248.8H577.421V210.214H538.835V148.264H577.421V101.89H538.835V39.94H577.421V1ZM642.242 210.214V39.94H649.676C654.278 39.94 657.464 43.48 657.464 47.728V202.426C657.464 206.674 654.278 210.214 649.676 210.214H642.242ZM711.98 218.002V32.152C711.98 15.16 697.82 1 680.828 1H588.08V248.8H680.828C697.82 248.8 711.98 234.994 711.98 218.002ZM88 164.8H70V182.8H88V164.8Z" fill="#2A2B4C"/>
|
||||
<rect x="17" y="164.8" width="18" height="18" fill="#2A2B4C"/>
|
||||
<rect y="141.8" width="11" height="18" fill="#2A2B4C"/>
|
||||
<rect x="26" y="64.7998" width="30" height="30" fill="#2A2B4C"/>
|
||||
<rect x="1334.52" y="90.3779" width="26.6955" height="26.6955" fill="#2A2B4C"/>
|
||||
<rect x="1360.32" y="133.091" width="10.6782" height="16.0173" fill="#2A2B4C"/>
|
||||
<rect x="1334.52" y="148.219" width="16.0173" height="16.0173" fill="#2A2B4C"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M723 217.646V31.2444C723 14.202 736.847 0 753.889 0H816.023C833.066 0 847.268 14.202 847.268 31.2444V85.5672H792.59V46.8667C792.59 42.6061 789.394 39.0556 784.779 39.0556C780.518 39.0556 777.323 42.6061 777.323 46.8667V202.024C777.323 206.284 780.518 209.835 784.779 209.835C789.394 209.835 792.59 206.284 792.59 202.024V163.323H847.268V217.646C847.268 234.688 833.066 248.535 816.023 248.535H753.889C736.847 248.535 723 234.688 723 217.646ZM856.144 248.535V0H910.467V101.189H925.734V0H980.057V248.535H925.734V147.701H910.467V248.535H856.144ZM1066.34 248.535L1062.79 209.835H1039.36L1035.45 248.535H988.941L1019.83 0H1081.96L1113.21 248.535H1066.34ZM1043.62 163.323H1058.18L1050.72 85.5672L1043.62 163.323ZM1176.06 248.535H1121.74V0H1176.06V248.535ZM1184.84 248.535V0H1239.17L1262.24 124.268V0H1308.76V75.2506H1302.48V101.946H1308.76V153.557H1294.47V169.575H1308.76V248.535H1254.43L1231.35 124.268V248.535H1184.84Z" fill="#2A2B4C"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -1,24 +1,11 @@
|
||||
<svg width="1161" height="212" viewBox="0 0 1161 212" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1010.3 212V0H1056.64L1076.33 106V0H1116V212H1069.66L1049.98 106V212H1010.3Z" fill="#010312"/>
|
||||
<path d="M1001.3 212H954.958V0H1001.3V212Z" fill="#010312"/>
|
||||
<path d="M906.196 212L903.167 178.989H883.179L879.847 212H840.173L866.522 0H919.522L946.173 212H906.196ZM886.813 139.314H899.23L892.87 72.9886L886.813 139.314Z" fill="#010312"/>
|
||||
<path d="M725.385 212V0H771.722V86.3143H784.745V0H831.082V212H784.745V125.989H771.722V212H725.385Z" fill="#010312"/>
|
||||
<path d="M610.298 185.651V26.6514C610.298 12.1143 622.109 0 636.646 0H689.646C704.183 0 716.298 12.1143 716.298 26.6514V72.9886H669.658V39.9771C669.658 36.3429 666.932 33.3143 662.995 33.3143C659.36 33.3143 656.635 36.3429 656.635 39.9771V172.326C656.635 175.96 659.36 178.989 662.995 178.989C666.932 178.989 669.658 175.96 669.658 172.326V139.314H716.298V185.651C716.298 200.189 704.183 212 689.646 212H636.646C622.109 212 610.298 200.189 610.298 185.651Z" fill="#010312"/>
|
||||
<path d="M541.841 33.3143V178.989H548.201C552.138 178.989 554.864 175.96 554.864 172.326V39.9771C554.864 36.3429 552.138 33.3143 548.201 33.3143H541.841ZM601.504 26.6514V185.651C601.504 200.189 589.389 212 574.852 212H495.504V0H574.852C589.389 0 601.504 12.1143 601.504 26.6514Z" fill="#010312"/>
|
||||
<path d="M407.037 212V0H486.385V33.3143H453.374V86.3143H486.385V125.989H453.374V178.989H486.385V212H407.037Z" fill="#010312"/>
|
||||
<path d="M338.587 125.989V178.989H345.249C348.884 178.989 351.609 175.96 351.609 172.326V132.651C351.609 129.017 348.884 125.989 345.249 125.989H338.587ZM371.598 106L372.204 106.303C386.741 106.606 398.249 118.114 398.249 132.651V185.651C398.249 200.189 386.135 212 371.598 212H292.249V0H371.598C386.135 0 398.249 12.1143 398.249 26.6514V79.6514C398.249 94.1886 386.135 106 371.598 106ZM338.587 86.3143H345.249C348.884 86.3143 351.609 83.2857 351.609 79.6514V39.9771C351.609 36.3429 348.884 33.3143 345.249 33.3143H338.587V86.3143Z" fill="#010312"/>
|
||||
<path d="M137.532 212V0H190.23L210.218 125.989L230.207 0H283.207V212H236.87V106L216.881 212H203.555L183.87 106V212H137.532Z" fill="#010312"/>
|
||||
<path d="M49.0637 212V0H128.412V33.3143H95.4008V86.3143H128.412V125.989H95.4008V178.989H128.412V212H49.0637Z" fill="#010312"/>
|
||||
<rect x="1125.62" y="65.6279" width="25.2381" height="25.238" fill="#010312"/>
|
||||
<path d="M1150.86 106H1160.95V121.143H1150.86V106Z" fill="#010312"/>
|
||||
<rect x="1125.62" y="121.118" width="15.1428" height="15.1429" fill="#010312"/>
|
||||
<rect x="1095.33" y="50.5068" width="25.2381" height="25.238" fill="white"/>
|
||||
<rect x="1105.43" y="111.022" width="15.1428" height="15.1429" fill="white"/>
|
||||
<rect x="1085.23" y="126.23" width="15.1428" height="15.1429" fill="white"/>
|
||||
<rect x="42.9069" y="55.4932" width="10.0952" height="25.238" fill="white"/>
|
||||
<rect x="45.4301" y="121.118" width="10.0952" height="20.1904" fill="white"/>
|
||||
<rect x="22.7124" y="55.5215" width="25.2381" height="25.238" fill="#010312"/>
|
||||
<path d="M0 121.148H10.0952V136.291H0V121.148Z" fill="#010312"/>
|
||||
<rect x="15.1404" y="141.375" width="15.1428" height="15.1429" fill="#010312"/>
|
||||
<rect x="60.5702" y="141.375" width="15.1428" height="15.1429" fill="white"/>
|
||||
<svg width="2052" height="549" viewBox="0 0 2052 549" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="2052" height="549" fill="#2A2B4C"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M406.248 151V398.8H498.996V360.214H460.41V298.264H498.996V251.89H460.41V189.94H498.996V151H406.248ZM509.655 151V398.8H563.817V274.9L586.827 398.8H602.403L625.767 274.9V398.8H679.929V151H617.979L594.615 298.264L571.251 151H509.655ZM744.661 360.214V298.264H752.449C756.697 298.264 759.883 301.804 759.883 306.052V352.426C759.883 356.674 756.697 360.214 752.449 360.214H744.661ZM783.955 275.254L783.247 274.9C800.239 274.9 814.399 261.094 814.399 244.102V182.152C814.399 165.16 800.239 151 783.247 151H690.499V398.8H783.247C800.239 398.8 814.399 384.994 814.399 368.002V306.052C814.399 289.06 800.947 275.608 783.955 275.254ZM752.449 251.89H744.661V189.94H752.449C756.697 189.94 759.883 193.48 759.883 197.728V244.102C759.883 248.35 756.697 251.89 752.449 251.89ZM917.421 151H824.673V398.8H917.421V360.214H878.835V298.264H917.421V251.89H878.835V189.94H917.421V151ZM982.242 360.214V189.94H989.676C994.278 189.94 997.464 193.48 997.464 197.728V352.426C997.464 356.674 994.278 360.214 989.676 360.214H982.242ZM1051.98 368.002V182.152C1051.98 165.16 1037.82 151 1020.83 151H928.08V398.8H1020.83C1037.82 398.8 1051.98 384.994 1051.98 368.002ZM428 314.8H410V332.8H428V314.8Z" fill="white"/>
|
||||
<rect x="357" y="314.8" width="18" height="18" fill="white"/>
|
||||
<rect x="340" y="291.8" width="11" height="18" fill="white"/>
|
||||
<rect x="366" y="214.8" width="30" height="30" fill="white"/>
|
||||
<rect x="1674.52" y="240.378" width="26.6955" height="26.6955" fill="white"/>
|
||||
<rect x="1700.32" y="283.091" width="10.6782" height="16.0173" fill="white"/>
|
||||
<rect x="1674.52" y="298.218" width="16.0173" height="16.0173" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1063 367.646V181.244C1063 164.202 1076.85 150 1093.89 150H1156.02C1173.07 150 1187.27 164.202 1187.27 181.244V235.567H1132.59V196.867C1132.59 192.606 1129.39 189.056 1124.78 189.056C1120.52 189.056 1117.32 192.606 1117.32 196.867V352.024C1117.32 356.284 1120.52 359.835 1124.78 359.835C1129.39 359.835 1132.59 356.284 1132.59 352.024V313.323H1187.27V367.646C1187.27 384.688 1173.07 398.535 1156.02 398.535H1093.89C1076.85 398.535 1063 384.688 1063 367.646ZM1196.14 398.535V150H1250.47V251.189H1265.73V150H1320.06V398.535H1265.73V297.701H1250.47V398.535H1196.14ZM1406.34 398.535L1402.79 359.835H1379.36L1375.45 398.535H1328.94L1359.83 150H1421.96L1453.21 398.535H1406.34ZM1383.62 313.323H1398.18L1390.72 235.567L1383.62 313.323ZM1516.06 398.535H1461.74V150H1516.06V398.535ZM1524.84 398.535V150H1579.17L1602.24 274.268V150H1648.76V225.251H1642.48V251.946H1648.76V303.557H1634.47V319.575H1648.76V398.535H1594.43L1571.35 274.268V398.535H1524.84Z" fill="white"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.8 KiB |
@@ -2,8 +2,8 @@
|
||||
"$schema": "https://mintlify.com/schema.json",
|
||||
"name": "Embedchain",
|
||||
"logo": {
|
||||
"dark": "/logo/dark.svg",
|
||||
"light": "/logo/light.svg",
|
||||
"dark": "/logo/dark-rt.svg",
|
||||
"light": "/logo/light-rt.svg",
|
||||
"href": "https://github.com/embedchain/embedchain"
|
||||
},
|
||||
"favicon": "/favicon.png",
|
||||
@@ -41,16 +41,6 @@
|
||||
"name": "Talk to founders",
|
||||
"icon": "calendar",
|
||||
"url": "https://cal.com/taranjeetio/ec"
|
||||
},
|
||||
{
|
||||
"name": "Join our slack",
|
||||
"icon": "slack",
|
||||
"url": "https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw"
|
||||
},
|
||||
{
|
||||
"name": "Join our discord",
|
||||
"icon": "discord",
|
||||
"url": "https://discord.gg/CUU9FPhRNt"
|
||||
}
|
||||
],
|
||||
"topbarLinks": [
|
||||
@@ -61,7 +51,7 @@
|
||||
],
|
||||
"topbarCtaButton": {
|
||||
"name": "Join our slack",
|
||||
"url": "https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw"
|
||||
"url": "https://embedchain.ai/slack"
|
||||
},
|
||||
"primaryTab": {
|
||||
"name": "Documentation"
|
||||
@@ -70,32 +60,24 @@
|
||||
{
|
||||
"group": "Get Started",
|
||||
"pages": [
|
||||
"get-started/introduction",
|
||||
"get-started/quickstart",
|
||||
"get-started/introduction",
|
||||
"get-started/faq",
|
||||
"get-started/full-stack",
|
||||
{
|
||||
"group": "🔗 Integrations",
|
||||
"group": "🔗 Integrations",
|
||||
"pages": [
|
||||
"integration/langsmith",
|
||||
"integration/chainlit",
|
||||
"integration/streamlit-mistral"
|
||||
]
|
||||
},
|
||||
"get-started/faq"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Deployment",
|
||||
"pages": [
|
||||
"get-started/deployment",
|
||||
"deployment/fly_io",
|
||||
"deployment/modal_com",
|
||||
"deployment/render_com",
|
||||
"deployment/streamlit_io"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Use cases",
|
||||
"pages": [
|
||||
"use-cases/introduction",
|
||||
"use-cases/chatbots",
|
||||
"use-cases/question-answering",
|
||||
"use-cases/semantic-search"
|
||||
@@ -104,31 +86,44 @@
|
||||
{
|
||||
"group": "Components",
|
||||
"pages": [
|
||||
"components/introduction",
|
||||
{
|
||||
"group": "Data sources",
|
||||
"pages": [
|
||||
|
||||
"components/data-sources/overview",
|
||||
{
|
||||
"group": "Data types",
|
||||
"pages": [
|
||||
"components/data-sources/pdf-file",
|
||||
"components/data-sources/csv",
|
||||
"components/data-sources/json",
|
||||
"components/data-sources/docs-site",
|
||||
"components/data-sources/docx",
|
||||
"components/data-sources/mdx",
|
||||
"components/data-sources/notion",
|
||||
"components/data-sources/pdf-file",
|
||||
"components/data-sources/qna",
|
||||
"components/data-sources/sitemap",
|
||||
"components/data-sources/text",
|
||||
"components/data-sources/directory",
|
||||
"components/data-sources/web-page",
|
||||
"components/data-sources/openapi",
|
||||
"components/data-sources/youtube-channel",
|
||||
"components/data-sources/youtube-video",
|
||||
"components/data-sources/docs-site",
|
||||
"components/data-sources/mdx",
|
||||
"components/data-sources/docx",
|
||||
"components/data-sources/notion",
|
||||
"components/data-sources/sitemap",
|
||||
"components/data-sources/xml",
|
||||
"components/data-sources/qna",
|
||||
"components/data-sources/openapi",
|
||||
"components/data-sources/gmail",
|
||||
"components/data-sources/github",
|
||||
"components/data-sources/postgres",
|
||||
"components/data-sources/mysql",
|
||||
"components/data-sources/slack",
|
||||
"components/data-sources/discord",
|
||||
"components/data-sources/discourse",
|
||||
"components/data-sources/substack",
|
||||
"components/data-sources/discord",
|
||||
"components/data-sources/beehiiv",
|
||||
"components/data-sources/directory"
|
||||
"components/data-sources/directory",
|
||||
"components/data-sources/dropbox",
|
||||
"components/data-sources/image",
|
||||
"components/data-sources/custom"
|
||||
]
|
||||
},
|
||||
"components/data-sources/data-type-handling"
|
||||
@@ -139,6 +134,19 @@
|
||||
"components/embedding-models"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Deployment",
|
||||
"pages": [
|
||||
"get-started/deployment",
|
||||
"deployment/fly_io",
|
||||
"deployment/modal_com",
|
||||
"deployment/render_com",
|
||||
"deployment/streamlit_io",
|
||||
"deployment/gradio_app",
|
||||
"deployment/huggingface_spaces",
|
||||
"deployment/embedchain_ai"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Community",
|
||||
"pages": [
|
||||
@@ -148,6 +156,7 @@
|
||||
{
|
||||
"group": "Examples",
|
||||
"pages": [
|
||||
"examples/chat-with-PDF",
|
||||
"examples/notebooks-and-replits",
|
||||
{
|
||||
"group": "REST API Service",
|
||||
@@ -165,7 +174,9 @@
|
||||
},
|
||||
"examples/full_stack",
|
||||
"examples/openai-assistant",
|
||||
"examples/opensource-assistant"
|
||||
"examples/opensource-assistant",
|
||||
"examples/nextjs-assistant",
|
||||
"examples/slack-AI"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -235,6 +246,9 @@
|
||||
"posthog": {
|
||||
"apiKey": "phc_PHQDA5KwztijnSojsxJ2c1DuJd52QCzJzT2xnSGvjN2",
|
||||
"apiHost": "https://app.embedchain.ai/ingest"
|
||||
},
|
||||
"ga4": {
|
||||
"measurementId": "G-4QK7FJE6T3"
|
||||
}
|
||||
},
|
||||
"feedback": {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Chatbots'
|
||||
title: '🤖 Chatbots'
|
||||
---
|
||||
|
||||
Chatbots, especially those powered by Large Language Models (LLMs), have a wide range of use cases, significantly enhancing various aspects of business, education, and personal assistance. Here are some key applications:
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: 🧱 Introduction
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
You can use embedchain to create the following usecases:
|
||||
|
||||
* [Chatbots](/use-cases/chatbots)
|
||||
* [Question Answering](/use-cases/question-answering)
|
||||
* [Semantic Search](/use-cases/semantic-search)
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
title: 'Question Answering'
|
||||
title: '❓ Question Answering'
|
||||
---
|
||||
|
||||
Utilizing large language models (LLMs) for question answering is a transformative application, bringing significant benefits to various real-world situations. Embedchain extensively supports tasks related to question answering, including summarization, content creation, language translation, and data analysis. The versatility of question answering with LLMs enables solutions for numerous practical applications such as:
|
||||
@@ -24,7 +24,7 @@ Quickly create a RAG pipeline to answer queries about the [Next.JS Framework](ht
|
||||
First, let's create your RAG pipeline. Open your Python environment and enter:
|
||||
|
||||
```python Create pipeline
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
app = App()
|
||||
```
|
||||
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
---
|
||||
title: '🔍 Semantic Search'
|
||||
---
|
||||
|
||||
Semantic searching, which involves understanding the intent and contextual meaning behind search queries, is yet another popular use-case of RAG. It has several popular use cases across various domains:
|
||||
|
||||
- **Information Retrieval**: Enhances search accuracy in databases and websites
|
||||
@@ -19,7 +23,7 @@ Embedchain offers a simple yet customizable `search()` API that you can use for
|
||||
First, let's create your RAG pipeline. Open your Python environment and enter:
|
||||
|
||||
```python Create pipeline
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain import App
|
||||
app = App()
|
||||
```
|
||||
|
||||
@@ -48,18 +52,24 @@ app.search("Summarize the features of Next.js 14?")
|
||||
[
|
||||
{
|
||||
'context': 'Next.js 14 | Next.jsBack to BlogThursday, October 26th 2023Next.js 14Posted byLee Robinson@leeerobTim Neutkens@timneutkensAs we announced at Next.js Conf, Next.js 14 is our most focused release with: Turbopack: 5,000 tests passing for App & Pages Router 53% faster local server startup 94% faster code updates with Fast Refresh Server Actions (Stable): Progressively enhanced mutations Integrated with caching & revalidating Simple function calls, or works natively with forms Partial Prerendering',
|
||||
'source': 'https://nextjs.org/blog/next-14',
|
||||
'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5'
|
||||
'metadata': {
|
||||
'source': 'https://nextjs.org/blog/next-14',
|
||||
'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5'
|
||||
}
|
||||
},
|
||||
{
|
||||
'context': 'Next.js 13.3 | Next.jsBack to BlogThursday, April 6th 2023Next.js 13.3Posted byDelba de Oliveira@delba_oliveiraTim Neutkens@timneutkensNext.js 13.3 adds popular community-requested features, including: File-Based Metadata API: Dynamically generate sitemaps, robots, favicons, and more. Dynamic Open Graph Images: Generate OG images using JSX, HTML, and CSS. Static Export for App Router: Static / Single-Page Application (SPA) support for Server Components. Parallel Routes and Interception: Advanced',
|
||||
'source': 'https://nextjs.org/blog/next-13-3',
|
||||
'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5'
|
||||
'metadata': {
|
||||
'source': 'https://nextjs.org/blog/next-13-3',
|
||||
'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5'
|
||||
}
|
||||
},
|
||||
{
|
||||
'context': 'Upgrading: Version 14 | Next.js MenuUsing App RouterFeatures available in /appApp Router.UpgradingVersion 14Version 14 Upgrading from 13 to 14 To update to Next.js version 14, run the following command using your preferred package manager: Terminalnpm i next@latest react@latest react-dom@latest eslint-config-next@latest Terminalyarn add next@latest react@latest react-dom@latest eslint-config-next@latest Terminalpnpm up next react react-dom eslint-config-next -latest Terminalbun add next@latest',
|
||||
'source': 'https://nextjs.org/docs/app/building-your-application/upgrading/version-14',
|
||||
'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5'
|
||||
'metadata': {
|
||||
'source': 'https://nextjs.org/docs/app/building-your-application/upgrading/version-14',
|
||||
'document_id': '6c8d1a7b-ea34-4927-8823-daa29dcfc5af--b83edb69b8fc7e442ff8ca311b48510e6c80bf00caa806b3a6acb34e1bcdd5d5'
|
||||
}
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
@@ -178,7 +178,7 @@ await app.addLocal("qna_pair", ["Question", "Answer"]);
|
||||
|
||||
## Testing
|
||||
|
||||
Before you consume valueable tokens, you should make sure that the embedding you have done works and that it's receiving the correct document from the database.
|
||||
Before you consume valuable tokens, you should make sure that the embedding you have done works and that it's receiving the correct document from the database.
|
||||
|
||||
For this you can use the `dryRun` method.
|
||||
|
||||
|
||||
@@ -2,10 +2,9 @@ import importlib.metadata
|
||||
|
||||
__version__ = importlib.metadata.version(__package__ or __name__)
|
||||
|
||||
from embedchain.apps.app import App # noqa: F401
|
||||
from embedchain.app import App # noqa: F401
|
||||
from embedchain.client import Client # noqa: F401
|
||||
from embedchain.pipeline import Pipeline # noqa: F401
|
||||
from embedchain.vectordb.chroma import ChromaDB # noqa: F401
|
||||
|
||||
# Setup the user directory if doesn't exist already
|
||||
Client.setup_dir()
|
||||
|
||||
@@ -0,0 +1,457 @@
|
||||
import ast
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sqlite3
|
||||
import uuid
|
||||
from typing import Any, Optional
|
||||
|
||||
import requests
|
||||
import yaml
|
||||
|
||||
from embedchain.cache import (Config, ExactMatchEvaluation,
|
||||
SearchDistanceEvaluation, cache,
|
||||
gptcache_data_manager, gptcache_pre_function)
|
||||
from embedchain.client import Client
|
||||
from embedchain.config import AppConfig, CacheConfig, ChunkerConfig
|
||||
from embedchain.constants import SQLITE_PATH
|
||||
from embedchain.embedchain import EmbedChain
|
||||
from embedchain.embedder.base import BaseEmbedder
|
||||
from embedchain.embedder.openai import OpenAIEmbedder
|
||||
from embedchain.factory import EmbedderFactory, LlmFactory, VectorDBFactory
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
from embedchain.llm.base import BaseLlm
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
from embedchain.telemetry.posthog import AnonymousTelemetry
|
||||
from embedchain.utils.misc import validate_config
|
||||
from embedchain.vectordb.base import BaseVectorDB
|
||||
from embedchain.vectordb.chroma import ChromaDB
|
||||
|
||||
# Set up the user directory if it doesn't exist already
|
||||
Client.setup_dir()
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class App(EmbedChain):
|
||||
"""
|
||||
EmbedChain App lets you create a LLM powered app for your unstructured
|
||||
data by defining your chosen data source, embedding model,
|
||||
and vector database.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
id: str = None,
|
||||
name: str = None,
|
||||
config: AppConfig = None,
|
||||
db: BaseVectorDB = None,
|
||||
embedding_model: BaseEmbedder = None,
|
||||
llm: BaseLlm = None,
|
||||
config_data: dict = None,
|
||||
log_level=logging.WARN,
|
||||
auto_deploy: bool = False,
|
||||
chunker: ChunkerConfig = None,
|
||||
cache_config: CacheConfig = None,
|
||||
):
|
||||
"""
|
||||
Initialize a new `App` instance.
|
||||
|
||||
:param config: Configuration for the pipeline, defaults to None
|
||||
:type config: AppConfig, optional
|
||||
:param db: The database to use for storing and retrieving embeddings, defaults to None
|
||||
:type db: BaseVectorDB, optional
|
||||
:param embedding_model: The embedding model used to calculate embeddings, defaults to None
|
||||
:type embedding_model: BaseEmbedder, optional
|
||||
:param llm: The LLM model used to calculate embeddings, defaults to None
|
||||
:type llm: BaseLlm, optional
|
||||
:param config_data: Config dictionary, defaults to None
|
||||
:type config_data: dict, optional
|
||||
:param log_level: Log level to use, defaults to logging.WARN
|
||||
:type log_level: int, optional
|
||||
:param auto_deploy: Whether to deploy the pipeline automatically, defaults to False
|
||||
:type auto_deploy: bool, optional
|
||||
:raises Exception: If an error occurs while creating the pipeline
|
||||
"""
|
||||
if id and config_data:
|
||||
raise Exception("Cannot provide both id and config. Please provide only one of them.")
|
||||
|
||||
if id and name:
|
||||
raise Exception("Cannot provide both id and name. Please provide only one of them.")
|
||||
|
||||
if name and config:
|
||||
raise Exception("Cannot provide both name and config. Please provide only one of them.")
|
||||
|
||||
logging.basicConfig(level=log_level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.auto_deploy = auto_deploy
|
||||
# Store the dict config as an attribute to be able to send it
|
||||
self.config_data = config_data if (config_data and validate_config(config_data)) else None
|
||||
self.client = None
|
||||
# pipeline_id from the backend
|
||||
self.id = None
|
||||
self.chunker = None
|
||||
if chunker:
|
||||
self.chunker = ChunkerConfig(**chunker)
|
||||
self.cache_config = cache_config
|
||||
|
||||
self.config = config or AppConfig()
|
||||
self.name = self.config.name
|
||||
self.config.id = self.local_id = str(uuid.uuid4()) if self.config.id is None else self.config.id
|
||||
|
||||
if id is not None:
|
||||
# Init client first since user is trying to fetch the pipeline
|
||||
# details from the platform
|
||||
self._init_client()
|
||||
pipeline_details = self._get_pipeline(id)
|
||||
self.config.id = self.local_id = pipeline_details["metadata"]["local_id"]
|
||||
self.id = id
|
||||
|
||||
if name is not None:
|
||||
self.name = name
|
||||
|
||||
self.embedding_model = embedding_model or OpenAIEmbedder()
|
||||
self.db = db or ChromaDB()
|
||||
self.llm = llm or OpenAILlm()
|
||||
self._init_db()
|
||||
|
||||
# If cache_config is provided, initializing the cache ...
|
||||
if self.cache_config is not None:
|
||||
self._init_cache()
|
||||
|
||||
# Send anonymous telemetry
|
||||
self._telemetry_props = {"class": self.__class__.__name__}
|
||||
self.telemetry = AnonymousTelemetry(enabled=self.config.collect_metrics)
|
||||
|
||||
# Establish a connection to the SQLite database
|
||||
self.connection = sqlite3.connect(SQLITE_PATH, check_same_thread=False)
|
||||
self.cursor = self.connection.cursor()
|
||||
|
||||
# Create the 'data_sources' table if it doesn't exist
|
||||
self.cursor.execute(
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS data_sources (
|
||||
pipeline_id TEXT,
|
||||
hash TEXT,
|
||||
type TEXT,
|
||||
value TEXT,
|
||||
metadata TEXT,
|
||||
is_uploaded INTEGER DEFAULT 0,
|
||||
PRIMARY KEY (pipeline_id, hash)
|
||||
)
|
||||
"""
|
||||
)
|
||||
self.connection.commit()
|
||||
# Send anonymous telemetry
|
||||
self.telemetry.capture(event_name="init", properties=self._telemetry_props)
|
||||
|
||||
self.user_asks = []
|
||||
if self.auto_deploy:
|
||||
self.deploy()
|
||||
|
||||
def _init_db(self):
|
||||
"""
|
||||
Initialize the database.
|
||||
"""
|
||||
self.db._set_embedder(self.embedding_model)
|
||||
self.db._initialize()
|
||||
self.db.set_collection_name(self.db.config.collection_name)
|
||||
|
||||
def _init_cache(self):
|
||||
if self.cache_config.similarity_eval_config.strategy == "exact":
|
||||
similarity_eval_func = ExactMatchEvaluation()
|
||||
else:
|
||||
similarity_eval_func = SearchDistanceEvaluation(
|
||||
max_distance=self.cache_config.similarity_eval_config.max_distance,
|
||||
positive=self.cache_config.similarity_eval_config.positive,
|
||||
)
|
||||
|
||||
cache.init(
|
||||
pre_embedding_func=gptcache_pre_function,
|
||||
embedding_func=self.embedding_model.to_embeddings,
|
||||
data_manager=gptcache_data_manager(vector_dimension=self.embedding_model.vector_dimension),
|
||||
similarity_evaluation=similarity_eval_func,
|
||||
config=Config(**self.cache_config.init_config.as_dict()),
|
||||
)
|
||||
|
||||
def _init_client(self):
|
||||
"""
|
||||
Initialize the client.
|
||||
"""
|
||||
config = Client.load_config()
|
||||
if config.get("api_key"):
|
||||
self.client = Client()
|
||||
else:
|
||||
api_key = input(
|
||||
"🔑 Enter your Embedchain API key. You can find the API key at https://app.embedchain.ai/settings/keys/ \n" # noqa: E501
|
||||
)
|
||||
self.client = Client(api_key=api_key)
|
||||
|
||||
def _get_pipeline(self, id):
|
||||
"""
|
||||
Get existing pipeline
|
||||
"""
|
||||
print("🛠️ Fetching pipeline details from the platform...")
|
||||
url = f"{self.client.host}/api/v1/pipelines/{id}/cli/"
|
||||
r = requests.get(
|
||||
url,
|
||||
headers={"Authorization": f"Token {self.client.api_key}"},
|
||||
)
|
||||
if r.status_code == 404:
|
||||
raise Exception(f"❌ Pipeline with id {id} not found!")
|
||||
|
||||
print(
|
||||
f"🎉 Pipeline loaded successfully! Pipeline url: https://app.embedchain.ai/pipelines/{r.json()['id']}\n" # noqa: E501
|
||||
)
|
||||
return r.json()
|
||||
|
||||
def _create_pipeline(self):
|
||||
"""
|
||||
Create a pipeline on the platform.
|
||||
"""
|
||||
print("🛠️ Creating pipeline on the platform...")
|
||||
# self.config_data is a dict. Pass it inside the key 'yaml_config' to the backend
|
||||
payload = {
|
||||
"yaml_config": json.dumps(self.config_data),
|
||||
"name": self.name,
|
||||
"local_id": self.local_id,
|
||||
}
|
||||
url = f"{self.client.host}/api/v1/pipelines/cli/create/"
|
||||
r = requests.post(
|
||||
url,
|
||||
json=payload,
|
||||
headers={"Authorization": f"Token {self.client.api_key}"},
|
||||
)
|
||||
if r.status_code not in [200, 201]:
|
||||
raise Exception(f"❌ Error occurred while creating pipeline. API response: {r.text}")
|
||||
|
||||
if r.status_code == 200:
|
||||
print(
|
||||
f"🎉🎉🎉 Existing pipeline found! View your pipeline: https://app.embedchain.ai/pipelines/{r.json()['id']}\n" # noqa: E501
|
||||
) # noqa: E501
|
||||
elif r.status_code == 201:
|
||||
print(
|
||||
f"🎉🎉🎉 Pipeline created successfully! View your pipeline: https://app.embedchain.ai/pipelines/{r.json()['id']}\n" # noqa: E501
|
||||
)
|
||||
return r.json()
|
||||
|
||||
def _get_presigned_url(self, data_type, data_value):
|
||||
payload = {"data_type": data_type, "data_value": data_value}
|
||||
r = requests.post(
|
||||
f"{self.client.host}/api/v1/pipelines/{self.id}/cli/presigned_url/",
|
||||
json=payload,
|
||||
headers={"Authorization": f"Token {self.client.api_key}"},
|
||||
)
|
||||
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:
|
||||
response = requests.put(presigned_url, data=file)
|
||||
response.raise_for_status()
|
||||
return response.status_code == 200
|
||||
except Exception as e:
|
||||
self.logger.exception(f"Error occurred during file upload: {str(e)}")
|
||||
print("❌ Error occurred during file upload!")
|
||||
return False
|
||||
|
||||
def _upload_data_to_pipeline(self, data_type, data_value, metadata=None):
|
||||
payload = {
|
||||
"data_type": data_type,
|
||||
"data_value": data_value,
|
||||
"metadata": metadata,
|
||||
}
|
||||
try:
|
||||
self._send_api_request(f"/api/v1/pipelines/{self.id}/cli/add/", payload)
|
||||
# print the local file path if user tries to upload a local file
|
||||
printed_value = metadata.get("file_path") if metadata.get("file_path") else data_value
|
||||
print(f"✅ Data of type: {data_type}, value: {printed_value} added successfully.")
|
||||
except Exception as e:
|
||||
print(f"❌ Error occurred during data upload for type {data_type}!. Error: {str(e)}")
|
||||
|
||||
def _send_api_request(self, endpoint, payload):
|
||||
url = f"{self.client.host}{endpoint}"
|
||||
headers = {"Authorization": f"Token {self.client.api_key}"}
|
||||
response = requests.post(url, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response
|
||||
|
||||
def _process_and_upload_data(self, data_hash, data_type, data_value):
|
||||
if os.path.isabs(data_value):
|
||||
presigned_url_data = self._get_presigned_url(data_type, data_value)
|
||||
presigned_url = presigned_url_data["presigned_url"]
|
||||
s3_key = presigned_url_data["s3_key"]
|
||||
if self._upload_file_to_presigned_url(presigned_url, file_path=data_value):
|
||||
metadata = {"file_path": data_value, "s3_key": s3_key}
|
||||
data_value = presigned_url
|
||||
else:
|
||||
self.logger.error(f"File upload failed for hash: {data_hash}")
|
||||
return False
|
||||
else:
|
||||
if data_type == "qna_pair":
|
||||
data_value = list(ast.literal_eval(data_value))
|
||||
metadata = {}
|
||||
|
||||
try:
|
||||
self._upload_data_to_pipeline(data_type, data_value, metadata)
|
||||
self._mark_data_as_uploaded(data_hash)
|
||||
return True
|
||||
except Exception:
|
||||
print(f"❌ Error occurred during data upload for hash {data_hash}!")
|
||||
return False
|
||||
|
||||
def _mark_data_as_uploaded(self, data_hash):
|
||||
self.cursor.execute(
|
||||
"UPDATE data_sources SET is_uploaded = 1 WHERE hash = ? AND pipeline_id = ?",
|
||||
(data_hash, self.local_id),
|
||||
)
|
||||
self.connection.commit()
|
||||
|
||||
def get_data_sources(self):
|
||||
db_data = self.cursor.execute("SELECT * FROM data_sources WHERE pipeline_id = ?", (self.local_id,)).fetchall()
|
||||
|
||||
data_sources = []
|
||||
for data in db_data:
|
||||
data_sources.append({"data_type": data[2], "data_value": data[3], "metadata": data[4]})
|
||||
|
||||
return data_sources
|
||||
|
||||
def deploy(self):
|
||||
if self.client is None:
|
||||
self._init_client()
|
||||
|
||||
pipeline_data = self._create_pipeline()
|
||||
self.id = pipeline_data["id"]
|
||||
|
||||
results = self.cursor.execute(
|
||||
"SELECT * FROM data_sources WHERE pipeline_id = ? AND is_uploaded = 0", (self.local_id,) # noqa:E501
|
||||
).fetchall()
|
||||
|
||||
if len(results) > 0:
|
||||
print("🛠️ Adding data to your pipeline...")
|
||||
for result in results:
|
||||
data_hash, data_type, data_value = result[1], result[2], result[3]
|
||||
self._process_and_upload_data(data_hash, data_type, data_value)
|
||||
|
||||
# Send anonymous telemetry
|
||||
self.telemetry.capture(event_name="deploy", properties=self._telemetry_props)
|
||||
|
||||
@classmethod
|
||||
def from_config(
|
||||
cls,
|
||||
config_path: Optional[str] = None,
|
||||
config: Optional[dict[str, Any]] = None,
|
||||
auto_deploy: bool = False,
|
||||
yaml_path: Optional[str] = None,
|
||||
):
|
||||
"""
|
||||
Instantiate a Pipeline object from a configuration.
|
||||
|
||||
:param config_path: Path to the YAML or JSON configuration file.
|
||||
:type config_path: Optional[str]
|
||||
:param config: A dictionary containing the configuration.
|
||||
:type config: Optional[dict[str, Any]]
|
||||
:param auto_deploy: Whether to deploy the pipeline automatically, defaults to False
|
||||
:type auto_deploy: bool, optional
|
||||
:param yaml_path: (Deprecated) Path to the YAML configuration file. Use config_path instead.
|
||||
:type yaml_path: Optional[str]
|
||||
:return: An instance of the Pipeline class.
|
||||
:rtype: Pipeline
|
||||
"""
|
||||
# Backward compatibility for yaml_path
|
||||
if yaml_path and not config_path:
|
||||
config_path = yaml_path
|
||||
|
||||
if config_path and config:
|
||||
raise ValueError("Please provide only one of config_path or config.")
|
||||
|
||||
config_data = None
|
||||
|
||||
if config_path:
|
||||
file_extension = os.path.splitext(config_path)[1]
|
||||
with open(config_path, "r") as file:
|
||||
if file_extension in [".yaml", ".yml"]:
|
||||
config_data = yaml.safe_load(file)
|
||||
elif file_extension == ".json":
|
||||
config_data = json.load(file)
|
||||
else:
|
||||
raise ValueError("config_path must be a path to a YAML or JSON file.")
|
||||
elif config and isinstance(config, dict):
|
||||
config_data = config
|
||||
else:
|
||||
logging.error(
|
||||
"Please provide either a config file path (YAML or JSON) or a config dictionary. Falling back to defaults because no config is provided.", # noqa: E501
|
||||
)
|
||||
config_data = {}
|
||||
|
||||
try:
|
||||
validate_config(config_data)
|
||||
except Exception as e:
|
||||
raise Exception(f"Error occurred while validating the config. Error: {str(e)}")
|
||||
|
||||
app_config_data = config_data.get("app", {}).get("config", {})
|
||||
db_config_data = config_data.get("vectordb", {})
|
||||
embedding_model_config_data = config_data.get("embedding_model", config_data.get("embedder", {}))
|
||||
llm_config_data = config_data.get("llm", {})
|
||||
chunker_config_data = config_data.get("chunker", {})
|
||||
cache_config_data = config_data.get("cache", None)
|
||||
|
||||
app_config = AppConfig(**app_config_data)
|
||||
|
||||
db_provider = db_config_data.get("provider", "chroma")
|
||||
db = VectorDBFactory.create(db_provider, db_config_data.get("config", {}))
|
||||
|
||||
if llm_config_data:
|
||||
llm_provider = llm_config_data.get("provider", "openai")
|
||||
llm = LlmFactory.create(llm_provider, llm_config_data.get("config", {}))
|
||||
else:
|
||||
llm = None
|
||||
|
||||
embedding_model_provider = embedding_model_config_data.get("provider", "openai")
|
||||
embedding_model = EmbedderFactory.create(
|
||||
embedding_model_provider, embedding_model_config_data.get("config", {})
|
||||
)
|
||||
|
||||
if cache_config_data is not None:
|
||||
cache_config = CacheConfig.from_config(cache_config_data)
|
||||
else:
|
||||
cache_config = None
|
||||
|
||||
# Send anonymous telemetry
|
||||
event_properties = {"init_type": "config_data"}
|
||||
AnonymousTelemetry().capture(event_name="init", properties=event_properties)
|
||||
|
||||
return cls(
|
||||
config=app_config,
|
||||
llm=llm,
|
||||
db=db,
|
||||
embedding_model=embedding_model,
|
||||
config_data=config_data,
|
||||
auto_deploy=auto_deploy,
|
||||
chunker=chunker_config_data,
|
||||
cache_config=cache_config,
|
||||
)
|
||||
@@ -1,157 +0,0 @@
|
||||
from typing import Optional
|
||||
|
||||
import yaml
|
||||
|
||||
from embedchain.config import (AppConfig, BaseEmbedderConfig, BaseLlmConfig,
|
||||
ChunkerConfig)
|
||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||
from embedchain.embedchain import EmbedChain
|
||||
from embedchain.embedder.base import BaseEmbedder
|
||||
from embedchain.embedder.openai import OpenAIEmbedder
|
||||
from embedchain.factory import EmbedderFactory, LlmFactory, VectorDBFactory
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
from embedchain.llm.base import BaseLlm
|
||||
from embedchain.llm.openai import OpenAILlm
|
||||
from embedchain.utils import validate_config
|
||||
from embedchain.vectordb.base import BaseVectorDB
|
||||
from embedchain.vectordb.chroma import ChromaDB
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class App(EmbedChain):
|
||||
"""
|
||||
The EmbedChain app in it's simplest and most straightforward form.
|
||||
An opinionated choice of LLM, vector database and embedding model.
|
||||
|
||||
Methods:
|
||||
add(source, data_type): adds the data from the given URL to the vector db.
|
||||
query(query): finds answer to the given query using vector database and LLM.
|
||||
chat(query): finds answer to the given query using vector database and LLM, with conversation history.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: Optional[AppConfig] = None,
|
||||
llm: BaseLlm = None,
|
||||
llm_config: Optional[BaseLlmConfig] = None,
|
||||
db: BaseVectorDB = None,
|
||||
db_config: Optional[BaseVectorDbConfig] = None,
|
||||
embedder: BaseEmbedder = None,
|
||||
embedder_config: Optional[BaseEmbedderConfig] = None,
|
||||
system_prompt: Optional[str] = None,
|
||||
chunker: Optional[ChunkerConfig] = None,
|
||||
):
|
||||
"""
|
||||
Initialize a new `App` instance.
|
||||
|
||||
:param config: Config for the app instance., defaults to None
|
||||
:type config: Optional[AppConfig], optional
|
||||
:param llm: LLM Class instance. example: `from embedchain.llm.openai import OpenAILlm`, defaults to OpenAiLlm
|
||||
:type llm: BaseLlm, optional
|
||||
:param llm_config: Allows you to configure the LLM, e.g. how many documents to return,
|
||||
example: `from embedchain.config import BaseLlmConfig`, defaults to None
|
||||
:type llm_config: Optional[BaseLlmConfig], optional
|
||||
:param db: The database to use for storing and retrieving embeddings,
|
||||
example: `from embedchain.vectordb.chroma_db import ChromaDb`, defaults to ChromaDb
|
||||
:type db: BaseVectorDB, optional
|
||||
:param db_config: Allows you to configure the vector database,
|
||||
example: `from embedchain.config import ChromaDbConfig`, defaults to None
|
||||
:type db_config: Optional[BaseVectorDbConfig], optional
|
||||
:param embedder: The embedder (embedding model and function) use to calculate embeddings.
|
||||
example: `from embedchain.embedder.gpt4all_embedder import GPT4AllEmbedder`, defaults to OpenAIEmbedder
|
||||
:type embedder: BaseEmbedder, optional
|
||||
:param embedder_config: Allows you to configure the Embedder.
|
||||
example: `from embedchain.config import BaseEmbedderConfig`, defaults to None
|
||||
:type embedder_config: Optional[BaseEmbedderConfig], optional
|
||||
:param system_prompt: System prompt that will be provided to the LLM as such, defaults to None
|
||||
:type system_prompt: Optional[str], optional
|
||||
:raises TypeError: LLM, database or embedder or their config is not a valid class instance.
|
||||
"""
|
||||
# Type check configs
|
||||
if config and not isinstance(config, AppConfig):
|
||||
raise TypeError(
|
||||
"Config is not a `AppConfig` instance. "
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
if llm_config and not isinstance(llm_config, BaseLlmConfig):
|
||||
raise TypeError(
|
||||
"`llm_config` is not a `BaseLlmConfig` instance. "
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
if db_config and not isinstance(db_config, BaseVectorDbConfig):
|
||||
raise TypeError(
|
||||
"`db_config` is not a `BaseVectorDbConfig` instance. "
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
if embedder_config and not isinstance(embedder_config, BaseEmbedderConfig):
|
||||
raise TypeError(
|
||||
"`embedder_config` is not a `BaseEmbedderConfig` instance. "
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
|
||||
# Assign defaults
|
||||
if config is None:
|
||||
config = AppConfig()
|
||||
if llm is None:
|
||||
llm = OpenAILlm(config=llm_config)
|
||||
if db is None:
|
||||
db = ChromaDB(config=db_config)
|
||||
if embedder is None:
|
||||
embedder = OpenAIEmbedder(config=embedder_config)
|
||||
|
||||
self.chunker = None
|
||||
if chunker:
|
||||
self.chunker = ChunkerConfig(**chunker)
|
||||
# Type check assignments
|
||||
if not isinstance(llm, BaseLlm):
|
||||
raise TypeError(
|
||||
"LLM is not a `BaseLlm` instance. "
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
if not isinstance(db, BaseVectorDB):
|
||||
raise TypeError(
|
||||
"Database is not a `BaseVectorDB` instance. "
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
if not isinstance(embedder, BaseEmbedder):
|
||||
raise TypeError(
|
||||
"Embedder is not a `BaseEmbedder` instance. "
|
||||
"Please make sure the type is right and that you are passing an instance."
|
||||
)
|
||||
super().__init__(config, llm=llm, db=db, embedder=embedder, system_prompt=system_prompt)
|
||||
|
||||
@classmethod
|
||||
def from_config(cls, yaml_path: str):
|
||||
"""
|
||||
Instantiate an App object from a YAML configuration file.
|
||||
|
||||
:param yaml_path: Path to the YAML configuration file.
|
||||
:type yaml_path: str
|
||||
:return: An instance of the App class.
|
||||
:rtype: App
|
||||
"""
|
||||
with open(yaml_path, "r") as file:
|
||||
config_data = yaml.safe_load(file)
|
||||
|
||||
try:
|
||||
validate_config(config_data)
|
||||
except Exception as e:
|
||||
raise Exception(f"❌ Error occurred while validating the YAML config. Error: {str(e)}")
|
||||
|
||||
app_config_data = config_data.get("app", {})
|
||||
llm_config_data = config_data.get("llm", {})
|
||||
db_config_data = config_data.get("vectordb", {})
|
||||
embedding_model_config_data = config_data.get("embedding_model", config_data.get("embedder", {}))
|
||||
chunker_config_data = config_data.get("chunker", {})
|
||||
|
||||
app_config = AppConfig(**app_config_data.get("config", {}))
|
||||
|
||||
llm_provider = llm_config_data.get("provider", "openai")
|
||||
llm = LlmFactory.create(llm_provider, llm_config_data.get("config", {}))
|
||||
|
||||
db_provider = db_config_data.get("provider", "chroma")
|
||||
db = VectorDBFactory.create(db_provider, db_config_data.get("config", {}))
|
||||
|
||||
embedder_provider = embedding_model_config_data.get("provider", "openai")
|
||||
embedder = EmbedderFactory.create(embedder_provider, embedding_model_config_data.get("config", {}))
|
||||
return cls(config=app_config, llm=llm, db=db, embedder=embedder, chunker=chunker_config_data)
|
||||
@@ -1,7 +1,7 @@
|
||||
from typing import Any
|
||||
|
||||
from embedchain import Pipeline as App
|
||||
from embedchain.config import AddConfig, BaseLlmConfig, PipelineConfig
|
||||
from embedchain import App
|
||||
from embedchain.config import AddConfig, AppConfig, BaseLlmConfig
|
||||
from embedchain.embedder.openai import OpenAIEmbedder
|
||||
from embedchain.helpers.json_serializable import (JSONSerializable,
|
||||
register_deserializable)
|
||||
@@ -12,7 +12,7 @@ from embedchain.vectordb.chroma import ChromaDB
|
||||
@register_deserializable
|
||||
class BaseBot(JSONSerializable):
|
||||
def __init__(self):
|
||||
self.app = App(config=PipelineConfig(), llm=OpenAILlm(), db=ChromaDB(), embedding_model=OpenAIEmbedder())
|
||||
self.app = App(config=AppConfig(), llm=OpenAILlm(), db=ChromaDB(), embedding_model=OpenAIEmbedder())
|
||||
|
||||
def add(self, data: Any, config: AddConfig = None):
|
||||
"""
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
@@ -53,7 +53,7 @@ class PoeBot(BaseBot, PoeBot):
|
||||
answer = self.handle_message(last_message, history)
|
||||
yield self.text_event(answer)
|
||||
|
||||
def handle_message(self, message, history: Optional[List[str]] = None):
|
||||
def handle_message(self, message, history: Optional[list[str]] = None):
|
||||
if message.startswith("/add "):
|
||||
response = self.add_data(message)
|
||||
else:
|
||||
@@ -70,7 +70,7 @@ class PoeBot(BaseBot, PoeBot):
|
||||
# response = "Some error occurred while adding data."
|
||||
# return response
|
||||
|
||||
def ask_bot(self, message, history: List[str]):
|
||||
def ask_bot(self, message, history: list[str]):
|
||||
try:
|
||||
self.app.llm.set_history(history=history)
|
||||
response = self.query(message)
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import logging
|
||||
import os # noqa: F401
|
||||
from typing import Any
|
||||
|
||||
from gptcache import cache # noqa: F401
|
||||
from gptcache.adapter.adapter import adapt # noqa: F401
|
||||
from gptcache.config import Config # noqa: F401
|
||||
from gptcache.manager import get_data_manager
|
||||
from gptcache.manager.scalar_data.base import Answer
|
||||
from gptcache.manager.scalar_data.base import DataType as CacheDataType
|
||||
from gptcache.session import Session
|
||||
from gptcache.similarity_evaluation.distance import \
|
||||
SearchDistanceEvaluation # noqa: F401
|
||||
from gptcache.similarity_evaluation.exact_match import \
|
||||
ExactMatchEvaluation # noqa: F401
|
||||
|
||||
|
||||
def gptcache_pre_function(data: dict[str, Any], **params: dict[str, Any]):
|
||||
return data["input_query"]
|
||||
|
||||
|
||||
def gptcache_data_manager(vector_dimension):
|
||||
return get_data_manager(cache_base="sqlite", vector_base="chromadb", max_size=1000, eviction="LRU")
|
||||
|
||||
|
||||
def gptcache_data_convert(cache_data):
|
||||
logging.info("[Cache] Cache hit, returning cache data...")
|
||||
return cache_data
|
||||
|
||||
|
||||
def gptcache_update_cache_callback(llm_data, update_cache_func, *args, **kwargs):
|
||||
logging.info("[Cache] Cache missed, updating cache...")
|
||||
update_cache_func(Answer(llm_data, CacheDataType.STR))
|
||||
return llm_data
|
||||
|
||||
|
||||
def _gptcache_session_hit_func(cur_session_id: str, cache_session_ids: list, cache_questions: list, cache_answer: str):
|
||||
return cur_session_id in cache_session_ids
|
||||
|
||||
|
||||
def get_gptcache_session(session_id: str):
|
||||
return Session(name=session_id, check_hit_func=_gptcache_session_hit_func)
|
||||
@@ -17,7 +17,7 @@ class BaseChunker(JSONSerializable):
|
||||
"""
|
||||
Loads data and chunks it.
|
||||
|
||||
:param loader: The loader which's `load_data` method is used to create
|
||||
:param loader: The loader whose `load_data` method is used to create
|
||||
the raw data.
|
||||
:param src: The data to be handled by the loader. Can be a URL for
|
||||
remote sources or local content for local loaders.
|
||||
@@ -25,7 +25,7 @@ class BaseChunker(JSONSerializable):
|
||||
"""
|
||||
documents = []
|
||||
chunk_ids = []
|
||||
idMap = {}
|
||||
id_map = {}
|
||||
min_chunk_size = config.min_chunk_size if config is not None else 1
|
||||
logging.info(f"[INFO] Skipping chunks smaller than {min_chunk_size} characters")
|
||||
data_result = loader.load_data(src)
|
||||
@@ -49,8 +49,8 @@ class BaseChunker(JSONSerializable):
|
||||
for chunk in chunks:
|
||||
chunk_id = hashlib.sha256((chunk + url).encode()).hexdigest()
|
||||
chunk_id = f"{app_id}--{chunk_id}" if app_id is not None else chunk_id
|
||||
if idMap.get(chunk_id) is None and len(chunk) >= min_chunk_size:
|
||||
idMap[chunk_id] = True
|
||||
if id_map.get(chunk_id) is None and len(chunk) >= min_chunk_size:
|
||||
id_map[chunk_id] = True
|
||||
chunk_ids.append(chunk_id)
|
||||
documents.append(chunk)
|
||||
metadatas.append(meta_data)
|
||||
@@ -77,5 +77,6 @@ class BaseChunker(JSONSerializable):
|
||||
|
||||
# TODO: This should be done during initialization. This means it has to be done in the child classes.
|
||||
|
||||
def get_word_count(self, documents):
|
||||
@staticmethod
|
||||
def get_word_count(documents) -> int:
|
||||
return sum([len(document.split(" ")) for document in documents])
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
from typing import Optional
|
||||
|
||||
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
||||
|
||||
from embedchain.chunkers.base_chunker import BaseChunker
|
||||
from embedchain.config.add_config import ChunkerConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class GoogleDriveChunker(BaseChunker):
|
||||
"""Chunker for google drive folder."""
|
||||
|
||||
def __init__(self, config: Optional[ChunkerConfig] = None):
|
||||
if config is None:
|
||||
config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len)
|
||||
text_splitter = RecursiveCharacterTextSplitter(
|
||||
chunk_size=config.chunk_size,
|
||||
chunk_overlap=config.chunk_overlap,
|
||||
length_function=config.length_function,
|
||||
)
|
||||
super().__init__(text_splitter)
|
||||
@@ -0,0 +1,22 @@
|
||||
from typing import Optional
|
||||
|
||||
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
||||
|
||||
from embedchain.chunkers.base_chunker import BaseChunker
|
||||
from embedchain.config.add_config import ChunkerConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class ImageChunker(BaseChunker):
|
||||
"""Chunker for Images."""
|
||||
|
||||
def __init__(self, config: Optional[ChunkerConfig] = None):
|
||||
if config is None:
|
||||
config = ChunkerConfig(chunk_size=2000, chunk_overlap=0, length_function=len)
|
||||
text_splitter = RecursiveCharacterTextSplitter(
|
||||
chunk_size=config.chunk_size,
|
||||
chunk_overlap=config.chunk_overlap,
|
||||
length_function=config.length_function,
|
||||
)
|
||||
super().__init__(text_splitter)
|
||||
@@ -1,67 +0,0 @@
|
||||
import hashlib
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from langchain.text_splitter import RecursiveCharacterTextSplitter
|
||||
|
||||
from embedchain.chunkers.base_chunker import BaseChunker
|
||||
from embedchain.config.add_config import ChunkerConfig
|
||||
|
||||
|
||||
class ImagesChunker(BaseChunker):
|
||||
"""Chunker for an Image."""
|
||||
|
||||
def __init__(self, config: Optional[ChunkerConfig] = None):
|
||||
if config is None:
|
||||
config = ChunkerConfig(chunk_size=300, chunk_overlap=0, length_function=len)
|
||||
image_splitter = RecursiveCharacterTextSplitter(
|
||||
chunk_size=config.chunk_size,
|
||||
chunk_overlap=config.chunk_overlap,
|
||||
length_function=config.length_function,
|
||||
)
|
||||
super().__init__(image_splitter)
|
||||
|
||||
def create_chunks(self, loader, src, app_id=None, config: Optional[ChunkerConfig] = None):
|
||||
"""
|
||||
Loads the image(s), and creates their corresponding embedding. This creates one chunk for each image
|
||||
|
||||
:param loader: The loader whose `load_data` method is used to create
|
||||
the raw data.
|
||||
:param src: The data to be handled by the loader. Can be a URL for
|
||||
remote sources or local content for local loaders.
|
||||
"""
|
||||
documents = []
|
||||
embeddings = []
|
||||
ids = []
|
||||
min_chunk_size = config.min_chunk_size if config is not None else 0
|
||||
logging.info(f"[INFO] Skipping chunks smaller than {min_chunk_size} characters")
|
||||
data_result = loader.load_data(src)
|
||||
data_records = data_result["data"]
|
||||
doc_id = data_result["doc_id"]
|
||||
doc_id = f"{app_id}--{doc_id}" if app_id is not None else doc_id
|
||||
metadatas = []
|
||||
for data in data_records:
|
||||
meta_data = data["meta_data"]
|
||||
# add data type to meta data to allow query using data type
|
||||
meta_data["data_type"] = self.data_type.value
|
||||
chunk_id = hashlib.sha256(meta_data["url"].encode()).hexdigest()
|
||||
ids.append(chunk_id)
|
||||
documents.append(data["content"])
|
||||
embeddings.append(data["embedding"])
|
||||
meta_data["doc_id"] = doc_id
|
||||
metadatas.append(meta_data)
|
||||
|
||||
return {
|
||||
"documents": documents,
|
||||
"embeddings": embeddings,
|
||||
"ids": ids,
|
||||
"metadatas": metadatas,
|
||||
"doc_id": doc_id,
|
||||
}
|
||||
|
||||
def get_word_count(self, documents):
|
||||
"""
|
||||
The number of chunks and the corresponding word count for an image is fixed to 1, as 1 embedding is created for
|
||||
each image
|
||||
"""
|
||||
return 1
|
||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
||||
|
||||
from embedchain.chunkers.base_chunker import BaseChunker
|
||||
from embedchain.config.add_config import ChunkerConfig
|
||||
from embedchain.helper.json_serializable import register_deserializable
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
|
||||
@register_deserializable
|
||||
|
||||
@@ -1,16 +1,45 @@
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import signal
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
import click
|
||||
import pkg_resources
|
||||
import requests
|
||||
from rich.console import Console
|
||||
|
||||
from embedchain.telemetry.posthog import AnonymousTelemetry
|
||||
from embedchain.utils.cli import (deploy_fly, deploy_gradio_app,
|
||||
deploy_hf_spaces, deploy_modal,
|
||||
deploy_render, deploy_streamlit,
|
||||
get_pkg_path_from_name, setup_fly_io_app,
|
||||
setup_gradio_app, setup_hf_app,
|
||||
setup_modal_com_app, setup_render_com_app,
|
||||
setup_streamlit_io_app)
|
||||
|
||||
console = Console()
|
||||
api_process = None
|
||||
ui_process = None
|
||||
|
||||
anonymous_telemetry = AnonymousTelemetry()
|
||||
|
||||
|
||||
def signal_handler(sig, frame):
|
||||
"""Signal handler to catch termination signals and kill server processes."""
|
||||
global api_process, ui_process
|
||||
console.print("\n🛑 [bold yellow]Stopping servers...[/bold yellow]")
|
||||
if api_process:
|
||||
api_process.terminate()
|
||||
console.print("🛑 [bold yellow]API server stopped.[/bold yellow]")
|
||||
if ui_process:
|
||||
ui_process.terminate()
|
||||
console.print("🛑 [bold yellow]UI server stopped.[/bold yellow]")
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
@click.group()
|
||||
@@ -18,89 +47,130 @@ def cli():
|
||||
pass
|
||||
|
||||
|
||||
anonymous_telemetry = AnonymousTelemetry()
|
||||
|
||||
|
||||
def get_pkg_path_from_name(template: str):
|
||||
try:
|
||||
# Determine the installation location of the embedchain package
|
||||
package_path = pkg_resources.resource_filename("embedchain", "")
|
||||
except ImportError:
|
||||
console.print("❌ [bold red]Failed to locate the 'embedchain' package. Is it installed?[/bold red]")
|
||||
@cli.command()
|
||||
@click.argument("app_name")
|
||||
@click.option("--docker", is_flag=True, help="Use docker to create the app.")
|
||||
@click.pass_context
|
||||
def create_app(ctx, app_name, docker):
|
||||
if Path(app_name).exists():
|
||||
console.print(
|
||||
f"❌ [red]Directory '{app_name}' already exists. Try using a new directory name, or remove it.[/red]"
|
||||
)
|
||||
return
|
||||
|
||||
# Construct the source path from the embedchain package
|
||||
src_path = os.path.join(package_path, "deployment", template)
|
||||
os.makedirs(app_name)
|
||||
os.chdir(app_name)
|
||||
|
||||
if not os.path.exists(src_path):
|
||||
console.print(f"❌ [bold red]Template '{template}' not found.[/bold red]")
|
||||
# Step 1: Download the zip file
|
||||
zip_url = "http://github.com/embedchain/ec-admin/archive/main.zip"
|
||||
console.print(f"Creating a new embedchain app in [green]{Path().resolve()}[/green]\n")
|
||||
try:
|
||||
response = requests.get(zip_url)
|
||||
response.raise_for_status()
|
||||
with tempfile.NamedTemporaryFile(delete=False) as tmp_file:
|
||||
tmp_file.write(response.content)
|
||||
zip_file_path = tmp_file.name
|
||||
console.print("✅ [bold green]Fetched template successfully.[/bold green]")
|
||||
except requests.RequestException as e:
|
||||
console.print(f"❌ [bold red]Failed to download zip file: {e}[/bold red]")
|
||||
anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": False})
|
||||
return
|
||||
|
||||
return src_path
|
||||
|
||||
|
||||
def setup_fly_io_app(extra_args):
|
||||
fly_launch_command = ["fly", "launch", "--region", "sjc", "--no-deploy"] + list(extra_args)
|
||||
# Step 2: Extract the zip file
|
||||
try:
|
||||
console.print(f"🚀 [bold cyan]Running: {' '.join(fly_launch_command)}[/bold cyan]")
|
||||
shutil.move(".env.example", ".env")
|
||||
subprocess.run(fly_launch_command, check=True)
|
||||
console.print("✅ [bold green]'fly launch' executed successfully.[/bold green]")
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
|
||||
except FileNotFoundError:
|
||||
console.print(
|
||||
"❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]"
|
||||
)
|
||||
with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
|
||||
# Get the name of the root directory inside the zip file
|
||||
root_dir = Path(zip_ref.namelist()[0])
|
||||
for member in zip_ref.infolist():
|
||||
# Build the path to extract the file to, skipping the root directory
|
||||
target_file = Path(member.filename).relative_to(root_dir)
|
||||
source_file = zip_ref.open(member, "r")
|
||||
if member.is_dir():
|
||||
# Create directory if it doesn't exist
|
||||
os.makedirs(target_file, exist_ok=True)
|
||||
else:
|
||||
with open(target_file, "wb") as file:
|
||||
# Write the file
|
||||
shutil.copyfileobj(source_file, file)
|
||||
console.print("✅ [bold green]Extracted zip file successfully.[/bold green]")
|
||||
anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": True})
|
||||
except zipfile.BadZipFile:
|
||||
console.print("❌ [bold red]Error in extracting zip file. The file might be corrupted.[/bold red]")
|
||||
anonymous_telemetry.capture(event_name="ec_create_app", properties={"success": False})
|
||||
return
|
||||
|
||||
|
||||
def setup_modal_com_app(extra_args):
|
||||
modal_setup_file = os.path.join(os.path.expanduser("~"), ".modal.toml")
|
||||
if os.path.exists(modal_setup_file):
|
||||
console.print(
|
||||
"""✅ [bold green]Modal setup already done. You can now install the dependencies by doing \n
|
||||
`pip install -r requirements.txt`[/bold green]"""
|
||||
)
|
||||
if docker:
|
||||
subprocess.run(["docker-compose", "build"], check=True)
|
||||
else:
|
||||
modal_setup_cmd = ["modal", "setup"] + list(extra_args)
|
||||
console.print(f"🚀 [bold cyan]Running: {' '.join(modal_setup_cmd)}[/bold cyan]")
|
||||
subprocess.run(modal_setup_cmd, check=True)
|
||||
shutil.move(".env.example", ".env")
|
||||
console.print(
|
||||
"""Great! Now you can install the dependencies by doing: \n
|
||||
`pip install -r requirements.txt`\n
|
||||
\n
|
||||
To run your app locally:\n
|
||||
`ec dev`
|
||||
"""
|
||||
)
|
||||
ctx.invoke(install_reqs)
|
||||
|
||||
|
||||
def setup_render_com_app():
|
||||
render_setup_file = os.path.join(os.path.expanduser("~"), ".render/config.yaml")
|
||||
if os.path.exists(render_setup_file):
|
||||
console.print(
|
||||
"""✅ [bold green]Render setup already done. You can now install the dependencies by doing \n
|
||||
`pip install -r requirements.txt`[/bold green]"""
|
||||
)
|
||||
else:
|
||||
render_setup_cmd = ["render", "config", "init"]
|
||||
console.print(f"🚀 [bold cyan]Running: {' '.join(render_setup_cmd)}[/bold cyan]")
|
||||
subprocess.run(render_setup_cmd, check=True)
|
||||
shutil.move(".env.example", ".env")
|
||||
console.print(
|
||||
"""Great! Now you can install the dependencies by doing: \n
|
||||
`pip install -r requirements.txt`\n
|
||||
\n
|
||||
To run your app locally:\n
|
||||
`ec dev`
|
||||
"""
|
||||
)
|
||||
@cli.command()
|
||||
def install_reqs():
|
||||
try:
|
||||
console.print("Installing python requirements...\n")
|
||||
time.sleep(2)
|
||||
os.chdir("api")
|
||||
subprocess.run(["pip", "install", "-r", "requirements.txt"], check=True)
|
||||
os.chdir("..")
|
||||
console.print("\n ✅ [bold green]Installed API requirements successfully.[/bold green]\n")
|
||||
except Exception as e:
|
||||
console.print(f"❌ [bold red]Failed to install API requirements: {e}[/bold red]")
|
||||
anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": False})
|
||||
return
|
||||
|
||||
try:
|
||||
os.chdir("ui")
|
||||
subprocess.run(["yarn"], check=True)
|
||||
console.print("\n✅ [bold green]Successfully installed frontend requirements.[/bold green]")
|
||||
anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": True})
|
||||
except Exception as e:
|
||||
console.print(f"❌ [bold red]Failed to install frontend requirements. Error: {e}[/bold red]")
|
||||
anonymous_telemetry.capture(event_name="ec_install_reqs", properties={"success": False})
|
||||
|
||||
|
||||
def setup_streamlit_io_app():
|
||||
# nothing needs to be done here
|
||||
console.print("Great! Now you can install the dependencies by doing `pip install -r requirements.txt`")
|
||||
@cli.command()
|
||||
@click.option("--docker", is_flag=True, help="Run inside docker.")
|
||||
def start(docker):
|
||||
if docker:
|
||||
subprocess.run(["docker-compose", "up"], check=True)
|
||||
return
|
||||
|
||||
# Set up signal handling
|
||||
signal.signal(signal.SIGINT, signal_handler)
|
||||
signal.signal(signal.SIGTERM, signal_handler)
|
||||
|
||||
# Step 1: Start the API server
|
||||
try:
|
||||
os.chdir("api")
|
||||
api_process = subprocess.Popen(["python", "-m", "main"], stdout=None, stderr=None)
|
||||
os.chdir("..")
|
||||
console.print("✅ [bold green]API server started successfully.[/bold green]")
|
||||
except Exception as e:
|
||||
console.print(f"❌ [bold red]Failed to start the API server: {e}[/bold red]")
|
||||
anonymous_telemetry.capture(event_name="ec_start", properties={"success": False})
|
||||
return
|
||||
|
||||
# Sleep for 2 seconds to give the user time to read the message
|
||||
time.sleep(2)
|
||||
|
||||
# Step 2: Install UI requirements and start the UI server
|
||||
try:
|
||||
os.chdir("ui")
|
||||
subprocess.run(["yarn"], check=True)
|
||||
ui_process = subprocess.Popen(["yarn", "dev"])
|
||||
console.print("✅ [bold green]UI server started successfully.[/bold green]")
|
||||
anonymous_telemetry.capture(event_name="ec_start", properties={"success": True})
|
||||
except Exception as e:
|
||||
console.print(f"❌ [bold red]Failed to start the UI server: {e}[/bold red]")
|
||||
anonymous_telemetry.capture(event_name="ec_start", properties={"success": False})
|
||||
|
||||
# Keep the script running until it receives a kill signal
|
||||
try:
|
||||
api_process.wait()
|
||||
ui_process.wait()
|
||||
except KeyboardInterrupt:
|
||||
console.print("\n🛑 [bold yellow]Stopping server...[/bold yellow]")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@@ -108,7 +178,10 @@ def setup_streamlit_io_app():
|
||||
@click.argument("extra_args", nargs=-1, type=click.UNPROCESSED)
|
||||
def create(template, extra_args):
|
||||
anonymous_telemetry.capture(event_name="ec_create", properties={"template_used": template})
|
||||
src_path = get_pkg_path_from_name(template)
|
||||
template_dir = template
|
||||
if "/" in template_dir:
|
||||
template_dir = template.split("/")[1]
|
||||
src_path = get_pkg_path_from_name(template_dir)
|
||||
shutil.copytree(src_path, os.getcwd(), dirs_exist_ok=True)
|
||||
console.print(f"✅ [bold green]Successfully created app from template '{template}'.[/bold green]")
|
||||
|
||||
@@ -120,6 +193,10 @@ def create(template, extra_args):
|
||||
setup_render_com_app()
|
||||
elif template == "streamlit.io":
|
||||
setup_streamlit_io_app()
|
||||
elif template == "gradio.app":
|
||||
setup_gradio_app()
|
||||
elif template == "hf/gradio.app" or template == "hf/streamlit.io":
|
||||
setup_hf_app()
|
||||
else:
|
||||
raise ValueError(f"Unknown template '{template}'.")
|
||||
|
||||
@@ -187,6 +264,17 @@ def run_dev_render_com(debug, host, port):
|
||||
console.print("\n🛑 [bold yellow]FastAPI server stopped[/bold yellow]")
|
||||
|
||||
|
||||
def run_dev_gradio():
|
||||
gradio_run_cmd = ["gradio", "app.py"]
|
||||
try:
|
||||
console.print(f"🚀 [bold cyan]Running Gradio app with command: {' '.join(gradio_run_cmd)}[/bold cyan]")
|
||||
subprocess.run(gradio_run_cmd, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
|
||||
except KeyboardInterrupt:
|
||||
console.print("\n🛑 [bold yellow]Gradio server stopped[/bold yellow]")
|
||||
|
||||
|
||||
@cli.command()
|
||||
@click.option("--debug", is_flag=True, help="Enable or disable debug mode.")
|
||||
@click.option("--host", default="127.0.0.1", help="The host address to run the FastAPI app on.")
|
||||
@@ -204,124 +292,22 @@ def dev(debug, host, port):
|
||||
run_dev_modal_com()
|
||||
elif template == "render.com":
|
||||
run_dev_render_com(debug, host, port)
|
||||
elif template == "streamlit.io":
|
||||
elif template == "streamlit.io" or template == "hf/streamlit.app":
|
||||
run_dev_streamlit_io()
|
||||
elif template == "gradio.app" or template == "hf/gradio.app":
|
||||
run_dev_gradio()
|
||||
else:
|
||||
raise ValueError(f"Unknown template '{template}'.")
|
||||
|
||||
|
||||
def read_env_file(env_file_path):
|
||||
"""
|
||||
Reads an environment file and returns a dictionary of key-value pairs.
|
||||
|
||||
Args:
|
||||
env_file_path (str): The path to the .env file.
|
||||
|
||||
Returns:
|
||||
dict: Dictionary of environment variables.
|
||||
"""
|
||||
env_vars = {}
|
||||
with open(env_file_path, "r") as file:
|
||||
for line in file:
|
||||
# Ignore comments and empty lines
|
||||
if line.strip() and not line.strip().startswith("#"):
|
||||
# Assume each line is in the format KEY=VALUE
|
||||
key_value_match = re.match(r"(\w+)=(.*)", line.strip())
|
||||
if key_value_match:
|
||||
key, value = key_value_match.groups()
|
||||
env_vars[key] = value
|
||||
return env_vars
|
||||
|
||||
|
||||
def deploy_fly():
|
||||
app_name = ""
|
||||
with open("fly.toml", "r") as file:
|
||||
for line in file:
|
||||
if line.strip().startswith("app ="):
|
||||
app_name = line.split("=")[1].strip().strip('"')
|
||||
|
||||
if not app_name:
|
||||
console.print("❌ [bold red]App name not found in fly.toml[/bold red]")
|
||||
return
|
||||
|
||||
env_vars = read_env_file(".env")
|
||||
secrets_command = ["flyctl", "secrets", "set", "-a", app_name] + [f"{k}={v}" for k, v in env_vars.items()]
|
||||
|
||||
deploy_command = ["fly", "deploy"]
|
||||
try:
|
||||
# Set secrets
|
||||
console.print(f"🔐 [bold cyan]Setting secrets for {app_name}[/bold cyan]")
|
||||
subprocess.run(secrets_command, check=True)
|
||||
|
||||
# Deploy application
|
||||
console.print(f"🚀 [bold cyan]Running: {' '.join(deploy_command)}[/bold cyan]")
|
||||
subprocess.run(deploy_command, check=True)
|
||||
console.print("✅ [bold green]'fly deploy' executed successfully.[/bold green]")
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
|
||||
except FileNotFoundError:
|
||||
console.print(
|
||||
"❌ [bold red]'fly' command not found. Please ensure Fly CLI is installed and in your PATH.[/bold red]"
|
||||
)
|
||||
|
||||
|
||||
def deploy_modal():
|
||||
modal_deploy_cmd = ["modal", "deploy", "app"]
|
||||
try:
|
||||
console.print(f"🚀 [bold cyan]Running: {' '.join(modal_deploy_cmd)}[/bold cyan]")
|
||||
subprocess.run(modal_deploy_cmd, check=True)
|
||||
console.print("✅ [bold green]'modal deploy' executed successfully.[/bold green]")
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
|
||||
except FileNotFoundError:
|
||||
console.print(
|
||||
"❌ [bold red]'modal' command not found. Please ensure Modal CLI is installed and in your PATH.[/bold red]"
|
||||
)
|
||||
|
||||
|
||||
def deploy_streamlit():
|
||||
streamlit_deploy_cmd = ["streamlit", "run", "app.py"]
|
||||
try:
|
||||
console.print(f"🚀 [bold cyan]Running: {' '.join(streamlit_deploy_cmd)}[/bold cyan]")
|
||||
console.print(
|
||||
"""\n\n✅ [bold yellow]To deploy a streamlit app, you can directly it from the UI.\n
|
||||
Click on the 'Deploy' button on the top right corner of the app.\n
|
||||
For more information, please refer to https://docs.embedchain.ai/deployment/streamlit_io
|
||||
[/bold yellow]
|
||||
\n\n"""
|
||||
)
|
||||
subprocess.run(streamlit_deploy_cmd, check=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
|
||||
except FileNotFoundError:
|
||||
console.print(
|
||||
"""❌ [bold red]'streamlit' command not found.\n
|
||||
Please ensure Streamlit CLI is installed and in your PATH.[/bold red]"""
|
||||
)
|
||||
|
||||
|
||||
def deploy_render():
|
||||
render_deploy_cmd = ["render", "blueprint", "launch"]
|
||||
|
||||
try:
|
||||
console.print(f"🚀 [bold cyan]Running: {' '.join(render_deploy_cmd)}[/bold cyan]")
|
||||
subprocess.run(render_deploy_cmd, check=True)
|
||||
console.print("✅ [bold green]'render blueprint launch' executed successfully.[/bold green]")
|
||||
except subprocess.CalledProcessError as e:
|
||||
console.print(f"❌ [bold red]An error occurred: {e}[/bold red]")
|
||||
except FileNotFoundError:
|
||||
console.print(
|
||||
"❌ [bold red]'render' command not found. Please ensure Render CLI is installed and in your PATH.[/bold red]"
|
||||
)
|
||||
|
||||
|
||||
@cli.command()
|
||||
def deploy():
|
||||
# Check for platform-specific files
|
||||
template = ""
|
||||
ec_app_name = ""
|
||||
with open("embedchain.json", "r") as file:
|
||||
embedchain_config = json.load(file)
|
||||
ec_app_name = embedchain_config["name"] if "name" in embedchain_config else None
|
||||
template = embedchain_config["provider"]
|
||||
|
||||
anonymous_telemetry.capture(event_name="ec_deploy", properties={"template_used": template})
|
||||
@@ -333,5 +319,9 @@ def deploy():
|
||||
deploy_render()
|
||||
elif template == "streamlit.io":
|
||||
deploy_streamlit()
|
||||
elif template == "gradio.app":
|
||||
deploy_gradio_app()
|
||||
elif template.startswith("hf/"):
|
||||
deploy_hf_spaces(ec_app_name)
|
||||
else:
|
||||
console.print("❌ [bold red]No recognized deployment platform found.[/bold red]")
|
||||
|
||||
@@ -31,7 +31,7 @@ class Client:
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def setup_dir(self):
|
||||
def setup_dir(cls):
|
||||
"""
|
||||
Loads the user id from the config file if it exists, otherwise generates a new
|
||||
one and saves it to the config file.
|
||||
@@ -39,9 +39,7 @@ class Client:
|
||||
:return: user id
|
||||
:rtype: str
|
||||
"""
|
||||
if not os.path.exists(CONFIG_DIR):
|
||||
os.makedirs(CONFIG_DIR)
|
||||
|
||||
os.makedirs(CONFIG_DIR, exist_ok=True)
|
||||
if os.path.exists(CONFIG_FILE):
|
||||
with open(CONFIG_FILE, "r") as f:
|
||||
data = json.load(f)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
# flake8: noqa: F401
|
||||
|
||||
from .add_config import AddConfig, ChunkerConfig
|
||||
from .apps.app_config import AppConfig
|
||||
from .app_config import AppConfig
|
||||
from .base_config import BaseConfig
|
||||
from .cache_config import CacheConfig
|
||||
from .embedder.base import BaseEmbedderConfig
|
||||
from .embedder.base import BaseEmbedderConfig as EmbedderConfig
|
||||
from .llm.base import BaseLlmConfig
|
||||
from .pipeline_config import PipelineConfig
|
||||
from .vectordb.chroma import ChromaDbConfig
|
||||
from .vectordb.elasticsearch import ElasticsearchDBConfig
|
||||
from .vectordb.opensearch import OpenSearchDBConfig
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import builtins
|
||||
import logging
|
||||
from collections.abc import Callable
|
||||
from importlib import import_module
|
||||
from typing import Callable, Optional
|
||||
from typing import Optional
|
||||
|
||||
from embedchain.config.base_config import BaseConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
@@ -26,7 +27,7 @@ class ChunkerConfig(BaseConfig):
|
||||
if self.min_chunk_size >= self.chunk_size:
|
||||
raise ValueError(f"min_chunk_size {min_chunk_size} should be less than chunk_size {chunk_size}")
|
||||
if self.min_chunk_size < self.chunk_overlap:
|
||||
logging.warn(
|
||||
logging.warning(
|
||||
f"min_chunk_size {min_chunk_size} should be greater than chunk_overlap {chunk_overlap}, otherwise it is redundant." # noqa:E501
|
||||
)
|
||||
|
||||
@@ -35,7 +36,8 @@ class ChunkerConfig(BaseConfig):
|
||||
else:
|
||||
self.length_function = length_function if length_function else len
|
||||
|
||||
def load_func(self, dotpath: str):
|
||||
@staticmethod
|
||||
def load_func(dotpath: str):
|
||||
if "." not in dotpath:
|
||||
return getattr(builtins, dotpath)
|
||||
else:
|
||||
|
||||
@@ -15,8 +15,9 @@ class AppConfig(BaseAppConfig):
|
||||
self,
|
||||
log_level: str = "WARNING",
|
||||
id: Optional[str] = None,
|
||||
name: Optional[str] = None,
|
||||
collect_metrics: Optional[bool] = True,
|
||||
collection_name: Optional[str] = None,
|
||||
**kwargs,
|
||||
):
|
||||
"""
|
||||
Initializes a configuration class instance for an App. This is the simplest form of an embedchain app.
|
||||
@@ -28,8 +29,6 @@ class AppConfig(BaseAppConfig):
|
||||
:type id: Optional[str], optional
|
||||
:param collect_metrics: Send anonymous telemetry to improve embedchain, defaults to True
|
||||
:type collect_metrics: Optional[bool], optional
|
||||
:param collection_name: Default collection name. It's recommended to use app.db.set_collection_name() instead,
|
||||
defaults to None
|
||||
:type collection_name: Optional[str], optional
|
||||
"""
|
||||
super().__init__(log_level=log_level, id=id, collect_metrics=collect_metrics, collection_name=collection_name)
|
||||
self.name = name
|
||||
super().__init__(log_level=log_level, id=id, collect_metrics=collect_metrics, **kwargs)
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from embedchain.helpers.json_serializable import JSONSerializable
|
||||
|
||||
@@ -12,10 +12,10 @@ class BaseConfig(JSONSerializable):
|
||||
"""Initializes a configuration class for a class."""
|
||||
pass
|
||||
|
||||
def as_dict(self) -> Dict[str, Any]:
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
"""Return config object as a dict
|
||||
|
||||
:return: config object as dict
|
||||
:rtype: Dict[str, Any]
|
||||
:rtype: dict[str, Any]
|
||||
"""
|
||||
return vars(self)
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
from typing import Any, Optional
|
||||
|
||||
from embedchain.config.base_config import BaseConfig
|
||||
from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class CacheSimilarityEvalConfig(BaseConfig):
|
||||
"""
|
||||
This is the evaluator to compare two embeddings according to their distance computed in embedding retrieval stage.
|
||||
In the retrieval stage, `search_result` is the distance used for approximate nearest neighbor search and have been
|
||||
put into `cache_dict`. `max_distance` is used to bound this distance to make it between [0-`max_distance`].
|
||||
`positive` is used to indicate this distance is directly proportional to the similarity of two entities.
|
||||
If `positive` is set `False`, `max_distance` will be used to subtract this distance to get the final score.
|
||||
|
||||
:param max_distance: the bound of maximum distance.
|
||||
:type max_distance: float
|
||||
:param positive: if the larger distance indicates more similar of two entities, It is True. Otherwise, it is False.
|
||||
:type positive: bool
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
strategy: Optional[str] = "distance",
|
||||
max_distance: Optional[float] = 1.0,
|
||||
positive: Optional[bool] = False,
|
||||
):
|
||||
self.strategy = strategy
|
||||
self.max_distance = max_distance
|
||||
self.positive = positive
|
||||
|
||||
@staticmethod
|
||||
def from_config(config: Optional[dict[str, Any]]):
|
||||
if config is None:
|
||||
return CacheSimilarityEvalConfig()
|
||||
else:
|
||||
return CacheSimilarityEvalConfig(
|
||||
strategy=config.get("strategy", "distance"),
|
||||
max_distance=config.get("max_distance", 1.0),
|
||||
positive=config.get("positive", False),
|
||||
)
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class CacheInitConfig(BaseConfig):
|
||||
"""
|
||||
This is a cache init config. Used to initialize a cache.
|
||||
|
||||
:param similarity_threshold: a threshold ranged from 0 to 1 to filter search results with similarity score higher \
|
||||
than the threshold. When it is 0, there is no hits. When it is 1, all search results will be returned as hits.
|
||||
:type similarity_threshold: float
|
||||
:param auto_flush: it will be automatically flushed every time xx pieces of data are added, default to 20
|
||||
:type auto_flush: int
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
similarity_threshold: Optional[float] = 0.8,
|
||||
auto_flush: Optional[int] = 20,
|
||||
):
|
||||
if similarity_threshold < 0 or similarity_threshold > 1:
|
||||
raise ValueError(f"similarity_threshold {similarity_threshold} should be between 0 and 1")
|
||||
|
||||
self.similarity_threshold = similarity_threshold
|
||||
self.auto_flush = auto_flush
|
||||
|
||||
@staticmethod
|
||||
def from_config(config: Optional[dict[str, Any]]):
|
||||
if config is None:
|
||||
return CacheInitConfig()
|
||||
else:
|
||||
return CacheInitConfig(
|
||||
similarity_threshold=config.get("similarity_threshold", 0.8),
|
||||
auto_flush=config.get("auto_flush", 20),
|
||||
)
|
||||
|
||||
|
||||
@register_deserializable
|
||||
class CacheConfig(BaseConfig):
|
||||
def __init__(
|
||||
self,
|
||||
similarity_eval_config: Optional[CacheSimilarityEvalConfig] = CacheSimilarityEvalConfig(),
|
||||
init_config: Optional[CacheInitConfig] = CacheInitConfig(),
|
||||
):
|
||||
self.similarity_eval_config = similarity_eval_config
|
||||
self.init_config = init_config
|
||||
|
||||
@staticmethod
|
||||
def from_config(config: Optional[dict[str, Any]]):
|
||||
if config is None:
|
||||
return CacheConfig()
|
||||
else:
|
||||
return CacheConfig(
|
||||
similarity_eval_config=CacheSimilarityEvalConfig.from_config(config.get("similarity_evaluation", {})),
|
||||
init_config=CacheInitConfig.from_config(config.get("init_config", {})),
|
||||
)
|
||||
@@ -5,7 +5,9 @@ from embedchain.helpers.json_serializable import register_deserializable
|
||||
|
||||
@register_deserializable
|
||||
class BaseEmbedderConfig:
|
||||
def __init__(self, model: Optional[str] = None, deployment_name: Optional[str] = None):
|
||||
def __init__(
|
||||
self, model: Optional[str] = None, deployment_name: Optional[str] = None, api_key: Optional[str] = None
|
||||
):
|
||||
"""
|
||||
Initialize a new instance of an embedder config class.
|
||||
|
||||
@@ -16,3 +18,4 @@ class BaseEmbedderConfig:
|
||||
"""
|
||||
self.model = model
|
||||
self.deployment_name = deployment_name
|
||||
self.api_key = api_key
|
||||
|
||||