Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b02e8feeda | ||
|
|
406c46e7f4 | ||
|
|
e35eaf1bfc | ||
|
|
38426a7af1 | ||
|
|
141a23fb1e | ||
|
|
bb28569abf | ||
|
|
1df46b2bb3 | ||
|
|
58f72e1ffe | ||
|
|
33409140b4 | ||
|
|
f6b80e01a1 | ||
|
|
798d3fcc5a | ||
|
|
85f3ac428b | ||
|
|
9fcf2130b5 | ||
|
|
51df00729e | ||
|
|
023a61446f | ||
|
|
e0b73e6a5a | ||
|
|
28460f725c | ||
|
|
c93e49d2b8 | ||
|
|
07fb6bee54 | ||
|
|
3fa7db8420 | ||
|
|
c14bd7b73b | ||
|
|
5201beaab0 | ||
|
|
122313d8a5 | ||
|
|
82fd595306 | ||
|
|
95c0d47236 | ||
|
|
919cc74e94 | ||
|
|
d839991acb | ||
|
|
539286aafd | ||
|
|
23522b7b55 | ||
|
|
bf3fac56e4 | ||
|
|
a5bf8e9075 | ||
|
|
1d31b8f7e4 | ||
|
|
b144c7dccc | ||
|
|
1364975396 | ||
|
|
deaa7f50f8 | ||
|
|
744ab5156f | ||
|
|
c45413969a | ||
|
|
b314e5e080 | ||
|
|
17129e2eaa | ||
|
|
654fd8d74c | ||
|
|
9d3568ef75 | ||
|
|
14712cac88 | ||
|
|
0d568c758b | ||
|
|
7c6b88c7c5 | ||
|
|
32c93be46e | ||
|
|
7de8d85199 |
@@ -3,7 +3,15 @@ name: ci
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- 'embedchain/**'
|
||||||
|
- 'tests/**'
|
||||||
|
- 'examples/**'
|
||||||
pull_request:
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'embedchain/**'
|
||||||
|
- 'tests/**'
|
||||||
|
- 'examples/**'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|||||||
@@ -23,4 +23,3 @@ embedder:
|
|||||||
provider: openai
|
provider: openai
|
||||||
config:
|
config:
|
||||||
model: 'text-embedding-ada-002'
|
model: 'text-embedding-ada-002'
|
||||||
deployment_name: 'test-deployment'
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
llm:
|
||||||
|
provider: openai
|
||||||
|
config:
|
||||||
|
model: 'gpt-4'
|
||||||
|
temperature: 0.5
|
||||||
|
max_tokens: 1000
|
||||||
|
top_p: 1
|
||||||
|
stream: false
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
app:
|
app:
|
||||||
config:
|
config:
|
||||||
id: 'my-app'
|
id: 'my-app'
|
||||||
log_level: 'WARN'
|
log_level: 'WARNING'
|
||||||
collect_metrics: true
|
collect_metrics: true
|
||||||
collection_name: 'my-app'
|
collection_name: 'my-app'
|
||||||
|
|
||||||
@@ -30,4 +30,4 @@ embedder:
|
|||||||
provider: openai
|
provider: openai
|
||||||
config:
|
config:
|
||||||
model: 'text-embedding-ada-002'
|
model: 'text-embedding-ada-002'
|
||||||
deployment_name: null
|
deployment_name: 'my-app'
|
||||||
|
|||||||
+121
-20
@@ -6,15 +6,16 @@ Embedchain is made to work out of the box. However, for advanced users we're als
|
|||||||
|
|
||||||
You can configure different components of your app (`llm`, `embedding model`, or `vector database`) through a simple yaml configuration that Embedchain offers. Here is a generic full-stack example of the yaml config:
|
You can configure different components of your app (`llm`, `embedding model`, or `vector database`) through a simple yaml configuration that Embedchain offers. Here is a generic full-stack example of the yaml config:
|
||||||
|
|
||||||
```yaml
|
|
||||||
|
<Tip>
|
||||||
|
Embedchain applications are configurable using YAML file, JSON file or by directly passing the config dictionary.
|
||||||
|
</Tip>
|
||||||
|
|
||||||
|
<CodeGroup>
|
||||||
|
```yaml config.yaml
|
||||||
app:
|
app:
|
||||||
config:
|
config:
|
||||||
id: 'full-stack-app'
|
name: 'full-stack-app'
|
||||||
|
|
||||||
chunker:
|
|
||||||
chunk_size: 100
|
|
||||||
chunk_overlap: 20
|
|
||||||
length_function: 'len'
|
|
||||||
|
|
||||||
llm:
|
llm:
|
||||||
provider: openai
|
provider: openai
|
||||||
@@ -47,38 +48,138 @@ embedder:
|
|||||||
provider: openai
|
provider: openai
|
||||||
config:
|
config:
|
||||||
model: 'text-embedding-ada-002'
|
model: 'text-embedding-ada-002'
|
||||||
|
|
||||||
|
chunker:
|
||||||
|
chunk_size: 2000
|
||||||
|
chunk_overlap: 100
|
||||||
|
length_function: 'len'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```json config.json
|
||||||
|
{
|
||||||
|
"app": {
|
||||||
|
"config": {
|
||||||
|
"name": "full-stack-app"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"llm": {
|
||||||
|
"provider": "openai",
|
||||||
|
"config": {
|
||||||
|
"model": "gpt-3.5-turbo",
|
||||||
|
"temperature": 0.5,
|
||||||
|
"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."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vectordb": {
|
||||||
|
"provider": "chroma",
|
||||||
|
"config": {
|
||||||
|
"collection_name": "full-stack-app",
|
||||||
|
"dir": "db",
|
||||||
|
"allow_reset": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"embedder": {
|
||||||
|
"provider": "openai",
|
||||||
|
"config": {
|
||||||
|
"model": "text-embedding-ada-002"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"chunker": {
|
||||||
|
"chunk_size": 2000,
|
||||||
|
"chunk_overlap": 100,
|
||||||
|
"length_function": "len"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```python config.py
|
||||||
|
config = {
|
||||||
|
'app': {
|
||||||
|
'config': {
|
||||||
|
'name': 'full-stack-app'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'llm': {
|
||||||
|
'provider': 'openai',
|
||||||
|
'config': {
|
||||||
|
'model': 'gpt-3.5-turbo',
|
||||||
|
'temperature': 0.5,
|
||||||
|
'max_tokens': 1000,
|
||||||
|
'top_p': 1,
|
||||||
|
'stream': False,
|
||||||
|
'template': (
|
||||||
|
"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."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'vectordb': {
|
||||||
|
'provider': 'chroma',
|
||||||
|
'config': {
|
||||||
|
'collection_name': 'full-stack-app',
|
||||||
|
'dir': 'db',
|
||||||
|
'allow_reset': True
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'embedder': {
|
||||||
|
'provider': 'openai',
|
||||||
|
'config': {
|
||||||
|
'model': 'text-embedding-ada-002'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'chunker': {
|
||||||
|
'chunk_size': 2000,
|
||||||
|
'chunk_overlap': 100,
|
||||||
|
'length_function': 'len'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
Alright, let's dive into what each key means in the yaml config above:
|
Alright, let's dive into what each key means in the yaml config above:
|
||||||
|
|
||||||
1. `app` Section:
|
1. `app` Section:
|
||||||
- `config`:
|
- `config`:
|
||||||
- `id` (String): The ID or name of your full-stack application.
|
- `name` (String): The name of your full-stack application.
|
||||||
2. `chunker` Section:
|
- `id` (String): The id of your full-stack application.
|
||||||
- `chunk_size` (Integer): The size of each chunk of text that is sent to the language model.
|
<Note>Only use this to reload already created apps. We recommend users to not create their own ids.</Note>
|
||||||
- `chunk_overlap` (Integer): The amount of overlap between each chunk of text.
|
- `collect_metrics` (Boolean): Indicates whether metrics should be collected for the app, defaults to `True`
|
||||||
- `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.
|
- `log_level` (String): The log level for the app, defaults to `WARNING`
|
||||||
3. `llm` Section:
|
2. `llm` Section:
|
||||||
- `provider` (String): The provider for the language model, which is set to 'openai'. You can find the full list of llm providers in [our docs](/components/llms).
|
- `provider` (String): The provider for the language model, which is set to 'openai'. You can find the full list of llm providers in [our docs](/components/llms).
|
||||||
- `model` (String): The specific model being used, 'gpt-3.5-turbo'.
|
|
||||||
- `config`:
|
- `config`:
|
||||||
|
- `model` (String): The specific model being used, 'gpt-3.5-turbo'.
|
||||||
- `temperature` (Float): Controls the randomness of the model's output. A higher value (closer to 1) makes the output more random.
|
- `temperature` (Float): Controls the randomness of the model's output. A higher value (closer to 1) makes the output more random.
|
||||||
- `max_tokens` (Integer): Controls how many tokens are used in the response.
|
- `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.
|
- `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).
|
- `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.
|
- `template` (String): A custom template for the prompt that the model uses to generate responses.
|
||||||
- `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.
|
- `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.
|
||||||
4. `vectordb` Section:
|
- `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
|
||||||
|
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).
|
- `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`:
|
- `config`:
|
||||||
- `collection_name` (String): The initial collection name for the database, set to 'full-stack-app'.
|
- `collection_name` (String): The initial collection name for the vectordb, set to 'full-stack-app'.
|
||||||
- `dir` (String): The directory for the database, set to 'db'.
|
- `dir` (String): The directory for the local database, set to 'db'.
|
||||||
- `allow_reset` (Boolean): Indicates whether resetting the database is allowed, set to true.
|
- `allow_reset` (Boolean): Indicates whether resetting the vectordb is allowed, set to true.
|
||||||
5. `embedder` Section:
|
<Note>We recommend you to checkout vectordb specific config [here](https://docs.embedchain.ai/components/vector-databases)</Note>
|
||||||
|
4. `embedder` Section:
|
||||||
- `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).
|
- `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`:
|
- `config`:
|
||||||
- `model` (String): The specific model used for text embedding, 'text-embedding-ada-002'.
|
- `model` (String): The specific model used for text embedding, 'text-embedding-ada-002'.
|
||||||
|
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.
|
||||||
If you have questions about the configuration above, please feel free to reach out to us using one of the following methods:
|
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" />
|
<Snippet file="get-help.mdx" />
|
||||||
@@ -29,7 +29,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||||
|
|
||||||
# load embedding model configuration from config.yaml file
|
# load embedding model configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
|
|
||||||
app.add("https://en.wikipedia.org/wiki/OpenAI")
|
app.add("https://en.wikipedia.org/wiki/OpenAI")
|
||||||
app.query("What is OpenAI?")
|
app.query("What is OpenAI?")
|
||||||
@@ -55,11 +55,11 @@ import os
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
os.environ["OPENAI_API_TYPE"] = "azure"
|
os.environ["OPENAI_API_TYPE"] = "azure"
|
||||||
os.environ["OPENAI_API_BASE"] = "https://xxx.openai.azure.com/"
|
os.environ["AZURE_OPENAI_ENDPOINT"] = "https://xxx.openai.azure.com/"
|
||||||
os.environ["OPENAI_API_KEY"] = "xxx"
|
os.environ["AZURE_OPENAI_API_KEY"] = "xxx"
|
||||||
os.environ["OPENAI_API_VERSION"] = "xxx"
|
os.environ["OPENAI_API_VERSION"] = "xxx"
|
||||||
|
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -93,7 +93,7 @@ GPT4All supports generating high quality embeddings of arbitrary length document
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load embedding model configuration from config.yaml file
|
# load embedding model configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -122,7 +122,7 @@ Hugging Face supports generating embeddings of arbitrary length documents of tex
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load embedding model configuration from config.yaml file
|
# load embedding model configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -153,7 +153,7 @@ Embedchain supports Google's VertexAI embeddings model through a simple interfac
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load embedding model configuration from config.yaml file
|
# load embedding model configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
|
|||||||
+10
-10
@@ -46,7 +46,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||||
|
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -78,7 +78,7 @@ os.environ["OPENAI_API_BASE"] = "https://xxx.openai.azure.com/"
|
|||||||
os.environ["OPENAI_API_KEY"] = "xxx"
|
os.environ["OPENAI_API_KEY"] = "xxx"
|
||||||
os.environ["OPENAI_API_VERSION"] = "xxx"
|
os.environ["OPENAI_API_VERSION"] = "xxx"
|
||||||
|
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -115,7 +115,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ["ANTHROPIC_API_KEY"] = "xxx"
|
os.environ["ANTHROPIC_API_KEY"] = "xxx"
|
||||||
|
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -152,7 +152,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ["COHERE_API_KEY"] = "xxx"
|
os.environ["COHERE_API_KEY"] = "xxx"
|
||||||
|
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -183,7 +183,7 @@ GPT4all is a free-to-use, locally running, privacy-aware chatbot. No GPU or inte
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -216,7 +216,7 @@ from embedchain import Pipeline as App
|
|||||||
|
|
||||||
os.environ["JINACHAT_API_KEY"] = "xxx"
|
os.environ["JINACHAT_API_KEY"] = "xxx"
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -237,7 +237,7 @@ llm:
|
|||||||
Install related dependencies using the following command:
|
Install related dependencies using the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install --upgrade 'embedchain[huggingface_hub]'
|
pip install --upgrade 'embedchain[huggingface-hub]'
|
||||||
```
|
```
|
||||||
|
|
||||||
First, set `HUGGINGFACE_ACCESS_TOKEN` in environment variable which you can obtain from [their platform](https://huggingface.co/settings/tokens).
|
First, set `HUGGINGFACE_ACCESS_TOKEN` in environment variable which you can obtain from [their platform](https://huggingface.co/settings/tokens).
|
||||||
@@ -253,7 +253,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "xxx"
|
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "xxx"
|
||||||
|
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -283,7 +283,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ["REPLICATE_API_TOKEN"] = "xxx"
|
os.environ["REPLICATE_API_TOKEN"] = "xxx"
|
||||||
|
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -308,7 +308,7 @@ Setup Google Cloud Platform application credentials by following the instruction
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load llm configuration from config.yaml file
|
# load llm configuration from config.yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Utilizing a vector database alongside Embedchain is a seamless process. All you
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load chroma configuration from yaml file
|
# load chroma configuration from yaml file
|
||||||
app = App.from_config(yaml_path="config1.yaml")
|
app = App.from_config(config_path="config1.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config1.yaml
|
```yaml config1.yaml
|
||||||
@@ -64,7 +64,7 @@ pip install --upgrade 'embedchain[elasticsearch]'
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load elasticsearch configuration from yaml file
|
# load elasticsearch configuration from yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -73,8 +73,11 @@ vectordb:
|
|||||||
config:
|
config:
|
||||||
collection_name: 'es-index'
|
collection_name: 'es-index'
|
||||||
es_url: http://localhost:9200
|
es_url: http://localhost:9200
|
||||||
allow_reset: true
|
http_auth:
|
||||||
|
- admin
|
||||||
|
- admin
|
||||||
api_key: xxx
|
api_key: xxx
|
||||||
|
verify_certs: false
|
||||||
```
|
```
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
|
|
||||||
@@ -92,19 +95,19 @@ pip install --upgrade 'embedchain[opensearch]'
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load opensearch configuration from yaml file
|
# load opensearch configuration from yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
vectordb:
|
vectordb:
|
||||||
provider: opensearch
|
provider: opensearch
|
||||||
config:
|
config:
|
||||||
|
collection_name: 'my-app'
|
||||||
opensearch_url: 'https://localhost:9200'
|
opensearch_url: 'https://localhost:9200'
|
||||||
http_auth:
|
http_auth:
|
||||||
- admin
|
- admin
|
||||||
- admin
|
- admin
|
||||||
vector_dimension: 1536
|
vector_dimension: 1536
|
||||||
collection_name: 'my-app'
|
|
||||||
use_ssl: false
|
use_ssl: false
|
||||||
verify_certs: false
|
verify_certs: false
|
||||||
```
|
```
|
||||||
@@ -131,7 +134,7 @@ os.environ['ZILLIZ_CLOUD_URI'] = 'https://xxx.zillizcloud.com'
|
|||||||
os.environ['ZILLIZ_CLOUD_TOKEN'] = 'xxx'
|
os.environ['ZILLIZ_CLOUD_TOKEN'] = 'xxx'
|
||||||
|
|
||||||
# load zilliz configuration from yaml file
|
# load zilliz configuration from yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -167,7 +170,7 @@ In order to use Pinecone as vector database, set the environment variables `PINE
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load pinecone configuration from yaml file
|
# load pinecone configuration from yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -190,7 +193,7 @@ In order to use Qdrant as a vector database, set the environment variables `QDRA
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load qdrant configuration from yaml file
|
# load qdrant configuration from yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
@@ -210,7 +213,7 @@ In order to use Weaviate as a vector database, set the environment variables `WE
|
|||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
# load weaviate configuration from yaml file
|
# load weaviate configuration from yaml file
|
||||||
app = App.from_config(yaml_path="config.yaml")
|
app = App.from_config(config_path="config.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml config.yaml
|
```yaml config.yaml
|
||||||
|
|||||||
@@ -50,3 +50,15 @@ from embedchain import Pipeline as App
|
|||||||
naval_chat_bot = 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?"))
|
print(naval_chat_bot.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?"))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Resetting an app and vector database
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
app.add("https://www.youtube.com/watch?v=3qHkcs3kG44")
|
||||||
|
app.reset()
|
||||||
|
```
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
title: "💬 Discord"
|
||||||
|
---
|
||||||
|
|
||||||
|
To add any Discord channel messages to your app, just add the `channel_id` as the source and set the `data_type` to `discord`.
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
This loader requires a Discord bot token with read messages access.
|
||||||
|
To obtain the token, follow the instructions provided in this tutorial:
|
||||||
|
<a href="https://www.writebots.com/discord-bot-token/">How to Get a Discord Bot Token?</a>.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
```python
|
||||||
|
import os
|
||||||
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
|
# add your discord "BOT" token
|
||||||
|
os.environ["DISCORD_TOKEN"] = "xxx"
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
|
||||||
|
app.add("1177296711023075338", data_type="discord")
|
||||||
|
|
||||||
|
response = app.query("What is Joe saying about Elon Musk?")
|
||||||
|
|
||||||
|
print(response)
|
||||||
|
# Answer: Joe is saying "Elon Musk is a genius".
|
||||||
|
```
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
title: '🗨️ Discourse'
|
||||||
|
---
|
||||||
|
|
||||||
|
You can now easily load data from your community built with [Discourse](https://discourse.org/).
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
1. Setup the Discourse Loader with your community url.
|
||||||
|
```Python
|
||||||
|
from embedchain.loaders.discourse import DiscourseLoader
|
||||||
|
|
||||||
|
dicourse_loader = DiscourseLoader(config={"domain": "https://community.openai.com"})
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Once you setup the loader, you can create an app and load data using the above discourse loader
|
||||||
|
```Python
|
||||||
|
import os
|
||||||
|
from embedchain.pipeline import Pipeline as App
|
||||||
|
|
||||||
|
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
|
||||||
|
app.add("openai after:2023-10-1", data_type="discourse", loader=dicourse_loader)
|
||||||
|
|
||||||
|
question = "Where can I find the OpenAI API status page?"
|
||||||
|
app.query(question)
|
||||||
|
# Answer: You can find the OpenAI API status page at https:/status.openai.com/.
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: The `add` function of the app will accept any executable search query to load data. Refer [Discourse API Docs](https://docs.discourse.org/#tag/Search) to learn more about search queries.
|
||||||
|
|
||||||
|
3. We automatically create a chunker to chunk your discourse data, however if you wish to provide your own chunker class. Here is how you can do that:
|
||||||
|
```Python
|
||||||
|
|
||||||
|
from embedchain.chunkers.discourse import DiscourseChunker
|
||||||
|
from embedchain.config.add_config import ChunkerConfig
|
||||||
|
|
||||||
|
discourse_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len)
|
||||||
|
discourse_chunker = DiscourseChunker(config=discourse_chunker_config)
|
||||||
|
|
||||||
|
app.add("openai", data_type='discourse', loader=dicourse_loader, chunker=discourse_chunker)
|
||||||
|
```
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: '📚🌐 Code documentation'
|
title: '📚 Code documentation'
|
||||||
---
|
---
|
||||||
|
|
||||||
To add any code documentation website as a loader, use the data_type as `docs_site`. Eg:
|
To add any code documentation website as a loader, use the data_type as `docs_site`. Eg:
|
||||||
|
|||||||
@@ -24,12 +24,11 @@ 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`
|
12. Put the `.json` file in your current directory and rename it to `credentials.json`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import os
|
from embedchain import Pipeline as App
|
||||||
from embedchain.apps.app import App
|
|
||||||
from embedchain.models.data_type import DataType
|
|
||||||
app = App()
|
app = App()
|
||||||
|
|
||||||
query = "to: me label:inbox"
|
gmail_filter = "to: me label:inbox"
|
||||||
app.add(query, data_type=DataType.GMAIL)
|
app.add(gmail_filter, data_type="gmail")
|
||||||
app.query("Summarize my email conversations")
|
app.query("Summarize my email conversations")
|
||||||
```
|
```
|
||||||
+17
-26
@@ -2,52 +2,43 @@
|
|||||||
title: '📃 JSON'
|
title: '📃 JSON'
|
||||||
---
|
---
|
||||||
|
|
||||||
To add any json file, use the data_type as `json`. Headers are included for each line, so if you have an `age` column, `18` will be added as `age: 18`. Eg:
|
To add any json file, use the data_type as `json`. Headers are included for each line, so for example if you have a json like `{"age": 18}`, then it will be added as `age: 18`.
|
||||||
|
|
||||||
Here are the supported sources for loading `json`:
|
Here are the supported sources for loading `json`:
|
||||||
|
|
||||||
```
|
```
|
||||||
1. URL - valid url to json file that ends with ".json" extension.
|
1. URL - valid url to json file that ends with ".json" extension.
|
||||||
2. Local file - valid url to local json file that ends with ".json" extension.
|
2. Local file - valid url to local json file that ends with ".json" extension.
|
||||||
3. String - valid json string (e.g. - app.add('{"foo": "bar"}'))
|
3. String - valid json string (e.g. - app.add('{"foo": "bar"}'))
|
||||||
```
|
```
|
||||||
|
|
||||||
If you would like to add other data structures (e.x. list, dict etc.), do:
|
<Tip>
|
||||||
```python
|
If you would like to add other data structures (e.g. list, dict etc.), convert it to a valid json first using `json.dumps()` function.
|
||||||
import json
|
</Tip>
|
||||||
a = {"foo": "bar"}
|
|
||||||
valid_json_string_data = json.dumps(a, indent=0)
|
|
||||||
|
|
||||||
b = [{"foo": "bar"}]
|
## Example
|
||||||
valid_json_string_data = json.dumps(b, indent=0)
|
|
||||||
```
|
|
||||||
Example:
|
|
||||||
```python
|
|
||||||
import os
|
|
||||||
|
|
||||||
from embedchain.apps.app import App
|
<CodeGroup>
|
||||||
|
|
||||||
os.environ["OPENAI_API_KEY"] = "openai_api_key"
|
```python python
|
||||||
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
app = App()
|
app = App()
|
||||||
|
|
||||||
response = app.query("What is the net worth of Elon Musk as of October 2023?")
|
# Add json file
|
||||||
|
app.add("temp.json")
|
||||||
|
|
||||||
print(response)
|
app.query("What is the net worth of Elon Musk as of October 2023?")
|
||||||
"I'm sorry, but I don't have access to real-time information or future predictions. Therefore, I don't know the net worth of Elon Musk as of October 2023."
|
# As of October 2023, Elon Musk's net worth is $255.2 billion.
|
||||||
|
|
||||||
source_id = app.add("temp.json")
|
|
||||||
|
|
||||||
response = app.query("What is the net worth of Elon Musk as of October 2023?")
|
|
||||||
|
|
||||||
print(response)
|
|
||||||
"As of October 2023, Elon Musk's net worth is $255.2 billion."
|
|
||||||
```
|
```
|
||||||
temp.json
|
|
||||||
```json
|
|
||||||
|
```json temp.json
|
||||||
{
|
{
|
||||||
"question": "What is your net worth, Elon Musk?",
|
"question": "What is your net worth, Elon Musk?",
|
||||||
"answer": "As of October 2023, Elon Musk's net worth is $255.2 billion, making him one of the wealthiest individuals in the world."
|
"answer": "As of October 2023, Elon Musk's net worth is $255.2 billion, making him one of the wealthiest individuals in the world."
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
</CodeGroup>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
title: '🐬 MySQL'
|
||||||
|
---
|
||||||
|
|
||||||
|
1. Setup the MySQL loader by configuring the SQL db.
|
||||||
|
```Python
|
||||||
|
from embedchain.loaders.mysql import MySQLLoader
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"host": "host",
|
||||||
|
"port": "port",
|
||||||
|
"database": "database",
|
||||||
|
"user": "username",
|
||||||
|
"password": "password",
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_loader = MySQLLoader(config=config)
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details on how to setup with valid config, check MySQL [documentation](https://dev.mysql.com/doc/connector-python/en/connector-python-connectargs.html).
|
||||||
|
|
||||||
|
2. Once you setup the loader, you can create an app and load data using the above MySQL loader
|
||||||
|
```Python
|
||||||
|
import os
|
||||||
|
from embedchain.pipeline import Pipeline as App
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
|
||||||
|
app.add("SELECT * FROM table_name;", data_type='mysql', loader=mysql_loader)
|
||||||
|
# Adds `(1, 'What is your net worth, Elon Musk?', "As of October 2023, Elon Musk's net worth is $255.2 billion.")`
|
||||||
|
|
||||||
|
response = app.query(question)
|
||||||
|
# Answer: As of October 2023, Elon Musk's net worth is $255.2 billion.
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: The `add` function of the app will accept any executable query to load data. DO NOT pass the `CREATE`, `INSERT` queries in `add` function.
|
||||||
|
|
||||||
|
3. We automatically create a chunker to chunk your SQL data, however if you wish to provide your own chunker class. Here is how you can do that:
|
||||||
|
``Python
|
||||||
|
|
||||||
|
from embedchain.chunkers.mysql import MySQLChunker
|
||||||
|
from embedchain.config.add_config import ChunkerConfig
|
||||||
|
|
||||||
|
mysql_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len)
|
||||||
|
mysql_chunker = MySQLChunker(config=mysql_chunker_config)
|
||||||
|
|
||||||
|
app.add("SELECT * FROM table_name;", data_type='mysql', loader=mysql_loader, chunker=mysql_chunker)
|
||||||
|
```
|
||||||
@@ -2,13 +2,10 @@
|
|||||||
title: 🙌 OpenAPI
|
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. Headers are included for each line, so if you have an `age` column, `18` will be added as `age: 18`. Eg:
|
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
|
```python
|
||||||
from embedchain.apps.app import App
|
from embedchain import Pipeline as App
|
||||||
import os
|
|
||||||
|
|
||||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
|
||||||
|
|
||||||
app = App()
|
app = App()
|
||||||
|
|
||||||
@@ -16,8 +13,10 @@ app.add("https://github.com/openai/openai-openapi/blob/master/openapi.yaml", dat
|
|||||||
# Or add using the local file path
|
# Or add using the local file path
|
||||||
# app.add("configs/openai_openapi.yaml", data_type="openapi")
|
# app.add("configs/openai_openapi.yaml", data_type="openapi")
|
||||||
|
|
||||||
response = app.query("What can OpenAI API endpoint do? Can you list the things it can learn from?")
|
app.query("What can OpenAI API endpoint do? Can you list the things it can learn from?")
|
||||||
# Answer: The OpenAI API endpoint allows users to interact with OpenAI's models and perform various tasks such as generating text, answering questions, summarizing documents, translating languages, and more. The specific capabilities and tasks that the API can learn from may vary depending on the models and features provided by OpenAI. For more detailed information, it is recommended to refer to the OpenAI API documentation at https://platform.openai.com/docs/api-reference.
|
# Answer: The OpenAI API endpoint allows users to interact with OpenAI's models and perform various tasks such as generating text, answering questions, summarizing documents, translating languages, and more. The specific capabilities and tasks that the API can learn from may vary depending on the models and features provided by OpenAI. For more detailed information, it is recommended to refer to the OpenAI API documentation at https://platform.openai.com/docs/api-reference.
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: The yaml file added to the App must have the required OpenAPI fields otherwise the adding OpenAPI spec will fail. Please refer to [OpenAPI Spec Doc](https://spec.openapis.org/oas/v3.1.0)
|
<Note>
|
||||||
|
The yaml file added to the App must have the required OpenAPI fields otherwise the adding OpenAPI spec will fail. Please refer to [OpenAPI Spec Doc](https://spec.openapis.org/oas/v3.1.0)
|
||||||
|
</Note>
|
||||||
@@ -5,21 +5,26 @@ title: Overview
|
|||||||
Embedchain comes with built-in support for various data sources. We handle the complexity of loading unstructured data from these data sources, allowing you to easily customize your app through a user-friendly interface.
|
Embedchain comes with built-in support for various data sources. We handle the complexity of loading unstructured data from these data sources, allowing you to easily customize your app through a user-friendly interface.
|
||||||
|
|
||||||
<CardGroup cols={4}>
|
<CardGroup cols={4}>
|
||||||
<Card title="📊 csv" href="/data-sources/csv"></Card>
|
<Card title="📊 CSV" href="/data-sources/csv"></Card>
|
||||||
<Card title="📃 JSON" href="/data-sources/json"></Card>
|
<Card title="📃 JSON" href="/data-sources/json"></Card>
|
||||||
<Card title="📚🌐 docs site" href="/data-sources/docs-site"></Card>
|
<Card title="📚 docs site" href="/data-sources/docs-site"></Card>
|
||||||
<Card title="📄 docx" href="/data-sources/docx"></Card>
|
<Card title="📄 docx" href="/data-sources/docx"></Card>
|
||||||
<Card title="📝 mdx" href="/data-sources/mdx"></Card>
|
<Card title="📝 mdx" href="/data-sources/mdx"></Card>
|
||||||
<Card title="📓 notion" href="/data-sources/notion"></Card>
|
<Card title="📓 Notion" href="/data-sources/notion"></Card>
|
||||||
<Card title="📰 pdf" href="/data-sources/pdf-file"></Card>
|
<Card title="📰 PDF" href="/data-sources/pdf-file"></Card>
|
||||||
<Card title="❓💬 q&a pair" href="/data-sources/qna"></Card>
|
<Card title="❓💬 q&a pair" href="/data-sources/qna"></Card>
|
||||||
<Card title="🗺️ sitemap" href="/data-sources/sitemap"></Card>
|
<Card title="🗺️ sitemap" href="/data-sources/sitemap"></Card>
|
||||||
<Card title="📝 text" href="/data-sources/text"></Card>
|
<Card title="📝 text" href="/data-sources/text"></Card>
|
||||||
<Card title="🌐📄 web page" href="/data-sources/web-page"></Card>
|
<Card title="🌐 web page" href="/data-sources/web-page"></Card>
|
||||||
<Card title="🧾 xml" href="/data-sources/xml"></Card>
|
<Card title="🧾 xml" href="/data-sources/xml"></Card>
|
||||||
<Card title="🙌 OpenAPI" href="/data-sources/openapi"></Card>
|
<Card title="🙌 OpenAPI" href="/data-sources/openapi"></Card>
|
||||||
<Card title="🎥📺 youtube video" href="/data-sources/youtube-video"></Card>
|
<Card title="📺 Youtube" href="/data-sources/youtube-video"></Card>
|
||||||
<Card title="📬 Gmail" href="/data-sources/gmail"></Card>
|
<Card title="📬 Gmail" href="/data-sources/gmail"></Card>
|
||||||
|
<Card title="🐘 Postgres" href="/data-sources/postgres"></Card>
|
||||||
|
<Card title="🐬 MySQL" href="/data-sources/mysql"></Card>
|
||||||
|
<Card title="🤖 Slack" href="/data-sources/slack"></Card>
|
||||||
|
<Card title="🗨️ Discourse" href="/data-sources/discourse"></Card>
|
||||||
|
<Card title="💬 Discord" href="/data-sources/discord"></Card>
|
||||||
</CardGroup>
|
</CardGroup>
|
||||||
|
|
||||||
<br/ >
|
<br/ >
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
title: '🐘 Postgres'
|
||||||
|
---
|
||||||
|
|
||||||
|
1. Setup the Postgres loader by configuring the postgres db.
|
||||||
|
```Python
|
||||||
|
from embedchain.loaders.postgres import PostgresLoader
|
||||||
|
|
||||||
|
config = {
|
||||||
|
"host": "host_address",
|
||||||
|
"port": "port_number",
|
||||||
|
"dbname": "database_name",
|
||||||
|
"user": "username",
|
||||||
|
"password": "password",
|
||||||
|
}
|
||||||
|
|
||||||
|
"""
|
||||||
|
config = {
|
||||||
|
"url": "your_postgres_url"
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
postgres_loader = PostgresLoader(config=config)
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
You can either setup the loader by passing the postgresql url or by providing the config data.
|
||||||
|
For more details on how to setup with valid url and config, check postgres [documentation](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING:~:text=34.1.1.%C2%A0Connection%20Strings-,%23,-Several%20libpq%20functions).
|
||||||
|
|
||||||
|
NOTE: if you provide the `url` field in config, all other fields will be ignored.
|
||||||
|
|
||||||
|
2. Once you setup the loader, you can create an app and load data using the above postgres loader
|
||||||
|
```Python
|
||||||
|
import os
|
||||||
|
from embedchain.pipeline import Pipeline as App
|
||||||
|
|
||||||
|
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
|
||||||
|
question = "What is Elon Musk's networth?"
|
||||||
|
response = app.query(question)
|
||||||
|
# Answer: As of September 2021, Elon Musk's net worth is estimated to be around $250 billion, making him one of the wealthiest individuals in the world. However, please note that net worth can fluctuate over time due to various factors such as stock market changes and business ventures.
|
||||||
|
|
||||||
|
app.add("SELECT * FROM table_name;", data_type='postgres', loader=postgres_loader)
|
||||||
|
# Adds `(1, 'What is your net worth, Elon Musk?', "As of October 2023, Elon Musk's net worth is $255.2 billion.")`
|
||||||
|
|
||||||
|
response = app.query(question)
|
||||||
|
# Answer: As of October 2023, Elon Musk's net worth is $255.2 billion.
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: The `add` function of the app will accept any executable query to load data. DO NOT pass the `CREATE`, `INSERT` queries in `add` function as they will result in not adding any data, so it is pointless.
|
||||||
|
|
||||||
|
3. We automatically create a chunker to chunk your postgres data, however if you wish to provide your own chunker class. Here is how you can do that:
|
||||||
|
```Python
|
||||||
|
|
||||||
|
from embedchain.chunkers.postgres import PostgresChunker
|
||||||
|
from embedchain.config.add_config import ChunkerConfig
|
||||||
|
|
||||||
|
postgres_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len)
|
||||||
|
postgres_chunker = PostgresChunker(config=postgres_chunker_config)
|
||||||
|
|
||||||
|
app.add("SELECT * FROM table_name;", data_type='postgres', loader=postgres_loader, chunker=postgres_chunker)
|
||||||
|
```
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
title: '🤖 Slack'
|
||||||
|
---
|
||||||
|
|
||||||
|
## Pre-requisite
|
||||||
|
- Download required packages by running `pip install --upgrade "embedchain[slack]"`.
|
||||||
|
- Configure your slack bot token as environment variable `SLACK_USER_TOKEN`.
|
||||||
|
- Find your user token on your [Slack Account](https://api.slack.com/authentication/token-types)
|
||||||
|
- Make sure your slack user token includes [search](https://api.slack.com/scopes/search:read) scope.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
1. Setup the Slack loader by configuring the Slack Webclient.
|
||||||
|
```Python
|
||||||
|
from embedchain.loaders.slack import SlackLoader
|
||||||
|
|
||||||
|
os.environ["SLACK_USER_TOKEN"] = "xoxp-*"
|
||||||
|
|
||||||
|
loader = SlackLoader()
|
||||||
|
|
||||||
|
"""
|
||||||
|
config = {
|
||||||
|
'base_url': slack_app_url,
|
||||||
|
'headers': web_headers,
|
||||||
|
'team_id': slack_team_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
loader = SlackLoader(config)
|
||||||
|
"""
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: you can also pass the `config` with `base_url`, `headers`, `team_id` to setup your SlackLoader.
|
||||||
|
|
||||||
|
2. Once you setup the loader, you can create an app and load data using the above slack loader
|
||||||
|
```Python
|
||||||
|
import os
|
||||||
|
from embedchain.pipeline import Pipeline as App
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
|
||||||
|
app.add("in:random", data_type="slack", loader=loader)
|
||||||
|
question = "Which bots are available in the slack workspace's random channel?"
|
||||||
|
# Answer: The available bot in the slack workspace's random channel is the Embedchain bot.
|
||||||
|
```
|
||||||
|
|
||||||
|
3. We automatically create a chunker to chunk your slack data, however if you wish to provide your own chunker class. Here is how you can do that:
|
||||||
|
```Python
|
||||||
|
from embedchain.chunkers.slack import SlackChunker
|
||||||
|
from embedchain.config.add_config import ChunkerConfig
|
||||||
|
|
||||||
|
slack_chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=0, length_function=len)
|
||||||
|
slack_chunker = SlackChunker(config=slack_chunker_config)
|
||||||
|
|
||||||
|
app.add(slack_chunker, data_type="slack", loader=loader, chunker=slack_chunker)
|
||||||
|
```
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
---
|
||||||
|
title: "📝 Substack"
|
||||||
|
---
|
||||||
|
|
||||||
|
To add any Substack data sources to your app, just add the sitemap.xml of that url as the source and set the data_type to `substack`.
|
||||||
|
|
||||||
|
```python
|
||||||
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
|
app = App()
|
||||||
|
|
||||||
|
# source: for any substack just add the sitemap.xml url
|
||||||
|
app.add('https://www.lennysnewsletter.com/sitemap.xml', data_type='substack')
|
||||||
|
app.query("Who is Brian Chesky?")
|
||||||
|
# Answer: Brian Chesky is the co-founder and CEO of Airbnb.
|
||||||
|
```
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: '🌐📄 Web page'
|
title: '🌐 Web page'
|
||||||
---
|
---
|
||||||
|
|
||||||
To add any web page, use the data_type as `web_page`. Eg:
|
To add any web page, use the data_type as `web_page`. Eg:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: '🎥📺 Youtube video'
|
title: '📺 Youtube'
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,21 @@ channels:read
|
|||||||
chat:write
|
chat:write
|
||||||
```
|
```
|
||||||
5. Now select the option `Install to Workspace` and after it's done, copy the `Bot User OAuth Token` and set it in your secrets as `SLACK_BOT_TOKEN`.
|
5. Now select the option `Install to Workspace` and after it's done, copy the `Bot User OAuth Token` and set it in your secrets as `SLACK_BOT_TOKEN`.
|
||||||
6. Run your bot now with `python3 -m embedchain.bots.slack`
|
6. Run your bot now,
|
||||||
7. Expose your bot to the internet. Default port is `5000`, which can be changed by adding `port --8080` to the startup command. You can use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible.
|
<Tabs>
|
||||||
|
<Tab title="docker">
|
||||||
|
```bash
|
||||||
|
docker run --name slack-bot -e OPENAI_API_KEY=sk-xxx -e SLACK_BOT_TOKEN=xxx -p 8000:8000 embedchain/slack-bot
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab title="python">
|
||||||
|
```bash
|
||||||
|
pip install --upgrade "embedchain[slack]"
|
||||||
|
python3 -m embedchain.bots.slack --port 8000
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
7. Expose your bot to the internet. You can use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible.
|
||||||
8. On the Slack API website go to `Event Subscriptions` on the left Sidebar and turn on `Enable Events`.
|
8. On the Slack API website go to `Event Subscriptions` on the left Sidebar and turn on `Enable Events`.
|
||||||
9. In `Request URL`, enter your server or ngrok address.
|
9. In `Request URL`, enter your server or ngrok address.
|
||||||
10. After it gets verified, click on `Subscribe to bot events`, add `message.channels` Bot User Event and click on `Save Changes`.
|
10. After it gets verified, click on `Subscribe to bot events`, add `message.channels` Bot User Event and click on `Save Changes`.
|
||||||
|
|||||||
@@ -1,21 +1,46 @@
|
|||||||
---
|
---
|
||||||
title: '📱 Telegram Bot'
|
title: "📱 Telegram Bot"
|
||||||
---
|
---
|
||||||
|
|
||||||
### 🖼️ Template Setup
|
### 🖼️ Template Setup
|
||||||
|
|
||||||
- Fork [this](https://replit.com/@taranjeetio/EC-Telegram-Bot-Template?v=1#README.md) replit template.
|
|
||||||
- Set your `OPENAI_API_KEY` in Secrets.
|
|
||||||
- Open the Telegram app and search for the `BotFather` user.
|
- Open the Telegram app and search for the `BotFather` user.
|
||||||
- Start a chat with BotFather and use the `/newbot` command to create a new bot.
|
- Start a chat with BotFather and use the `/newbot` command to create a new bot.
|
||||||
- Follow the instructions to choose a name and username for your bot.
|
- Follow the instructions to choose a name and username for your bot.
|
||||||
- Once the bot is created, BotFather will provide you with a unique token for your bot.
|
- Once the bot is created, BotFather will provide you with a unique token for your bot.
|
||||||
- Set this token as `TELEGRAM_BOT_TOKEN` in Secrets.
|
|
||||||
|
<Tabs>
|
||||||
|
<Tab title="docker">
|
||||||
|
```bash
|
||||||
|
docker run --name telegram-bot -e OPENAI_API_KEY=sk-xxx -e TELEGRAM_BOT_TOKEN=xxx -p 8000:8000 embedchain/telegram-bot
|
||||||
|
```
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
If you wish to use **Docker**, you would need to host your bot on a server.
|
||||||
|
You can use [ngrok](https://ngrok.com/) to expose your localhost to the
|
||||||
|
internet and then set the webhook using the ngrok URL.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
</Tab>
|
||||||
|
<Tab title="replit">
|
||||||
|
<Card>
|
||||||
|
Fork <ins>**[this](https://replit.com/@taranjeetio/EC-Telegram-Bot-Template?v=1#README.md)**</ins> replit template.
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
- Set your `OPENAI_API_KEY` in Secrets.
|
||||||
|
- Set the unique token as `TELEGRAM_BOT_TOKEN` in Secrets.
|
||||||
|
|
||||||
|
</Tab>
|
||||||
|
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
- Click on `Run` in the replit container and a URL will get generated for your bot.
|
- Click on `Run` in the replit container and a URL will get generated for your bot.
|
||||||
- Now set your webhook by running the following link in your browser:
|
- Now set your webhook by running the following link in your browser:
|
||||||
|
|
||||||
```url
|
```url
|
||||||
https://api.telegram.org/bot<Your_Telegram_Bot_Token>/setWebhook?url=<Replit_Generated_URL>
|
https://api.telegram.org/bot<Your_Telegram_Bot_Token>/setWebhook?url=<Replit_Generated_URL>
|
||||||
```
|
```
|
||||||
|
|
||||||
- When you get a successful response in your browser, your bot is ready to be used.
|
- When you get a successful response in your browser, your bot is ready to be used.
|
||||||
|
|
||||||
### 🚀 Usage Instructions
|
### 🚀 Usage Instructions
|
||||||
|
|||||||
@@ -12,10 +12,19 @@ pip install --upgrade embedchain
|
|||||||
|
|
||||||
2. Launch your WhatsApp bot:
|
2. Launch your WhatsApp bot:
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<Tab title="docker">
|
||||||
|
```bash
|
||||||
|
docker run --name whatsapp-bot -e OPENAI_API_KEY=sk-xxx -p 8000:8000 embedchain/whatsapp-bot
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
<Tab title="python">
|
||||||
|
```bash
|
||||||
|
python -m embedchain.bots.whatsapp --port 5000
|
||||||
|
```
|
||||||
|
</Tab>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
```bash
|
|
||||||
python -m embedchain.bots.whatsapp --port 5000
|
|
||||||
```
|
|
||||||
|
|
||||||
If your bot needs to be accessible online, use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible.
|
If your bot needs to be accessible online, use your machine's public IP or DNS. Otherwise, employ a proxy server like [ngrok](https://ngrok.com/) to make your local bot accessible.
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
---
|
---
|
||||||
title: 🔎 Examples
|
title: 🔎 Examples
|
||||||
description: 'Collection of Google colab notebook and Replit links for users'
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
# Explore awesome apps
|
||||||
|
|
||||||
|
Check out the remarkable work accomplished using [Embedchain](https://app.embedchain.ai/custom-gpts/).
|
||||||
|
|
||||||
|
## Collection of Google colab notebook and Replit links for users
|
||||||
|
|
||||||
|
Get started with Embedchain by trying out the examples below. You can run the examples in your browser using Google Colab or Replit.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
+37
-16
@@ -2,13 +2,36 @@
|
|||||||
title: ❓ FAQs
|
title: ❓ FAQs
|
||||||
description: 'Collections of all the frequently asked questions'
|
description: 'Collections of all the frequently asked questions'
|
||||||
---
|
---
|
||||||
|
<AccordionGroup>
|
||||||
#### Does Embedchain support OpenAI's Assistant APIs?
|
<Accordion title="Does Embedchain support OpenAI's Assistant APIs?">
|
||||||
|
|
||||||
Yes, it does. Please refer to the [OpenAI Assistant docs page](/get-started/openai-assistant).
|
Yes, it does. Please refer to the [OpenAI Assistant docs page](/get-started/openai-assistant).
|
||||||
|
</Accordion>
|
||||||
|
<Accordion title="How to use MistralAI language model?">
|
||||||
|
Use the model provided on huggingface: `mistralai/Mistral-7B-v0.1`
|
||||||
|
<CodeGroup>
|
||||||
|
```python main.py
|
||||||
|
import os
|
||||||
|
from embedchain import Pipeline as App
|
||||||
|
|
||||||
#### How to use `gpt-4-turbo` model released on OpenAI DevDay?
|
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||||
|
os.environ["HUGGINGFACE_ACCESS_TOKEN"] = "hf_your_token"
|
||||||
|
|
||||||
|
app = App.from_config("huggingface.yaml")
|
||||||
|
```
|
||||||
|
```yaml huggingface.yaml
|
||||||
|
llm:
|
||||||
|
provider: huggingface
|
||||||
|
config:
|
||||||
|
model: 'mistralai/Mistral-7B-v0.1'
|
||||||
|
temperature: 0.5
|
||||||
|
max_tokens: 1000
|
||||||
|
top_p: 0.5
|
||||||
|
stream: false
|
||||||
|
```
|
||||||
|
</CodeGroup>
|
||||||
|
</Accordion>
|
||||||
|
<Accordion title="How to use ChatGPT 4 turbo model released on OpenAI DevDay?">
|
||||||
|
Use the model `gpt-4-turbo` provided my openai.
|
||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
|
|
||||||
```python main.py
|
```python main.py
|
||||||
@@ -18,7 +41,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||||
|
|
||||||
# load llm configuration from gpt4_turbo.yaml file
|
# load llm configuration from gpt4_turbo.yaml file
|
||||||
app = App.from_config(yaml_path="gpt4_turbo.yaml")
|
app = App.from_config(config_path="gpt4_turbo.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml gpt4_turbo.yaml
|
```yaml gpt4_turbo.yaml
|
||||||
@@ -31,12 +54,9 @@ llm:
|
|||||||
top_p: 1
|
top_p: 1
|
||||||
stream: false
|
stream: false
|
||||||
```
|
```
|
||||||
|
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
|
</Accordion>
|
||||||
|
<Accordion title="How to use GPT-4 as the LLM model?">
|
||||||
#### How to use GPT-4 as the LLM model?
|
|
||||||
|
|
||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
|
|
||||||
```python main.py
|
```python main.py
|
||||||
@@ -46,7 +66,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||||
|
|
||||||
# load llm configuration from gpt4.yaml file
|
# load llm configuration from gpt4.yaml file
|
||||||
app = App.from_config(yaml_path="gpt4.yaml")
|
app = App.from_config(config_path="gpt4.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml gpt4.yaml
|
```yaml gpt4.yaml
|
||||||
@@ -61,9 +81,8 @@ llm:
|
|||||||
```
|
```
|
||||||
|
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
|
</Accordion>
|
||||||
#### I don't have OpenAI credits. How can I use some open source model?
|
<Accordion title="I don't have OpenAI credits. How can I use some open source model?">
|
||||||
|
|
||||||
<CodeGroup>
|
<CodeGroup>
|
||||||
|
|
||||||
```python main.py
|
```python main.py
|
||||||
@@ -73,7 +92,7 @@ from embedchain import Pipeline as App
|
|||||||
os.environ['OPENAI_API_KEY'] = 'xxx'
|
os.environ['OPENAI_API_KEY'] = 'xxx'
|
||||||
|
|
||||||
# load llm configuration from opensource.yaml file
|
# load llm configuration from opensource.yaml file
|
||||||
app = App.from_config(yaml_path="opensource.yaml")
|
app = App.from_config(config_path="opensource.yaml")
|
||||||
```
|
```
|
||||||
|
|
||||||
```yaml opensource.yaml
|
```yaml opensource.yaml
|
||||||
@@ -93,8 +112,10 @@ embedder:
|
|||||||
```
|
```
|
||||||
</CodeGroup>
|
</CodeGroup>
|
||||||
|
|
||||||
#### How to contact support?
|
</Accordion>
|
||||||
|
</AccordionGroup>
|
||||||
|
|
||||||
|
#### Need more help?
|
||||||
If docs aren't sufficient, please feel free to reach out to us using one of the following methods:
|
If docs aren't sufficient, please feel free to reach out to us using one of the following methods:
|
||||||
|
|
||||||
<Snippet file="get-help.mdx" />
|
<Snippet file="get-help.mdx" />
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ app.deploy()
|
|||||||
# ✅ Data of type: web_page, value: https://www.forbes.com/profile/elon-musk added successfully.
|
# ✅ Data of type: web_page, value: https://www.forbes.com/profile/elon-musk added successfully.
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🚀 How it works?
|
## 🛠️ How it works?
|
||||||
|
|
||||||
Embedchain abstracts out the following steps from you to easily create LLM powered apps:
|
Embedchain abstracts out the following steps from you to easily create LLM powered apps:
|
||||||
|
|
||||||
@@ -129,3 +129,5 @@ The process of loading the dataset and querying involves multiple steps, each wi
|
|||||||
- How should I find similar documents for a query? Which ranking model should I use?
|
- How should I find similar documents for a query? Which ranking model should I use?
|
||||||
|
|
||||||
Embedchain takes care of all these nuances and provides a simple interface to create apps on any data.
|
Embedchain takes care of all these nuances and provides a simple interface to create apps on any data.
|
||||||
|
|
||||||
|
## [🚀 Get started](https://docs.embedchain.ai/get-started/quickstart)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Embedchain now supports [OpenAI Assistants API](https://platform.openai.com/docs
|
|||||||
|
|
||||||
At a high level, an integration of the Assistants API has the following flow:
|
At a high level, an integration of the Assistants API has the following flow:
|
||||||
|
|
||||||
1. Create an Assistant in the API by defining it custom instructions and picking a model
|
1. Create an Assistant in the API by defining custom instructions and picking a model
|
||||||
2. Create a Thread when a user starts a conversation
|
2. Create a Thread when a user starts a conversation
|
||||||
3. Add Messages to the Thread as the user ask questions
|
3. Add Messages to the Thread as the user ask questions
|
||||||
4. Run the Assistant on the Thread to trigger responses. This automatically calls the relevant tools.
|
4. Run the Assistant on the Thread to trigger responses. This automatically calls the relevant tools.
|
||||||
@@ -19,7 +19,7 @@ Creating an OpenAI Assistant using Embedchain is very simple 3 step process.
|
|||||||
|
|
||||||
Make sure that you have `OPENAI_API_KEY` set in the environment variable.
|
Make sure that you have `OPENAI_API_KEY` set in the environment variable.
|
||||||
|
|
||||||
```python
|
```python Initialize
|
||||||
from embedchain.store.assistants import OpenAIAssistant
|
from embedchain.store.assistants import OpenAIAssistant
|
||||||
|
|
||||||
assistant = OpenAIAssistant(
|
assistant = OpenAIAssistant(
|
||||||
@@ -28,10 +28,28 @@ assistant = OpenAIAssistant(
|
|||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want to use the existing assistant, you can do something like this:
|
||||||
|
|
||||||
|
```python Initialize
|
||||||
|
# Load an assistant and create a new thread
|
||||||
|
assistant = OpenAIAssistant(assistant_id="asst_xxx")
|
||||||
|
|
||||||
|
# Load a specific thread for an assistant
|
||||||
|
assistant = OpenAIAssistant(assistant_id="asst_xxx", thread_id="thread_xxx")
|
||||||
|
```
|
||||||
|
|
||||||
### Arguments
|
### Arguments
|
||||||
|
|
||||||
<ResponseField name="assistant_id" type="string" required>
|
<ResponseField name="name" type="string">
|
||||||
Load existing OpenAI Assistant. If you pass this, you don't have to pass other arguments
|
Name for your AI assistant
|
||||||
|
</ResponseField>
|
||||||
|
|
||||||
|
<ResponseField name="instructions" type="string">
|
||||||
|
how the Assistant and model should behave or respond
|
||||||
|
</ResponseField>
|
||||||
|
|
||||||
|
<ResponseField name="assistant_id" type="string">
|
||||||
|
Load existing OpenAI Assistant. If you pass this, you don't have to pass other arguments.
|
||||||
</ResponseField>
|
</ResponseField>
|
||||||
|
|
||||||
<ResponseField name="thread_id" type="string">
|
<ResponseField name="thread_id" type="string">
|
||||||
@@ -50,17 +68,21 @@ assistant = OpenAIAssistant(
|
|||||||
Add data sources to your assistant. You can add in the following format: `[{"source": "https://example.com", "data_type": "web_page"}]`
|
Add data sources to your assistant. You can add in the following format: `[{"source": "https://example.com", "data_type": "web_page"}]`
|
||||||
</ResponseField>
|
</ResponseField>
|
||||||
|
|
||||||
|
<ResponseField name="telemetry" type="boolean" default="True">
|
||||||
|
Anonymous telemetry (doesn't collect any user information or user's files). Used to improve the Embedchain package utilization. Default is `True`.
|
||||||
|
</ResponseField>
|
||||||
|
|
||||||
## Step-2: Add data to thread
|
## Step-2: Add data to thread
|
||||||
|
|
||||||
You can add any custom data source that is supported by Embedchain. Else, you can directly pass the file path on your local system and Embedchain propagates it to OpenAI Assistant.
|
You can add any custom data source that is supported by Embedchain. Else, you can directly pass the file path on your local system and Embedchain propagates it to OpenAI Assistant.
|
||||||
```python
|
```python Add data
|
||||||
assistant.add("/path/to/file.pdf")
|
assistant.add("/path/to/file.pdf")
|
||||||
assistant.add("https://www.youtube.com/watch?v=U9mJuUkhUzk", data_type="youtube_video")
|
assistant.add("https://www.youtube.com/watch?v=U9mJuUkhUzk")
|
||||||
assistant.add("https://openai.com/blog/new-models-and-developer-products-announced-at-devday")
|
assistant.add("https://openai.com/blog/new-models-and-developer-products-announced-at-devday")
|
||||||
```
|
```
|
||||||
|
|
||||||
## Step-3: Chat with your Assistant
|
## Step-3: Chat with your Assistant
|
||||||
```python
|
```python Chat
|
||||||
assistant.chat("How much OpenAI credits were offered to attendees during OpenAI DevDay?")
|
assistant.chat("How much OpenAI credits were offered to attendees during OpenAI DevDay?")
|
||||||
# Response: 'Every attendee of OpenAI DevDay 2023 was offered $500 in OpenAI credits.'
|
# Response: 'Every attendee of OpenAI DevDay 2023 was offered $500 in OpenAI credits.'
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -12,74 +12,74 @@ pip install embedchain
|
|||||||
```
|
```
|
||||||
|
|
||||||
<Tip>
|
<Tip>
|
||||||
Embedchain now supports OpenAI's latest `gpt-4-turbo` model. Checkout the [docs here](/get-started/faq#how-to-use-gpt-4-turbo-model-released-on-openai-devday) on how to use it.
|
Embedchain now supports OpenAI's latest `gpt-4-turbo` model. Checkout the [FAQs](/get-started/faq#how-to-use-gpt-4-turbo-model-released-on-openai-devday).
|
||||||
</Tip>
|
</Tip>
|
||||||
|
|
||||||
Creating an app involves 3 steps:
|
Creating an app involves 3 steps:
|
||||||
|
|
||||||
<Steps>
|
<Steps>
|
||||||
<Step title="⚙️ Import app instance">
|
<Step title="⚙️ Import app instance">
|
||||||
```python
|
```python
|
||||||
from embedchain import Pipeline as App
|
from embedchain import Pipeline as App
|
||||||
app = 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).
|
||||||
|
```python
|
||||||
|
from embedchain import Pipeline as App
|
||||||
|
app = App(yaml_config="config.yaml")
|
||||||
|
```
|
||||||
|
</Accordion>
|
||||||
</Step>
|
</Step>
|
||||||
<Step title="🗃️ Add data sources">
|
<Step title="🗃️ Add data sources">
|
||||||
```python
|
```python
|
||||||
# Add different data sources
|
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||||
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
app.add("https://www.forbes.com/profile/elon-musk")
|
||||||
app.add("https://www.forbes.com/profile/elon-musk")
|
# app.add("path/to/file/elon_musk.pdf")
|
||||||
# You can also add local data sources such as pdf, csv files etc.
|
```
|
||||||
# app.add("/path/to/file.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>
|
||||||
<Step title="💬 Query or chat or search context on your data">
|
<Step title="💬 Ask questions, chat, or search through your data with ease">
|
||||||
```python
|
```python
|
||||||
app.query("What is the net worth of Elon Musk today?")
|
app.query("What is the net worth of Elon Musk today?")
|
||||||
# Answer: The net worth of Elon Musk today is $258.7 billion.
|
# Answer: The net worth of Elon Musk today is $258.7 billion.
|
||||||
```
|
```
|
||||||
|
<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>
|
||||||
<Step title="🚀 (Optional) Deploy your pipeline to Embedchain Platform">
|
<Step title="🚀 Seamlessly launch your App on the Embedchain Platform!">
|
||||||
```python
|
```python
|
||||||
app.deploy()
|
app.deploy()
|
||||||
# 🔑 Enter your Embedchain API key. You can find the API key at https://app.embedchain.ai/settings/keys/
|
# 🔑 Enter your Embedchain API key. You can find the API key at https://app.embedchain.ai/settings/keys/
|
||||||
# ec-xxxxxx
|
# ec-xxxxxx
|
||||||
|
|
||||||
# 🛠️ Creating pipeline on the platform...
|
# 🛠️ Creating pipeline on the platform...
|
||||||
# 🎉🎉🎉 Pipeline created successfully! View your pipeline: https://app.embedchain.ai/pipelines/xxxxx
|
# 🎉🎉🎉 Pipeline created successfully! View your pipeline: https://app.embedchain.ai/pipelines/xxxxx
|
||||||
|
|
||||||
# 🛠️ Adding data to your pipeline...
|
# 🛠️ Adding data to your pipeline...
|
||||||
# ✅ Data of type: web_page, value: https://www.forbes.com/profile/elon-musk added successfully.
|
# ✅ 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>
|
</Step>
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
Putting it together, you can run your first app using the following code. Make sure to set the `OPENAI_API_KEY` 🔑 environment variable in the code.
|
Putting it together, you can run your first app using the following Google Colab. Make sure to set the `OPENAI_API_KEY` 🔑 environment variable in the code.
|
||||||
|
|
||||||
```python
|
<a href="https://colab.research.google.com/drive/17ON1LPonnXAtLaZEebnOktstB_1cJJmh?usp=sharing">
|
||||||
import os
|
<img src="https://camo.githubusercontent.com/84f0493939e0c4de4e6dbe113251b4bfb5353e57134ffd9fcab6b8714514d4d1/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667" alt="Open in Colab" />
|
||||||
from embedchain import Pipeline as App
|
</a>
|
||||||
|
|
||||||
os.environ["OPENAI_API_KEY"] = "xxx"
|
|
||||||
app = App()
|
|
||||||
|
|
||||||
# Add different data sources
|
|
||||||
app.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
|
||||||
app.add("https://www.forbes.com/profile/elon-musk")
|
|
||||||
# You can also add local data sources such as pdf, csv files etc.
|
|
||||||
# app.add("/path/to/file.pdf")
|
|
||||||
|
|
||||||
response = app.query("What is the net worth of Elon Musk today?")
|
|
||||||
print(response)
|
|
||||||
# Answer: The net worth of Elon Musk today is $258.7 billion.
|
|
||||||
|
|
||||||
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.
|
|
||||||
```
|
|
||||||
|
|||||||
+4
-1
@@ -87,7 +87,10 @@
|
|||||||
"data-sources/text",
|
"data-sources/text",
|
||||||
"data-sources/web-page",
|
"data-sources/web-page",
|
||||||
"data-sources/openapi",
|
"data-sources/openapi",
|
||||||
"data-sources/youtube-video"
|
"data-sources/youtube-video",
|
||||||
|
"data-sources/discourse",
|
||||||
|
"data-sources/substack",
|
||||||
|
"data-sources/discord"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"data-sources/data-type-handling"
|
"data-sources/data-type-handling"
|
||||||
|
|||||||
@@ -6,3 +6,6 @@ from embedchain.apps.app import App # noqa: F401
|
|||||||
from embedchain.client import Client # noqa: F401
|
from embedchain.client import Client # noqa: F401
|
||||||
from embedchain.pipeline import Pipeline # noqa: F401
|
from embedchain.pipeline import Pipeline # noqa: F401
|
||||||
from embedchain.vectordb.chroma import ChromaDB # noqa: F401
|
from embedchain.vectordb.chroma import ChromaDB # noqa: F401
|
||||||
|
|
||||||
|
# Setup the user directory if doesn't exist already
|
||||||
|
Client.setup_dir()
|
||||||
|
|||||||
@@ -9,10 +9,10 @@ from embedchain.embedchain import EmbedChain
|
|||||||
from embedchain.embedder.base import BaseEmbedder
|
from embedchain.embedder.base import BaseEmbedder
|
||||||
from embedchain.embedder.openai import OpenAIEmbedder
|
from embedchain.embedder.openai import OpenAIEmbedder
|
||||||
from embedchain.factory import EmbedderFactory, LlmFactory, VectorDBFactory
|
from embedchain.factory import EmbedderFactory, LlmFactory, VectorDBFactory
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
from embedchain.llm.openai import OpenAILlm
|
from embedchain.llm.openai import OpenAILlm
|
||||||
from embedchain.utils import validate_yaml_config
|
from embedchain.utils import validate_config
|
||||||
from embedchain.vectordb.base import BaseVectorDB
|
from embedchain.vectordb.base import BaseVectorDB
|
||||||
from embedchain.vectordb.chroma import ChromaDB
|
from embedchain.vectordb.chroma import ChromaDB
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ class App(EmbedChain):
|
|||||||
config_data = yaml.safe_load(file)
|
config_data = yaml.safe_load(file)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
validate_yaml_config(config_data)
|
validate_config(config_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise Exception(f"❌ Error occurred while validating the YAML config. Error: {str(e)}")
|
raise Exception(f"❌ Error occurred while validating the YAML config. Error: {str(e)}")
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from embedchain import App
|
from embedchain import Pipeline as App
|
||||||
from embedchain.config import AddConfig, AppConfig, BaseLlmConfig
|
from embedchain.config import AddConfig, BaseLlmConfig, PipelineConfig
|
||||||
from embedchain.embedder.openai import OpenAIEmbedder
|
from embedchain.embedder.openai import OpenAIEmbedder
|
||||||
from embedchain.helper.json_serializable import (JSONSerializable,
|
from embedchain.helpers.json_serializable import (JSONSerializable,
|
||||||
register_deserializable)
|
register_deserializable)
|
||||||
from embedchain.llm.openai import OpenAILlm
|
from embedchain.llm.openai import OpenAILlm
|
||||||
from embedchain.vectordb.chroma import ChromaDB
|
from embedchain.vectordb.chroma import ChromaDB
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ from embedchain.vectordb.chroma import ChromaDB
|
|||||||
@register_deserializable
|
@register_deserializable
|
||||||
class BaseBot(JSONSerializable):
|
class BaseBot(JSONSerializable):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.app = App(config=AppConfig(), llm=OpenAILlm(), db=ChromaDB(), embedder=OpenAIEmbedder())
|
self.app = App(config=PipelineConfig(), llm=OpenAILlm(), db=ChromaDB(), embedding_model=OpenAIEmbedder())
|
||||||
|
|
||||||
def add(self, data: Any, config: AddConfig = None):
|
def add(self, data: Any, config: AddConfig = None):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import argparse
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
from .base import BaseBot
|
from .base import BaseBot
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
from .base import BaseBot
|
from .base import BaseBot
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import signal
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
from embedchain import App
|
from embedchain import App
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
from .base import BaseBot
|
from .base import BaseBot
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import logging
|
|||||||
import signal
|
import signal
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
from .base import BaseBot
|
from .base import BaseBot
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import JSONSerializable
|
from embedchain.helpers.json_serializable import JSONSerializable
|
||||||
from embedchain.models.data_type import DataType
|
from embedchain.models.data_type import DataType
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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 CommonChunker(BaseChunker):
|
||||||
|
"""Common chunker for all loaders."""
|
||||||
|
|
||||||
|
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 DiscourseChunker(BaseChunker):
|
||||||
|
"""Chunker for discourse."""
|
||||||
|
|
||||||
|
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)
|
||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -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 MySQLChunker(BaseChunker):
|
||||||
|
"""Chunker for json."""
|
||||||
|
|
||||||
|
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)
|
||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -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 PostgresChunker(BaseChunker):
|
||||||
|
"""Chunker for postgres."""
|
||||||
|
|
||||||
|
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)
|
||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -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 SlackChunker(BaseChunker):
|
||||||
|
"""Chunker for postgres."""
|
||||||
|
|
||||||
|
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 SubstackChunker(BaseChunker):
|
||||||
|
"""Chunker for Substack."""
|
||||||
|
|
||||||
|
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)
|
||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.text_splitter import RecursiveCharacterTextSplitter
|
|||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config.add_config import ChunkerConfig
|
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
|
@register_deserializable
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import uuid
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from embedchain.embedchain import CONFIG_DIR, CONFIG_FILE
|
from embedchain.constants import CONFIG_DIR, CONFIG_FILE
|
||||||
|
|
||||||
|
|
||||||
class Client:
|
class Client:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ from importlib import import_module
|
|||||||
from typing import Callable, Optional
|
from typing import Callable, Optional
|
||||||
|
|
||||||
from embedchain.config.base_config import BaseConfig
|
from embedchain.config.base_config import BaseConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
from .base_app_config import BaseAppConfig
|
from .base_app_config import BaseAppConfig
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import logging
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.config.base_config import BaseConfig
|
from embedchain.config.base_config import BaseConfig
|
||||||
from embedchain.helper.json_serializable import JSONSerializable
|
from embedchain.helpers.json_serializable import JSONSerializable
|
||||||
from embedchain.vectordb.base import BaseVectorDB
|
from embedchain.vectordb.base import BaseVectorDB
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import JSONSerializable
|
from embedchain.helpers.json_serializable import JSONSerializable
|
||||||
|
|
||||||
|
|
||||||
class BaseConfig(JSONSerializable):
|
class BaseConfig(JSONSerializable):
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import re
|
import re
|
||||||
from string import Template
|
from string import Template
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from embedchain.config.base_config import BaseConfig
|
from embedchain.config.base_config import BaseConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
DEFAULT_PROMPT = """
|
DEFAULT_PROMPT = """
|
||||||
Use the following pieces of context to answer the query at the end.
|
Use the following pieces of context to answer the query at the end.
|
||||||
@@ -68,6 +68,7 @@ class BaseLlmConfig(BaseConfig):
|
|||||||
system_prompt: Optional[str] = None,
|
system_prompt: Optional[str] = None,
|
||||||
where: Dict[str, Any] = None,
|
where: Dict[str, Any] = None,
|
||||||
query_type: Optional[str] = None,
|
query_type: Optional[str] = None,
|
||||||
|
callbacks: Optional[List] = None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Initializes a configuration class instance for the LLM.
|
Initializes a configuration class instance for the LLM.
|
||||||
@@ -98,6 +99,8 @@ class BaseLlmConfig(BaseConfig):
|
|||||||
:type system_prompt: Optional[str], optional
|
:type system_prompt: Optional[str], optional
|
||||||
:param where: A dictionary of key-value pairs to filter the database results., defaults to None
|
:param where: A dictionary of key-value pairs to filter the database results., defaults to None
|
||||||
:type where: Dict[str, Any], optional
|
:type where: Dict[str, Any], optional
|
||||||
|
:param callbacks: Langchain callback functions to use, defaults to None
|
||||||
|
:type callbacks: Optional[List], optional
|
||||||
:raises ValueError: If the template is not valid as template should
|
:raises ValueError: If the template is not valid as template should
|
||||||
contain $context and $query (and optionally $history)
|
contain $context and $query (and optionally $history)
|
||||||
:raises ValueError: Stream is not boolean
|
:raises ValueError: Stream is not boolean
|
||||||
@@ -113,6 +116,7 @@ class BaseLlmConfig(BaseConfig):
|
|||||||
self.deployment_name = deployment_name
|
self.deployment_name = deployment_name
|
||||||
self.system_prompt = system_prompt
|
self.system_prompt = system_prompt
|
||||||
self.query_type = query_type
|
self.query_type = query_type
|
||||||
|
self.callbacks = callbacks
|
||||||
|
|
||||||
if type(template) is str:
|
if type(template) is str:
|
||||||
template = Template(template)
|
template = Template(template)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
from .apps.base_app_config import BaseAppConfig
|
from .apps.base_app_config import BaseAppConfig
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
from typing import Dict, List, Optional, Union
|
from typing import Dict, List, Optional, Union
|
||||||
|
|
||||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Dict, Optional, Tuple
|
from typing import Dict, Optional, Tuple
|
||||||
|
|
||||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import os
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
from embedchain.config.vectordb.base import BaseVectorDbConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
|
||||||
|
|
||||||
@register_deserializable
|
@register_deserializable
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ABS_PATH = os.getcwd()
|
||||||
|
HOME_DIR = str(Path.home())
|
||||||
|
CONFIG_DIR = os.path.join(HOME_DIR, ".embedchain")
|
||||||
|
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
|
||||||
|
SQLITE_PATH = os.path.join(CONFIG_DIR, "embedchain.db")
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
from importlib import import_module
|
from importlib import import_module
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config import AddConfig
|
from embedchain.config import AddConfig
|
||||||
from embedchain.config.add_config import ChunkerConfig, LoaderConfig
|
from embedchain.config.add_config import ChunkerConfig, LoaderConfig
|
||||||
from embedchain.helper.json_serializable import JSONSerializable
|
from embedchain.helpers.json_serializable import JSONSerializable
|
||||||
from embedchain.loaders.base_loader import BaseLoader
|
from embedchain.loaders.base_loader import BaseLoader
|
||||||
from embedchain.models.data_type import DataType
|
from embedchain.models.data_type import DataType
|
||||||
|
|
||||||
@@ -15,7 +16,7 @@ class DataFormatter(JSONSerializable):
|
|||||||
.add or .add_local method call
|
.add or .add_local method call
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, data_type: DataType, config: AddConfig):
|
def __init__(self, data_type: DataType, config: AddConfig, kwargs: Dict[str, Any]):
|
||||||
"""
|
"""
|
||||||
Initialize a dataformatter, set data type and chunker based on datatype.
|
Initialize a dataformatter, set data type and chunker based on datatype.
|
||||||
|
|
||||||
@@ -24,15 +25,15 @@ class DataFormatter(JSONSerializable):
|
|||||||
:param config: AddConfig instance with nested loader and chunker config attributes.
|
:param config: AddConfig instance with nested loader and chunker config attributes.
|
||||||
:type config: AddConfig
|
:type config: AddConfig
|
||||||
"""
|
"""
|
||||||
self.loader = self._get_loader(data_type=data_type, config=config.loader)
|
self.loader = self._get_loader(data_type=data_type, config=config.loader, kwargs=kwargs)
|
||||||
self.chunker = self._get_chunker(data_type=data_type, config=config.chunker)
|
self.chunker = self._get_chunker(data_type=data_type, config=config.chunker, kwargs=kwargs)
|
||||||
|
|
||||||
def _lazy_load(self, module_path: str):
|
def _lazy_load(self, module_path: str):
|
||||||
module_path, class_name = module_path.rsplit(".", 1)
|
module_path, class_name = module_path.rsplit(".", 1)
|
||||||
module = import_module(module_path)
|
module = import_module(module_path)
|
||||||
return getattr(module, class_name)
|
return getattr(module, class_name)
|
||||||
|
|
||||||
def _get_loader(self, data_type: DataType, config: LoaderConfig) -> BaseLoader:
|
def _get_loader(self, data_type: DataType, config: LoaderConfig, kwargs: Dict[str, Any]) -> BaseLoader:
|
||||||
"""
|
"""
|
||||||
Returns the appropriate data loader for the given data type.
|
Returns the appropriate data loader for the given data type.
|
||||||
|
|
||||||
@@ -62,14 +63,36 @@ class DataFormatter(JSONSerializable):
|
|||||||
DataType.OPENAPI: "embedchain.loaders.openapi.OpenAPILoader",
|
DataType.OPENAPI: "embedchain.loaders.openapi.OpenAPILoader",
|
||||||
DataType.GMAIL: "embedchain.loaders.gmail.GmailLoader",
|
DataType.GMAIL: "embedchain.loaders.gmail.GmailLoader",
|
||||||
DataType.NOTION: "embedchain.loaders.notion.NotionLoader",
|
DataType.NOTION: "embedchain.loaders.notion.NotionLoader",
|
||||||
|
DataType.SUBSTACK: "embedchain.loaders.substack.SubstackLoader",
|
||||||
|
DataType.GITHUB: "embedchain.loaders.github.GithubLoader",
|
||||||
|
DataType.YOUTUBE_CHANNEL: "embedchain.loaders.youtube_channel.YoutubeChannelLoader",
|
||||||
|
DataType.DISCORD: "embedchain.loaders.discord.DiscordLoader",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_loaders = set(
|
||||||
|
[
|
||||||
|
DataType.POSTGRES,
|
||||||
|
DataType.MYSQL,
|
||||||
|
DataType.SLACK,
|
||||||
|
DataType.DISCOURSE,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
if data_type in loaders:
|
if data_type in loaders:
|
||||||
loader_class: type = self._lazy_load(loaders[data_type])
|
loader_class: type = self._lazy_load(loaders[data_type])
|
||||||
return loader_class()
|
return loader_class()
|
||||||
else:
|
elif data_type in custom_loaders:
|
||||||
raise ValueError(f"Unsupported data type: {data_type}")
|
loader_class: type = kwargs.get("loader", None)
|
||||||
|
if loader_class is not None:
|
||||||
|
return loader_class
|
||||||
|
|
||||||
def _get_chunker(self, data_type: DataType, config: ChunkerConfig) -> BaseChunker:
|
raise ValueError(
|
||||||
|
f"Cant find the loader for {data_type}.\
|
||||||
|
We recommend to pass the loader to use data_type: {data_type},\
|
||||||
|
check `https://docs.embedchain.ai/data-sources/overview`."
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_chunker(self, data_type: DataType, config: ChunkerConfig, kwargs: Dict[str, Any]) -> BaseChunker:
|
||||||
"""Returns the appropriate chunker for the given data type (updated for lazy loading)."""
|
"""Returns the appropriate chunker for the given data type (updated for lazy loading)."""
|
||||||
chunker_classes = {
|
chunker_classes = {
|
||||||
DataType.YOUTUBE_VIDEO: "embedchain.chunkers.youtube_video.YoutubeVideoChunker",
|
DataType.YOUTUBE_VIDEO: "embedchain.chunkers.youtube_video.YoutubeVideoChunker",
|
||||||
@@ -89,12 +112,28 @@ class DataFormatter(JSONSerializable):
|
|||||||
DataType.OPENAPI: "embedchain.chunkers.openapi.OpenAPIChunker",
|
DataType.OPENAPI: "embedchain.chunkers.openapi.OpenAPIChunker",
|
||||||
DataType.GMAIL: "embedchain.chunkers.gmail.GmailChunker",
|
DataType.GMAIL: "embedchain.chunkers.gmail.GmailChunker",
|
||||||
DataType.NOTION: "embedchain.chunkers.notion.NotionChunker",
|
DataType.NOTION: "embedchain.chunkers.notion.NotionChunker",
|
||||||
|
DataType.POSTGRES: "embedchain.chunkers.postgres.PostgresChunker",
|
||||||
|
DataType.MYSQL: "embedchain.chunkers.mysql.MySQLChunker",
|
||||||
|
DataType.SLACK: "embedchain.chunkers.slack.SlackChunker",
|
||||||
|
DataType.DISCOURSE: "embedchain.chunkers.discourse.DiscourseChunker",
|
||||||
|
DataType.SUBSTACK: "embedchain.chunkers.substack.SubstackChunker",
|
||||||
|
DataType.GITHUB: "embedchain.chunkers.common_chunker.CommonChunker",
|
||||||
|
DataType.YOUTUBE_CHANNEL: "embedchain.chunkers.common_chunker.CommonChunker",
|
||||||
|
DataType.DISCORD: "embedchain.chunkers.common_chunker.CommonChunker",
|
||||||
}
|
}
|
||||||
|
|
||||||
if data_type in chunker_classes:
|
if data_type in chunker_classes:
|
||||||
chunker_class = self._lazy_load(chunker_classes[data_type])
|
if "chunker" in kwargs:
|
||||||
|
chunker_class = kwargs.get("chunker")
|
||||||
|
else:
|
||||||
|
chunker_class = self._lazy_load(chunker_classes[data_type])
|
||||||
|
|
||||||
chunker = chunker_class(config)
|
chunker = chunker_class(config)
|
||||||
chunker.set_data_type(data_type)
|
chunker.set_data_type(data_type)
|
||||||
return chunker
|
return chunker
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Unsupported data type: {data_type}")
|
raise ValueError(
|
||||||
|
f"Cant find the chunker for {data_type}.\
|
||||||
|
We recommend to pass the chunker to use data_type: {data_type},\
|
||||||
|
check `https://docs.embedchain.ai/data-sources/overview`."
|
||||||
|
)
|
||||||
|
|||||||
+43
-35
@@ -1,9 +1,7 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
from pathlib import Path
|
|
||||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
@@ -12,9 +10,10 @@ from langchain.docstore.document import Document
|
|||||||
from embedchain.chunkers.base_chunker import BaseChunker
|
from embedchain.chunkers.base_chunker import BaseChunker
|
||||||
from embedchain.config import AddConfig, BaseLlmConfig, ChunkerConfig
|
from embedchain.config import AddConfig, BaseLlmConfig, ChunkerConfig
|
||||||
from embedchain.config.apps.base_app_config import BaseAppConfig
|
from embedchain.config.apps.base_app_config import BaseAppConfig
|
||||||
|
from embedchain.constants import SQLITE_PATH
|
||||||
from embedchain.data_formatter import DataFormatter
|
from embedchain.data_formatter import DataFormatter
|
||||||
from embedchain.embedder.base import BaseEmbedder
|
from embedchain.embedder.base import BaseEmbedder
|
||||||
from embedchain.helper.json_serializable import JSONSerializable
|
from embedchain.helpers.json_serializable import JSONSerializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
from embedchain.loaders.base_loader import BaseLoader
|
from embedchain.loaders.base_loader import BaseLoader
|
||||||
from embedchain.models.data_type import (DataType, DirectDataType,
|
from embedchain.models.data_type import (DataType, DirectDataType,
|
||||||
@@ -25,12 +24,6 @@ from embedchain.vectordb.base import BaseVectorDB
|
|||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
ABS_PATH = os.getcwd()
|
|
||||||
HOME_DIR = str(Path.home())
|
|
||||||
CONFIG_DIR = os.path.join(HOME_DIR, ".embedchain")
|
|
||||||
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
|
|
||||||
SQLITE_PATH = os.path.join(CONFIG_DIR, "embedchain.db")
|
|
||||||
|
|
||||||
|
|
||||||
class EmbedChain(JSONSerializable):
|
class EmbedChain(JSONSerializable):
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -81,6 +74,9 @@ class EmbedChain(JSONSerializable):
|
|||||||
if system_prompt:
|
if system_prompt:
|
||||||
self.llm.config.system_prompt = system_prompt
|
self.llm.config.system_prompt = system_prompt
|
||||||
|
|
||||||
|
# Fetch the history from the database if exists
|
||||||
|
self.llm.update_history(app_id=self.config.id)
|
||||||
|
|
||||||
# Attributes that aren't subclass related.
|
# Attributes that aren't subclass related.
|
||||||
self.user_asks = []
|
self.user_asks = []
|
||||||
|
|
||||||
@@ -137,6 +133,7 @@ class EmbedChain(JSONSerializable):
|
|||||||
metadata: Optional[Dict[str, Any]] = None,
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
config: Optional[AddConfig] = None,
|
config: Optional[AddConfig] = None,
|
||||||
dry_run=False,
|
dry_run=False,
|
||||||
|
**kwargs: Dict[str, Any],
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Adds the data from the given URL to the vector db.
|
Adds the data from the given URL to the vector db.
|
||||||
@@ -180,21 +177,6 @@ class EmbedChain(JSONSerializable):
|
|||||||
if data_type:
|
if data_type:
|
||||||
try:
|
try:
|
||||||
data_type = DataType(data_type)
|
data_type = DataType(data_type)
|
||||||
if data_type == DataType.JSON:
|
|
||||||
if isinstance(source, str):
|
|
||||||
if not is_valid_json_string(source):
|
|
||||||
raise ValueError(
|
|
||||||
f"Invalid json input: {source}",
|
|
||||||
"Provide the correct JSON formatted source, \
|
|
||||||
refer `https://docs.embedchain.ai/data-sources/json`",
|
|
||||||
)
|
|
||||||
elif not isinstance(source, str):
|
|
||||||
raise ValueError(
|
|
||||||
"Invaid content input. \
|
|
||||||
If you want to upload (list, dict, etc.), do \
|
|
||||||
`json.dump(data, indent=0)` and add the stringified JSON. \
|
|
||||||
Check - `https://docs.embedchain.ai/data-sources/json`"
|
|
||||||
)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Invalid data_type: '{data_type}'.",
|
f"Invalid data_type: '{data_type}'.",
|
||||||
@@ -218,9 +200,10 @@ class EmbedChain(JSONSerializable):
|
|||||||
print(f"Data with hash {source_hash} already exists. Skipping addition.")
|
print(f"Data with hash {source_hash} already exists. Skipping addition.")
|
||||||
return source_hash
|
return source_hash
|
||||||
|
|
||||||
data_formatter = DataFormatter(data_type, config)
|
|
||||||
self.user_asks.append([source, data_type.value, metadata])
|
self.user_asks.append([source, data_type.value, metadata])
|
||||||
documents, metadatas, _ids, new_chunks = self.load_and_embed(
|
|
||||||
|
data_formatter = DataFormatter(data_type, config, kwargs)
|
||||||
|
documents, metadatas, _ids, new_chunks = self._load_and_embed(
|
||||||
data_formatter.loader, data_formatter.chunker, source, metadata, source_hash, dry_run
|
data_formatter.loader, data_formatter.chunker, source, metadata, source_hash, dry_run
|
||||||
)
|
)
|
||||||
if data_type in {DataType.DOCS_SITE}:
|
if data_type in {DataType.DOCS_SITE}:
|
||||||
@@ -265,6 +248,7 @@ class EmbedChain(JSONSerializable):
|
|||||||
data_type: Optional[DataType] = None,
|
data_type: Optional[DataType] = None,
|
||||||
metadata: Optional[Dict[str, Any]] = None,
|
metadata: Optional[Dict[str, Any]] = None,
|
||||||
config: Optional[AddConfig] = None,
|
config: Optional[AddConfig] = None,
|
||||||
|
**kwargs: Dict[str, Any],
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Adds the data from the given URL to the vector db.
|
Adds the data from the given URL to the vector db.
|
||||||
@@ -290,7 +274,13 @@ class EmbedChain(JSONSerializable):
|
|||||||
logging.warning(
|
logging.warning(
|
||||||
"The `add_local` method is deprecated and will be removed in future versions. Please use the `add` method for both local and remote files." # noqa: E501
|
"The `add_local` method is deprecated and will be removed in future versions. Please use the `add` method for both local and remote files." # noqa: E501
|
||||||
)
|
)
|
||||||
return self.add(source=source, data_type=data_type, metadata=metadata, config=config)
|
return self.add(
|
||||||
|
source=source,
|
||||||
|
data_type=data_type,
|
||||||
|
metadata=metadata,
|
||||||
|
config=config,
|
||||||
|
kwargs=kwargs,
|
||||||
|
)
|
||||||
|
|
||||||
def _get_existing_doc_id(self, chunker: BaseChunker, src: Any):
|
def _get_existing_doc_id(self, chunker: BaseChunker, src: Any):
|
||||||
"""
|
"""
|
||||||
@@ -350,7 +340,7 @@ class EmbedChain(JSONSerializable):
|
|||||||
"When it should be DirectDataType, IndirectDataType or SpecialDataType."
|
"When it should be DirectDataType, IndirectDataType or SpecialDataType."
|
||||||
)
|
)
|
||||||
|
|
||||||
def load_and_embed(
|
def _load_and_embed(
|
||||||
self,
|
self,
|
||||||
loader: BaseLoader,
|
loader: BaseLoader,
|
||||||
chunker: BaseChunker,
|
chunker: BaseChunker,
|
||||||
@@ -467,7 +457,7 @@ class EmbedChain(JSONSerializable):
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
def retrieve_from_database(
|
def _retrieve_from_database(
|
||||||
self, input_query: str, config: Optional[BaseLlmConfig] = None, where=None, citations: bool = False
|
self, input_query: str, config: Optional[BaseLlmConfig] = None, where=None, citations: bool = False
|
||||||
) -> Union[List[Tuple[str, str, str]], List[str]]:
|
) -> Union[List[Tuple[str, str, str]], List[str]]:
|
||||||
"""
|
"""
|
||||||
@@ -488,13 +478,13 @@ class EmbedChain(JSONSerializable):
|
|||||||
query_config = config or self.llm.config
|
query_config = config or self.llm.config
|
||||||
if where is not None:
|
if where is not None:
|
||||||
where = where
|
where = where
|
||||||
elif query_config is not None and query_config.where is not None:
|
|
||||||
where = query_config.where
|
|
||||||
else:
|
else:
|
||||||
where = {}
|
where = {}
|
||||||
|
if query_config is not None and query_config.where is not None:
|
||||||
|
where = query_config.where
|
||||||
|
|
||||||
if self.config.id is not None:
|
if self.config.id is not None:
|
||||||
where.update({"app_id": self.config.id})
|
where.update({"app_id": self.config.id})
|
||||||
|
|
||||||
# We cannot query the database with the input query in case of an image search. This is because we need
|
# We cannot query the database with the input query in case of an image search. This is because we need
|
||||||
# to bring down both the image and text to the same dimension to be able to compare them.
|
# to bring down both the image and text to the same dimension to be able to compare them.
|
||||||
@@ -547,7 +537,9 @@ class EmbedChain(JSONSerializable):
|
|||||||
:rtype: str, if citations is False, otherwise Tuple[str,List[Tuple[str,str,str]]]
|
:rtype: str, if citations is False, otherwise Tuple[str,List[Tuple[str,str,str]]]
|
||||||
"""
|
"""
|
||||||
citations = kwargs.get("citations", False)
|
citations = kwargs.get("citations", False)
|
||||||
contexts = self.retrieve_from_database(input_query=input_query, config=config, where=where, citations=citations)
|
contexts = self._retrieve_from_database(
|
||||||
|
input_query=input_query, config=config, where=where, citations=citations
|
||||||
|
)
|
||||||
if citations and len(contexts) > 0 and isinstance(contexts[0], tuple):
|
if citations and len(contexts) > 0 and isinstance(contexts[0], tuple):
|
||||||
contexts_data_for_llm_query = list(map(lambda x: x[0], contexts))
|
contexts_data_for_llm_query = list(map(lambda x: x[0], contexts))
|
||||||
else:
|
else:
|
||||||
@@ -598,7 +590,9 @@ class EmbedChain(JSONSerializable):
|
|||||||
:rtype: str, if citations is False, otherwise Tuple[str,List[Tuple[str,str,str]]]
|
:rtype: str, if citations is False, otherwise Tuple[str,List[Tuple[str,str,str]]]
|
||||||
"""
|
"""
|
||||||
citations = kwargs.get("citations", False)
|
citations = kwargs.get("citations", False)
|
||||||
contexts = self.retrieve_from_database(input_query=input_query, config=config, where=where, citations=citations)
|
contexts = self._retrieve_from_database(
|
||||||
|
input_query=input_query, config=config, where=where, citations=citations
|
||||||
|
)
|
||||||
if citations and len(contexts) > 0 and isinstance(contexts[0], tuple):
|
if citations and len(contexts) > 0 and isinstance(contexts[0], tuple):
|
||||||
contexts_data_for_llm_query = list(map(lambda x: x[0], contexts))
|
contexts_data_for_llm_query = list(map(lambda x: x[0], contexts))
|
||||||
else:
|
else:
|
||||||
@@ -608,6 +602,9 @@ class EmbedChain(JSONSerializable):
|
|||||||
input_query=input_query, contexts=contexts_data_for_llm_query, config=config, dry_run=dry_run
|
input_query=input_query, contexts=contexts_data_for_llm_query, config=config, dry_run=dry_run
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# add conversation in memory
|
||||||
|
self.llm.add_history(self.config.id, input_query, answer)
|
||||||
|
|
||||||
# Send anonymous telemetry
|
# Send anonymous telemetry
|
||||||
self.telemetry.capture(event_name="chat", properties=self._telemetry_props)
|
self.telemetry.capture(event_name="chat", properties=self._telemetry_props)
|
||||||
|
|
||||||
@@ -651,5 +648,16 @@ class EmbedChain(JSONSerializable):
|
|||||||
self.db.reset()
|
self.db.reset()
|
||||||
self.cursor.execute("DELETE FROM data_sources WHERE pipeline_id = ?", (self.config.id,))
|
self.cursor.execute("DELETE FROM data_sources WHERE pipeline_id = ?", (self.config.id,))
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
|
self.delete_history()
|
||||||
# Send anonymous telemetry
|
# Send anonymous telemetry
|
||||||
self.telemetry.capture(event_name="reset", properties=self._telemetry_props)
|
self.telemetry.capture(event_name="reset", properties=self._telemetry_props)
|
||||||
|
|
||||||
|
def get_history(self, num_rounds: int = 10, display_format: bool = True):
|
||||||
|
return self.llm.memory.get_recent_memories(
|
||||||
|
app_id=self.config.id,
|
||||||
|
num_rounds=num_rounds,
|
||||||
|
display_format=display_format,
|
||||||
|
)
|
||||||
|
|
||||||
|
def delete_history(self):
|
||||||
|
self.llm.memory.delete_chat_history(app_id=self.config.id)
|
||||||
|
|||||||
@@ -3,12 +3,20 @@ from typing import Any, Callable, Optional
|
|||||||
from embedchain.config.embedder.base import BaseEmbedderConfig
|
from embedchain.config.embedder.base import BaseEmbedderConfig
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from chromadb.api.types import Documents, Embeddings
|
from chromadb.api.types import Embeddable, EmbeddingFunction, Embeddings
|
||||||
except RuntimeError:
|
except RuntimeError:
|
||||||
from embedchain.utils import use_pysqlite3
|
from embedchain.utils import use_pysqlite3
|
||||||
|
|
||||||
use_pysqlite3()
|
use_pysqlite3()
|
||||||
from chromadb.api.types import Documents, Embeddings
|
from chromadb.api.types import Embeddable, EmbeddingFunction, Embeddings
|
||||||
|
|
||||||
|
|
||||||
|
class EmbeddingFunc(EmbeddingFunction):
|
||||||
|
def __init__(self, embedding_fn: Callable[[list[str]], list[str]]):
|
||||||
|
self.embedding_fn = embedding_fn
|
||||||
|
|
||||||
|
def __call__(self, input: Embeddable) -> Embeddings:
|
||||||
|
return self.embedding_fn(input)
|
||||||
|
|
||||||
|
|
||||||
class BaseEmbedder:
|
class BaseEmbedder:
|
||||||
@@ -66,7 +74,4 @@ class BaseEmbedder:
|
|||||||
:rtype: Callable
|
:rtype: Callable
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def embed_function(texts: Documents) -> Embeddings:
|
return EmbeddingFunc(embeddings.embed_documents)
|
||||||
return embeddings.embed_documents(texts)
|
|
||||||
|
|
||||||
return embed_function
|
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
"""
|
|
||||||
Note that this file is copied from Chroma repository. We will remove this file once the fix in
|
|
||||||
ChromaDB's repository.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from chromadb.api.types import Documents, Embeddings
|
|
||||||
|
|
||||||
|
|
||||||
class OpenAIEmbeddingFunction:
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
api_key: Optional[str] = None,
|
|
||||||
model_name: str = "text-embedding-ada-002",
|
|
||||||
organization_id: Optional[str] = None,
|
|
||||||
api_base: Optional[str] = None,
|
|
||||||
api_type: Optional[str] = None,
|
|
||||||
api_version: Optional[str] = None,
|
|
||||||
deployment_id: Optional[str] = None,
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Initialize the OpenAIEmbeddingFunction.
|
|
||||||
Args:
|
|
||||||
api_key (str, optional): Your API key for the OpenAI API. If not
|
|
||||||
provided, it will raise an error to provide an OpenAI API key.
|
|
||||||
organization_id(str, optional): The OpenAI organization ID if applicable
|
|
||||||
model_name (str, optional): The name of the model to use for text
|
|
||||||
embeddings. Defaults to "text-embedding-ada-002".
|
|
||||||
api_base (str, optional): The base path for the API. If not provided,
|
|
||||||
it will use the base path for the OpenAI API. This can be used to
|
|
||||||
point to a different deployment, such as an Azure deployment.
|
|
||||||
api_type (str, optional): The type of the API deployment. This can be
|
|
||||||
used to specify a different deployment, such as 'azure'. If not
|
|
||||||
provided, it will use the default OpenAI deployment.
|
|
||||||
api_version (str, optional): The api version for the API. If not provided,
|
|
||||||
it will use the api version for the OpenAI API. This can be used to
|
|
||||||
point to a different deployment, such as an Azure deployment.
|
|
||||||
deployment_id (str, optional): Deployment ID for Azure OpenAI.
|
|
||||||
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
import openai
|
|
||||||
except ImportError:
|
|
||||||
raise ValueError("The openai python package is not installed. Please install it with `pip install openai`")
|
|
||||||
|
|
||||||
if api_key is not None:
|
|
||||||
openai.api_key = api_key
|
|
||||||
# If the api key is still not set, raise an error
|
|
||||||
elif openai.api_key is None:
|
|
||||||
raise ValueError(
|
|
||||||
"Please provide an OpenAI API key. You can get one at https://platform.openai.com/account/api-keys"
|
|
||||||
)
|
|
||||||
|
|
||||||
if api_base is not None:
|
|
||||||
openai.api_base = api_base
|
|
||||||
|
|
||||||
if api_version is not None:
|
|
||||||
openai.api_version = api_version
|
|
||||||
|
|
||||||
self._api_type = api_type
|
|
||||||
if api_type is not None:
|
|
||||||
openai.api_type = api_type
|
|
||||||
|
|
||||||
if organization_id is not None:
|
|
||||||
openai.organization = organization_id
|
|
||||||
|
|
||||||
self._v1 = openai.__version__.startswith("1.")
|
|
||||||
if self._v1:
|
|
||||||
if api_type == "azure":
|
|
||||||
self._client = openai.AzureOpenAI(
|
|
||||||
api_key=api_key, api_version=api_version, azure_endpoint=api_base
|
|
||||||
).embeddings
|
|
||||||
else:
|
|
||||||
self._client = openai.OpenAI(api_key=api_key, base_url=api_base).embeddings
|
|
||||||
else:
|
|
||||||
self._client = openai.Embedding
|
|
||||||
self._model_name = model_name
|
|
||||||
self._deployment_id = deployment_id
|
|
||||||
|
|
||||||
def __call__(self, input: Documents) -> Embeddings:
|
|
||||||
# replace newlines, which can negatively affect performance.
|
|
||||||
input = [t.replace("\n", " ") for t in input]
|
|
||||||
|
|
||||||
# Call the OpenAI Embedding API
|
|
||||||
if self._v1:
|
|
||||||
embeddings = self._client.create(input=input, model=self._deployment_id or self._model_name).data
|
|
||||||
|
|
||||||
# Sort resulting embeddings by index
|
|
||||||
sorted_embeddings = sorted(embeddings, key=lambda e: e.index) # type: ignore
|
|
||||||
|
|
||||||
# Return just the embeddings
|
|
||||||
return [result.embedding for result in sorted_embeddings]
|
|
||||||
else:
|
|
||||||
if self._api_type == "azure":
|
|
||||||
embeddings = self._client.create(input=input, engine=self._deployment_id or self._model_name)["data"]
|
|
||||||
else:
|
|
||||||
embeddings = self._client.create(input=input, model=self._model_name)["data"]
|
|
||||||
|
|
||||||
# Sort resulting embeddings by index
|
|
||||||
sorted_embeddings = sorted(embeddings, key=lambda e: e["index"]) # type: ignore
|
|
||||||
|
|
||||||
# Return just the embeddings
|
|
||||||
return [result["embedding"] for result in sorted_embeddings]
|
|
||||||
@@ -1,23 +1,23 @@
|
|||||||
import os
|
import os
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from langchain.embeddings import OpenAIEmbeddings
|
from chromadb.utils.embedding_functions import OpenAIEmbeddingFunction
|
||||||
|
from langchain.embeddings import AzureOpenAIEmbeddings
|
||||||
|
|
||||||
from embedchain.config import BaseEmbedderConfig
|
from embedchain.config import BaseEmbedderConfig
|
||||||
from embedchain.embedder.base import BaseEmbedder
|
from embedchain.embedder.base import BaseEmbedder
|
||||||
from embedchain.models import VectorDimensions
|
from embedchain.models import VectorDimensions
|
||||||
|
|
||||||
from .chroma_embeddings import OpenAIEmbeddingFunction
|
|
||||||
|
|
||||||
|
|
||||||
class OpenAIEmbedder(BaseEmbedder):
|
class OpenAIEmbedder(BaseEmbedder):
|
||||||
def __init__(self, config: Optional[BaseEmbedderConfig] = None):
|
def __init__(self, config: Optional[BaseEmbedderConfig] = None):
|
||||||
super().__init__(config=config)
|
super().__init__(config=config)
|
||||||
|
|
||||||
if self.config.model is None:
|
if self.config.model is None:
|
||||||
self.config.model = "text-embedding-ada-002"
|
self.config.model = "text-embedding-ada-002"
|
||||||
|
|
||||||
if self.config.deployment_name:
|
if self.config.deployment_name:
|
||||||
embeddings = OpenAIEmbeddings(deployment=self.config.deployment_name)
|
embeddings = AzureOpenAIEmbeddings(deployment=self.config.deployment_name)
|
||||||
embedding_fn = BaseEmbedder._langchain_default_concept(embeddings)
|
embedding_fn = BaseEmbedder._langchain_default_concept(embeddings)
|
||||||
else:
|
else:
|
||||||
if os.getenv("OPENAI_API_KEY") is None and os.getenv("OPENAI_ORGANIZATION") is None:
|
if os.getenv("OPENAI_API_KEY") is None and os.getenv("OPENAI_ORGANIZATION") is None:
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import queue
|
||||||
|
from typing import Any, Dict, List, Union
|
||||||
|
|
||||||
|
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
||||||
|
from langchain.schema import LLMResult
|
||||||
|
|
||||||
|
STOP_ITEM = "[END]"
|
||||||
|
"""
|
||||||
|
This is a special item that is used to signal the end of the stream.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class StreamingStdOutCallbackHandlerYield(StreamingStdOutCallbackHandler):
|
||||||
|
"""
|
||||||
|
This is a callback handler that yields the tokens as they are generated.
|
||||||
|
For a usage example, see the :func:`generate` function below.
|
||||||
|
"""
|
||||||
|
|
||||||
|
q: queue.Queue
|
||||||
|
"""
|
||||||
|
The queue to write the tokens to as they are generated.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, q: queue.Queue) -> None:
|
||||||
|
"""
|
||||||
|
Initialize the callback handler.
|
||||||
|
q: The queue to write the tokens to as they are generated.
|
||||||
|
"""
|
||||||
|
super().__init__()
|
||||||
|
self.q = q
|
||||||
|
|
||||||
|
def on_llm_start(self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any) -> None:
|
||||||
|
"""Run when LLM starts running."""
|
||||||
|
with self.q.mutex:
|
||||||
|
self.q.queue.clear()
|
||||||
|
|
||||||
|
def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
|
||||||
|
"""Run on new LLM token. Only available when streaming is enabled."""
|
||||||
|
self.q.put(token)
|
||||||
|
|
||||||
|
def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
|
||||||
|
"""Run when LLM ends running."""
|
||||||
|
self.q.put(STOP_ITEM)
|
||||||
|
|
||||||
|
def on_llm_error(self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any) -> None:
|
||||||
|
"""Run when LLM errors."""
|
||||||
|
self.q.put("%s: %s" % (type(error).__name__, str(error)))
|
||||||
|
self.q.put(STOP_ITEM)
|
||||||
|
|
||||||
|
|
||||||
|
def generate(rq: queue.Queue):
|
||||||
|
"""
|
||||||
|
This is a generator that yields the items in the queue until it reaches the stop item.
|
||||||
|
|
||||||
|
Usage example:
|
||||||
|
```
|
||||||
|
def askQuestion(callback_fn: StreamingStdOutCallbackHandlerYield):
|
||||||
|
llm = OpenAI(streaming=True, callbacks=[callback_fn])
|
||||||
|
return llm(prompt="Write a poem about a tree.")
|
||||||
|
|
||||||
|
@app.route("/", methods=["GET"])
|
||||||
|
def generate_output():
|
||||||
|
q = Queue()
|
||||||
|
callback_fn = StreamingStdOutCallbackHandlerYield(q)
|
||||||
|
threading.Thread(target=askQuestion, args=(callback_fn,)).start()
|
||||||
|
return Response(generate(q), mimetype="text/event-stream")
|
||||||
|
```
|
||||||
|
"""
|
||||||
|
while True:
|
||||||
|
result: str = rq.get()
|
||||||
|
if result == STOP_ITEM or result is None:
|
||||||
|
break
|
||||||
|
yield result
|
||||||
@@ -33,7 +33,7 @@ def register_deserializable(cls: Type[T]) -> Type[T]:
|
|||||||
Returns:
|
Returns:
|
||||||
Type: The same class, after registration.
|
Type: The same class, after registration.
|
||||||
"""
|
"""
|
||||||
JSONSerializable.register_class_as_deserializable(cls)
|
JSONSerializable._register_class_as_deserializable(cls)
|
||||||
return cls
|
return cls
|
||||||
|
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ class JSONSerializable:
|
|||||||
return cls.deserialize(json_str)
|
return cls.deserialize(json_str)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def register_class_as_deserializable(cls, target_class: Type[T]) -> None:
|
def _register_class_as_deserializable(cls, target_class: Type[T]) -> None:
|
||||||
"""
|
"""
|
||||||
Register a class as deserializable. This is a classmethod and globally shared.
|
Register a class as deserializable. This is a classmethod and globally shared.
|
||||||
|
|
||||||
@@ -3,7 +3,7 @@ import os
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import logging
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+16
-18
@@ -1,14 +1,15 @@
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Generator, List, Optional
|
from typing import Any, Dict, Generator, List, Optional
|
||||||
|
|
||||||
from langchain.memory import ConversationBufferMemory
|
from langchain.schema import BaseMessage as LCBaseMessage
|
||||||
from langchain.schema import BaseMessage
|
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.config.llm.base import (DEFAULT_PROMPT,
|
from embedchain.config.llm.base import (DEFAULT_PROMPT,
|
||||||
DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE,
|
DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE,
|
||||||
DOCS_SITE_PROMPT_TEMPLATE)
|
DOCS_SITE_PROMPT_TEMPLATE)
|
||||||
from embedchain.helper.json_serializable import JSONSerializable
|
from embedchain.helpers.json_serializable import JSONSerializable
|
||||||
|
from embedchain.memory.base import ECChatMemory
|
||||||
|
from embedchain.memory.message import ChatMessage
|
||||||
|
|
||||||
|
|
||||||
class BaseLlm(JSONSerializable):
|
class BaseLlm(JSONSerializable):
|
||||||
@@ -23,7 +24,7 @@ class BaseLlm(JSONSerializable):
|
|||||||
else:
|
else:
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
self.memory = ConversationBufferMemory()
|
self.memory = ECChatMemory()
|
||||||
self.is_docs_site_instance = False
|
self.is_docs_site_instance = False
|
||||||
self.online = False
|
self.online = False
|
||||||
self.history: Any = None
|
self.history: Any = None
|
||||||
@@ -44,11 +45,18 @@ class BaseLlm(JSONSerializable):
|
|||||||
"""
|
"""
|
||||||
self.history = history
|
self.history = history
|
||||||
|
|
||||||
def update_history(self):
|
def update_history(self, app_id: str):
|
||||||
"""Update class history attribute with history in memory (for chat method)"""
|
"""Update class history attribute with history in memory (for chat method)"""
|
||||||
chat_history = self.memory.load_memory_variables({})["history"]
|
chat_history = self.memory.get_recent_memories(app_id=app_id, num_rounds=10)
|
||||||
if chat_history:
|
if chat_history:
|
||||||
self.set_history(chat_history)
|
self.set_history([str(history) for history in chat_history])
|
||||||
|
|
||||||
|
def add_history(self, app_id: str, question: str, answer: str, metadata: Optional[Dict[str, Any]] = None):
|
||||||
|
chat_message = ChatMessage()
|
||||||
|
chat_message.add_user_message(question, metadata=metadata)
|
||||||
|
chat_message.add_ai_message(answer, metadata=metadata)
|
||||||
|
self.memory.add(app_id=app_id, chat_message=chat_message)
|
||||||
|
self.update_history(app_id=app_id)
|
||||||
|
|
||||||
def generate_prompt(self, input_query: str, contexts: List[str], **kwargs: Dict[str, Any]) -> str:
|
def generate_prompt(self, input_query: str, contexts: List[str], **kwargs: Dict[str, Any]) -> str:
|
||||||
"""
|
"""
|
||||||
@@ -165,7 +173,6 @@ class BaseLlm(JSONSerializable):
|
|||||||
for chunk in answer:
|
for chunk in answer:
|
||||||
streamed_answer = streamed_answer + chunk
|
streamed_answer = streamed_answer + chunk
|
||||||
yield chunk
|
yield chunk
|
||||||
self.memory.chat_memory.add_ai_message(streamed_answer)
|
|
||||||
logging.info(f"Answer: {streamed_answer}")
|
logging.info(f"Answer: {streamed_answer}")
|
||||||
|
|
||||||
def query(self, input_query: str, contexts: List[str], config: BaseLlmConfig = None, dry_run=False):
|
def query(self, input_query: str, contexts: List[str], config: BaseLlmConfig = None, dry_run=False):
|
||||||
@@ -257,8 +264,6 @@ class BaseLlm(JSONSerializable):
|
|||||||
if self.online:
|
if self.online:
|
||||||
k["web_search_result"] = self.access_search_and_get_results(input_query)
|
k["web_search_result"] = self.access_search_and_get_results(input_query)
|
||||||
|
|
||||||
self.update_history()
|
|
||||||
|
|
||||||
prompt = self.generate_prompt(input_query, contexts, **k)
|
prompt = self.generate_prompt(input_query, contexts, **k)
|
||||||
logging.info(f"Prompt: {prompt}")
|
logging.info(f"Prompt: {prompt}")
|
||||||
|
|
||||||
@@ -267,16 +272,9 @@ class BaseLlm(JSONSerializable):
|
|||||||
|
|
||||||
answer = self.get_answer_from_llm(prompt)
|
answer = self.get_answer_from_llm(prompt)
|
||||||
|
|
||||||
self.memory.chat_memory.add_user_message(input_query)
|
|
||||||
|
|
||||||
if isinstance(answer, str):
|
if isinstance(answer, str):
|
||||||
self.memory.chat_memory.add_ai_message(answer)
|
|
||||||
logging.info(f"Answer: {answer}")
|
logging.info(f"Answer: {answer}")
|
||||||
|
|
||||||
# NOTE: Adding to history before and after. This could be seen as redundant.
|
|
||||||
# If we change it, we have to change the tests (no big deal).
|
|
||||||
self.update_history()
|
|
||||||
|
|
||||||
return answer
|
return answer
|
||||||
else:
|
else:
|
||||||
# this is a streamed response and needs to be handled differently.
|
# this is a streamed response and needs to be handled differently.
|
||||||
@@ -287,7 +285,7 @@ class BaseLlm(JSONSerializable):
|
|||||||
self.config: BaseLlmConfig = BaseLlmConfig.deserialize(prev_config)
|
self.config: BaseLlmConfig = BaseLlmConfig.deserialize(prev_config)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_messages(prompt: str, system_prompt: Optional[str] = None) -> List[BaseMessage]:
|
def _get_messages(prompt: str, system_prompt: Optional[str] = None) -> List[LCBaseMessage]:
|
||||||
"""
|
"""
|
||||||
Construct a list of langchain messages
|
Construct a list of langchain messages
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from typing import Optional
|
|||||||
from langchain.llms import Cohere
|
from langchain.llms import Cohere
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.callbacks.stdout import StdOutCallbackHandler
|
|||||||
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import importlib
|
import importlib
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from langchain.llms import HuggingFaceHub
|
from langchain.llms import HuggingFaceHub
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
@@ -20,7 +21,7 @@ class HuggingFaceLlm(BaseLlm):
|
|||||||
except ModuleNotFoundError:
|
except ModuleNotFoundError:
|
||||||
raise ModuleNotFoundError(
|
raise ModuleNotFoundError(
|
||||||
"The required dependencies for HuggingFaceHub are not installed."
|
"The required dependencies for HuggingFaceHub are not installed."
|
||||||
'Please install with `pip install --upgrade "embedchain[huggingface_hub]"`'
|
'Please install with `pip install --upgrade "embedchain[huggingface-hub]"`'
|
||||||
) from None
|
) from None
|
||||||
|
|
||||||
super().__init__(config=config)
|
super().__init__(config=config)
|
||||||
@@ -42,9 +43,11 @@ class HuggingFaceLlm(BaseLlm):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("`top_p` must be > 0.0 and < 1.0")
|
raise ValueError("`top_p` must be > 0.0 and < 1.0")
|
||||||
|
|
||||||
|
model = config.model or "google/flan-t5-xxl"
|
||||||
|
logging.info(f"Using HuggingFaceHub with model {model}")
|
||||||
llm = HuggingFaceHub(
|
llm = HuggingFaceHub(
|
||||||
huggingfacehub_api_token=os.environ["HUGGINGFACE_ACCESS_TOKEN"],
|
huggingfacehub_api_token=os.environ["HUGGINGFACE_ACCESS_TOKEN"],
|
||||||
repo_id=config.model or "google/flan-t5-xxl",
|
repo_id=model,
|
||||||
model_kwargs=model_kwargs,
|
model_kwargs=model_kwargs,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from langchain.chat_models import JinaChat
|
|||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain.schema import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from typing import Optional
|
|||||||
from langchain.llms import Replicate
|
from langchain.llms import Replicate
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from langchain.chat_models import ChatOpenAI
|
|||||||
from langchain.schema import HumanMessage, SystemMessage
|
from langchain.schema import HumanMessage, SystemMessage
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +34,8 @@ class OpenAILlm(BaseLlm):
|
|||||||
from langchain.callbacks.streaming_stdout import \
|
from langchain.callbacks.streaming_stdout import \
|
||||||
StreamingStdOutCallbackHandler
|
StreamingStdOutCallbackHandler
|
||||||
|
|
||||||
chat = ChatOpenAI(**kwargs, streaming=config.stream, callbacks=[StreamingStdOutCallbackHandler()])
|
callbacks = config.callbacks if config.callbacks else [StreamingStdOutCallbackHandler()]
|
||||||
|
chat = ChatOpenAI(**kwargs, streaming=config.stream, callbacks=callbacks)
|
||||||
else:
|
else:
|
||||||
chat = ChatOpenAI(**kwargs)
|
chat = ChatOpenAI(**kwargs)
|
||||||
return chat(messages).content
|
return chat(messages).content
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import logging
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from embedchain.config import BaseLlmConfig
|
from embedchain.config import BaseLlmConfig
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.llm.base import BaseLlm
|
from embedchain.llm.base import BaseLlm
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from embedchain.helper.json_serializable import JSONSerializable
|
from embedchain.helpers.json_serializable import JSONSerializable
|
||||||
|
|
||||||
|
|
||||||
class BaseLoader(JSONSerializable):
|
class BaseLoader(JSONSerializable):
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
import hashlib
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
|
from embedchain.loaders.base_loader import BaseLoader
|
||||||
|
|
||||||
|
|
||||||
|
@register_deserializable
|
||||||
|
class DiscordLoader(BaseLoader):
|
||||||
|
"""
|
||||||
|
Load data from a Discord Channel ID.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
if not os.environ.get("DISCORD_TOKEN"):
|
||||||
|
raise ValueError("DISCORD_TOKEN is not set")
|
||||||
|
|
||||||
|
self.token = os.environ.get("DISCORD_TOKEN")
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _format_message(message):
|
||||||
|
return {
|
||||||
|
"message_id": message.id,
|
||||||
|
"content": message.content,
|
||||||
|
"author": {
|
||||||
|
"id": message.author.id,
|
||||||
|
"name": message.author.name,
|
||||||
|
"discriminator": message.author.discriminator,
|
||||||
|
},
|
||||||
|
"created_at": message.created_at.isoformat(),
|
||||||
|
"attachments": [
|
||||||
|
{
|
||||||
|
"id": attachment.id,
|
||||||
|
"filename": attachment.filename,
|
||||||
|
"size": attachment.size,
|
||||||
|
"url": attachment.url,
|
||||||
|
"proxy_url": attachment.proxy_url,
|
||||||
|
"height": attachment.height,
|
||||||
|
"width": attachment.width,
|
||||||
|
}
|
||||||
|
for attachment in message.attachments
|
||||||
|
],
|
||||||
|
"embeds": [
|
||||||
|
{
|
||||||
|
"title": embed.title,
|
||||||
|
"type": embed.type,
|
||||||
|
"description": embed.description,
|
||||||
|
"url": embed.url,
|
||||||
|
"timestamp": embed.timestamp.isoformat(),
|
||||||
|
"color": embed.color,
|
||||||
|
"footer": {
|
||||||
|
"text": embed.footer.text,
|
||||||
|
"icon_url": embed.footer.icon_url,
|
||||||
|
"proxy_icon_url": embed.footer.proxy_icon_url,
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"url": embed.image.url,
|
||||||
|
"proxy_url": embed.image.proxy_url,
|
||||||
|
"height": embed.image.height,
|
||||||
|
"width": embed.image.width,
|
||||||
|
},
|
||||||
|
"thumbnail": {
|
||||||
|
"url": embed.thumbnail.url,
|
||||||
|
"proxy_url": embed.thumbnail.proxy_url,
|
||||||
|
"height": embed.thumbnail.height,
|
||||||
|
"width": embed.thumbnail.width,
|
||||||
|
},
|
||||||
|
"video": {
|
||||||
|
"url": embed.video.url,
|
||||||
|
"height": embed.video.height,
|
||||||
|
"width": embed.video.width,
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"name": embed.provider.name,
|
||||||
|
"url": embed.provider.url,
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": embed.author.name,
|
||||||
|
"url": embed.author.url,
|
||||||
|
"icon_url": embed.author.icon_url,
|
||||||
|
"proxy_icon_url": embed.author.proxy_icon_url,
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": field.name,
|
||||||
|
"value": field.value,
|
||||||
|
"inline": field.inline,
|
||||||
|
}
|
||||||
|
for field in embed.fields
|
||||||
|
],
|
||||||
|
}
|
||||||
|
for embed in message.embeds
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
def load_data(self, channel_id: str):
|
||||||
|
"""Load data from a Discord Channel ID."""
|
||||||
|
import discord
|
||||||
|
|
||||||
|
messages = []
|
||||||
|
|
||||||
|
class DiscordClient(discord.Client):
|
||||||
|
async def on_ready(self) -> None:
|
||||||
|
logging.info("Logged on as {0}!".format(self.user))
|
||||||
|
try:
|
||||||
|
channel = self.get_channel(int(channel_id))
|
||||||
|
if not isinstance(channel, discord.TextChannel):
|
||||||
|
raise ValueError(
|
||||||
|
f"Channel {channel_id} is not a text channel. " "Only text channels are supported for now."
|
||||||
|
)
|
||||||
|
threads = {}
|
||||||
|
|
||||||
|
for thread in channel.threads:
|
||||||
|
threads[thread.id] = thread
|
||||||
|
|
||||||
|
async for message in channel.history(limit=None):
|
||||||
|
messages.append(DiscordLoader._format_message(message))
|
||||||
|
if message.id in threads:
|
||||||
|
async for thread_message in threads[message.id].history(limit=None):
|
||||||
|
messages.append(DiscordLoader._format_message(thread_message))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(e)
|
||||||
|
await self.close()
|
||||||
|
finally:
|
||||||
|
await self.close()
|
||||||
|
|
||||||
|
intents = discord.Intents.default()
|
||||||
|
intents.message_content = True
|
||||||
|
client = DiscordClient(intents=intents)
|
||||||
|
client.run(self.token)
|
||||||
|
|
||||||
|
meta_data = {
|
||||||
|
"url": channel_id,
|
||||||
|
}
|
||||||
|
|
||||||
|
messages = str(messages)
|
||||||
|
|
||||||
|
doc_id = hashlib.sha256((messages + channel_id).encode()).hexdigest()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"doc_id": doc_id,
|
||||||
|
"data": [
|
||||||
|
{
|
||||||
|
"content": messages,
|
||||||
|
"meta_data": meta_data,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import hashlib
|
||||||
|
import logging
|
||||||
|
import time
|
||||||
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from embedchain.loaders.base_loader import BaseLoader
|
||||||
|
from embedchain.utils import clean_string
|
||||||
|
|
||||||
|
|
||||||
|
class DiscourseLoader(BaseLoader):
|
||||||
|
def __init__(self, config: Optional[Dict[str, Any]] = None):
|
||||||
|
super().__init__()
|
||||||
|
if not config:
|
||||||
|
raise ValueError(
|
||||||
|
"DiscourseLoader requires a config. Check the documentation for the correct format - `https://docs.embedchain.ai/data-sources/discourse`" # noqa: E501
|
||||||
|
)
|
||||||
|
|
||||||
|
self.domain = config.get("domain")
|
||||||
|
if not self.domain:
|
||||||
|
raise ValueError(
|
||||||
|
"DiscourseLoader requires a domain. Check the documentation for the correct format - `https://docs.embedchain.ai/data-sources/discourse`" # noqa: E501
|
||||||
|
)
|
||||||
|
|
||||||
|
def _check_query(self, query):
|
||||||
|
if not query or not isinstance(query, str):
|
||||||
|
raise ValueError(
|
||||||
|
"DiscourseLoader requires a query. Check the documentation for the correct format - `https://docs.embedchain.ai/data-sources/discourse`" # noqa: E501
|
||||||
|
)
|
||||||
|
|
||||||
|
def _load_post(self, post_id):
|
||||||
|
post_url = f"{self.domain}posts/{post_id}.json"
|
||||||
|
response = requests.get(post_url)
|
||||||
|
try:
|
||||||
|
response.raise_for_status()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Failed to load post {post_id}: {e}")
|
||||||
|
return
|
||||||
|
response_data = response.json()
|
||||||
|
post_contents = clean_string(response_data.get("raw"))
|
||||||
|
meta_data = {
|
||||||
|
"url": post_url,
|
||||||
|
"created_at": response_data.get("created_at", ""),
|
||||||
|
"username": response_data.get("username", ""),
|
||||||
|
"topic_slug": response_data.get("topic_slug", ""),
|
||||||
|
"score": response_data.get("score", ""),
|
||||||
|
}
|
||||||
|
data = {
|
||||||
|
"content": post_contents,
|
||||||
|
"meta_data": meta_data,
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
|
||||||
|
def load_data(self, query):
|
||||||
|
self._check_query(query)
|
||||||
|
data = []
|
||||||
|
data_contents = []
|
||||||
|
logging.info(f"Searching data on discourse url: {self.domain}, for query: {query}")
|
||||||
|
search_url = f"{self.domain}search.json?q={query}"
|
||||||
|
response = requests.get(search_url)
|
||||||
|
try:
|
||||||
|
response.raise_for_status()
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError(f"Failed to search query {query}: {e}")
|
||||||
|
response_data = response.json()
|
||||||
|
post_ids = response_data.get("grouped_search_result").get("post_ids")
|
||||||
|
for id in post_ids:
|
||||||
|
post_data = self._load_post(id)
|
||||||
|
if post_data:
|
||||||
|
data.append(post_data)
|
||||||
|
data_contents.append(post_data.get("content"))
|
||||||
|
# Sleep for 0.4 sec, to avoid rate limiting. Check `https://meta.discourse.org/t/api-rate-limits/208405/6`
|
||||||
|
time.sleep(0.4)
|
||||||
|
doc_id = hashlib.sha256((query + ", ".join(data_contents)).encode()).hexdigest()
|
||||||
|
response_data = {"doc_id": doc_id, "data": data}
|
||||||
|
return response_data
|
||||||
@@ -12,7 +12,7 @@ except ImportError:
|
|||||||
) from None
|
) from None
|
||||||
|
|
||||||
|
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.loaders.base_loader import BaseLoader
|
from embedchain.loaders.base_loader import BaseLoader
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ except ImportError:
|
|||||||
raise ImportError(
|
raise ImportError(
|
||||||
'Docx file requires extra dependencies. Install with `pip install --upgrade "embedchain[dataloaders]"`'
|
'Docx file requires extra dependencies. Install with `pip install --upgrade "embedchain[dataloaders]"`'
|
||||||
) from None
|
) from None
|
||||||
from embedchain.helper.json_serializable import register_deserializable
|
from embedchain.helpers.json_serializable import register_deserializable
|
||||||
from embedchain.loaders.base_loader import BaseLoader
|
from embedchain.loaders.base_loader import BaseLoader
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
import concurrent.futures
|
||||||
|
import hashlib
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
|
||||||
|
from tqdm import tqdm
|
||||||
|
|
||||||
|
from embedchain.loaders.base_loader import BaseLoader
|
||||||
|
from embedchain.loaders.json import JSONLoader
|
||||||
|
from embedchain.loaders.mdx import MdxLoader
|
||||||
|
from embedchain.utils import detect_datatype
|
||||||
|
|
||||||
|
|
||||||
|
def _load_file_data(path):
|
||||||
|
data = []
|
||||||
|
data_content = []
|
||||||
|
try:
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
content = f.read().decode("utf-8")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error reading file {path}: {e}")
|
||||||
|
raise ValueError(f"Failed to read file {path}")
|
||||||
|
|
||||||
|
meta_data = {}
|
||||||
|
meta_data["url"] = path
|
||||||
|
data.append(
|
||||||
|
{
|
||||||
|
"content": content,
|
||||||
|
"meta_data": meta_data,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
data_content.append(content)
|
||||||
|
doc_id = hashlib.sha256((" ".join(data_content) + path).encode()).hexdigest()
|
||||||
|
return {
|
||||||
|
"doc_id": doc_id,
|
||||||
|
"data": data,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class GithubLoader(BaseLoader):
|
||||||
|
def load_data(self, repo_url):
|
||||||
|
"""Load data from a git repo."""
|
||||||
|
try:
|
||||||
|
from git import Repo
|
||||||
|
except ImportError as e:
|
||||||
|
raise ValueError(
|
||||||
|
"GithubLoader requires extra dependencies. Install with `pip install --upgrade 'embedchain[git]'`"
|
||||||
|
) from e
|
||||||
|
|
||||||
|
mdx_loader = MdxLoader()
|
||||||
|
json_loader = JSONLoader()
|
||||||
|
data = []
|
||||||
|
data_urls = []
|
||||||
|
|
||||||
|
def _fetch_or_clone_repo(repo_url: str, local_path: str):
|
||||||
|
if os.path.exists(local_path):
|
||||||
|
logging.info("Repository already exists. Fetching updates...")
|
||||||
|
repo = Repo(local_path)
|
||||||
|
origin = repo.remotes.origin
|
||||||
|
origin.fetch()
|
||||||
|
logging.info("Fetch completed.")
|
||||||
|
else:
|
||||||
|
logging.info("Cloning repository...")
|
||||||
|
Repo.clone_from(repo_url, local_path)
|
||||||
|
logging.info("Clone completed.")
|
||||||
|
|
||||||
|
def _load_file(file_path: str):
|
||||||
|
try:
|
||||||
|
data_type = detect_datatype(file_path).value
|
||||||
|
except Exception:
|
||||||
|
data_type = "unstructured"
|
||||||
|
|
||||||
|
if data_type == "mdx":
|
||||||
|
data = mdx_loader.load_data(file_path)
|
||||||
|
elif data_type == "json":
|
||||||
|
data = json_loader.load_data(file_path)
|
||||||
|
else:
|
||||||
|
data = _load_file_data(file_path)
|
||||||
|
|
||||||
|
return data.get("data", [])
|
||||||
|
|
||||||
|
def _is_file_empty(file_path):
|
||||||
|
return os.path.getsize(file_path) == 0
|
||||||
|
|
||||||
|
def _is_whitelisted(file_path):
|
||||||
|
whitelisted_extensions = ["md", "txt", "html", "json", "py", "js", "jsx", "ts", "tsx", "mdx", "rst"]
|
||||||
|
_, file_extension = os.path.splitext(file_path)
|
||||||
|
return file_extension[1:] in whitelisted_extensions
|
||||||
|
|
||||||
|
def _add_repo_files(repo_path: str):
|
||||||
|
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
|
||||||
|
future_to_file = {
|
||||||
|
executor.submit(_load_file, os.path.join(root, filename)): os.path.join(root, filename)
|
||||||
|
for root, _, files in os.walk(repo_path)
|
||||||
|
for filename in files
|
||||||
|
if _is_whitelisted(os.path.join(root, filename))
|
||||||
|
and not _is_file_empty(os.path.join(root, filename)) # noqa:E501
|
||||||
|
}
|
||||||
|
for future in tqdm(concurrent.futures.as_completed(future_to_file), total=len(future_to_file)):
|
||||||
|
file = future_to_file[future]
|
||||||
|
try:
|
||||||
|
results = future.result()
|
||||||
|
if results:
|
||||||
|
data.extend(results)
|
||||||
|
data_urls.extend([result.get("meta_data").get("url") for result in results])
|
||||||
|
except Exception as e:
|
||||||
|
logging.warn(f"Failed to process {file}: {e}")
|
||||||
|
|
||||||
|
source_hash = hashlib.sha256(repo_url.encode()).hexdigest()
|
||||||
|
repo_path = f"/tmp/{source_hash}"
|
||||||
|
_fetch_or_clone_repo(repo_url=repo_url, local_path=repo_path)
|
||||||
|
_add_repo_files(repo_path)
|
||||||
|
doc_id = hashlib.sha256((repo_url + ", ".join(data_urls)).encode()).hexdigest()
|
||||||
|
return {
|
||||||
|
"doc_id": doc_id,
|
||||||
|
"data": data,
|
||||||
|
}
|
||||||
@@ -25,10 +25,21 @@ class JSONLoader(BaseLoader):
|
|||||||
|
|
||||||
return LLHUBJSONLoader()
|
return LLHUBJSONLoader()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_content(content):
|
||||||
|
if not isinstance(content, str):
|
||||||
|
raise ValueError(
|
||||||
|
"Invaid content input. \
|
||||||
|
If you want to upload (list, dict, etc.), do \
|
||||||
|
`json.dump(data, indent=0)` and add the stringified JSON. \
|
||||||
|
Check - `https://docs.embedchain.ai/data-sources/json`"
|
||||||
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_data(content):
|
def load_data(content):
|
||||||
"""Load a json file. Each data point is a key value pair."""
|
"""Load a json file. Each data point is a key value pair."""
|
||||||
|
|
||||||
|
JSONLoader._check_content(content)
|
||||||
loader = JSONLoader._get_llama_hub_loader()
|
loader = JSONLoader._get_llama_hub_loader()
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user