Add rest-api example (#889)
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -76,7 +76,6 @@ docs/_build/
|
|||||||
target/
|
target/
|
||||||
|
|
||||||
# Jupyter Notebook
|
# Jupyter Notebook
|
||||||
*.yaml
|
|
||||||
|
|
||||||
# IPython
|
# IPython
|
||||||
profile_default/
|
profile_default/
|
||||||
|
|||||||
@@ -26,6 +26,14 @@ Book a [1-on-1 Session](https://cal.com/taranjeetio/ec) with Taranjeet, the foun
|
|||||||
pip install --upgrade embedchain
|
pip install --upgrade embedchain
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To run Embedchain as a REST API server use,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name embedchain -p 8000:8000 embedchain/app:rest-api-latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Navigate to http://0.0.0.0:8000/docs to interact with the API.
|
||||||
|
|
||||||
## 🔍 Demo
|
## 🔍 Demo
|
||||||
|
|
||||||
Try out embedchain in your browser:
|
Try out embedchain in your browser:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
llm:
|
llm:
|
||||||
provider: anthropic
|
provider: anthropic
|
||||||
model: 'claude-instant-1'
|
|
||||||
config:
|
config:
|
||||||
|
model: 'claude-instant-1'
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
top_p: 1
|
top_p: 1
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ app:
|
|||||||
|
|
||||||
llm:
|
llm:
|
||||||
provider: azure_openai
|
provider: azure_openai
|
||||||
model: gpt-35-turbo
|
|
||||||
config:
|
config:
|
||||||
|
model: gpt-35-turbo
|
||||||
deployment_name: your_llm_deployment_name
|
deployment_name: your_llm_deployment_name
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ app:
|
|||||||
|
|
||||||
llm:
|
llm:
|
||||||
provider: openai
|
provider: openai
|
||||||
model: 'gpt-3.5-turbo'
|
|
||||||
config:
|
config:
|
||||||
|
model: 'gpt-3.5-turbo'
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
top_p: 1
|
top_p: 1
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
llm:
|
llm:
|
||||||
provider: cohere
|
provider: cohere
|
||||||
model: large
|
|
||||||
config:
|
config:
|
||||||
|
model: large
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
top_p: 1
|
top_p: 1
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ app:
|
|||||||
|
|
||||||
llm:
|
llm:
|
||||||
provider: openai
|
provider: openai
|
||||||
model: 'gpt-3.5-turbo'
|
|
||||||
config:
|
config:
|
||||||
|
model: 'gpt-3.5-turbo'
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
top_p: 1
|
top_p: 1
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
llm:
|
llm:
|
||||||
provider: huggingface
|
provider: huggingface
|
||||||
model: 'google/flan-t5-xxl'
|
|
||||||
config:
|
config:
|
||||||
|
model: 'google/flan-t5-xxl'
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
top_p: 0.5
|
top_p: 0.5
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
llm:
|
llm:
|
||||||
provider: llama2
|
provider: llama2
|
||||||
model: 'a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5'
|
|
||||||
config:
|
config:
|
||||||
|
model: 'a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5'
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
top_p: 0.5
|
top_p: 0.5
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ app:
|
|||||||
|
|
||||||
llm:
|
llm:
|
||||||
provider: openai
|
provider: openai
|
||||||
model: 'gpt-3.5-turbo'
|
|
||||||
config:
|
config:
|
||||||
|
model: 'gpt-3.5-turbo'
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
max_tokens: 1000
|
max_tokens: 1000
|
||||||
top_p: 1
|
top_p: 1
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
llm:
|
llm:
|
||||||
provider: vertexai
|
provider: vertexai
|
||||||
model: 'chat-bison'
|
|
||||||
config:
|
config:
|
||||||
|
model: 'chat-bison'
|
||||||
temperature: 0.5
|
temperature: 0.5
|
||||||
top_p: 0.5
|
top_p: 0.5
|
||||||
|
|||||||
3
docs/api-reference/add-datasource-to-an-app.mdx
Normal file
3
docs/api-reference/add-datasource-to-an-app.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: post /{app_id}/add
|
||||||
|
---
|
||||||
3
docs/api-reference/chat-with-an-app.mdx
Normal file
3
docs/api-reference/chat-with-an-app.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: post /{app_id}/chat
|
||||||
|
---
|
||||||
3
docs/api-reference/check-status.mdx
Normal file
3
docs/api-reference/check-status.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: get /ping
|
||||||
|
---
|
||||||
3
docs/api-reference/create-app.mdx
Normal file
3
docs/api-reference/create-app.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: post /create
|
||||||
|
---
|
||||||
3
docs/api-reference/delete-app.mdx
Normal file
3
docs/api-reference/delete-app.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: delete /{app_id}/delete
|
||||||
|
---
|
||||||
3
docs/api-reference/deploy-app.mdx
Normal file
3
docs/api-reference/deploy-app.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: post /{app_id}/deploy
|
||||||
|
---
|
||||||
3
docs/api-reference/get-all-apps.mdx
Normal file
3
docs/api-reference/get-all-apps.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: get /apps
|
||||||
|
---
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: get /{app_id}/data
|
||||||
|
---
|
||||||
102
docs/api-reference/getting-started.mdx
Normal file
102
docs/api-reference/getting-started.mdx
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
---
|
||||||
|
title: "🌍 Getting Started"
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
To run Embedchain as a REST API server use,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name embedchain -p 8000:8000 embedchain/app:rest-api-latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Open up your browser and navigate to http://0.0.0.0:8000/docs to interact with the API. There is a full-fledged Swagger docs playground with all the information
|
||||||
|
about the API endpoints.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Creating your first App
|
||||||
|
|
||||||
|
App requires an `app_id` to be created. The `app_id` is a unique identifier for your app.
|
||||||
|
|
||||||
|
By default we will use the opensource **gpt4all** model to perform operations. You can also specify your own config by uploading a config YAML file.
|
||||||
|
|
||||||
|
For example, create a `config.yaml` file (adjust according to your requirements):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
app:
|
||||||
|
config:
|
||||||
|
id: "default-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.
|
||||||
|
If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||||
|
|
||||||
|
$context
|
||||||
|
|
||||||
|
Query: $query
|
||||||
|
|
||||||
|
Helpful Answer:
|
||||||
|
|
||||||
|
vectordb:
|
||||||
|
provider: chroma
|
||||||
|
config:
|
||||||
|
collection_name: "rest-api-app"
|
||||||
|
dir: db
|
||||||
|
allow_reset: true
|
||||||
|
|
||||||
|
embedder:
|
||||||
|
provider: openai
|
||||||
|
config:
|
||||||
|
model: "text-embedding-ada-002"
|
||||||
|
```
|
||||||
|
|
||||||
|
To learn more about custom configurations, check out the [Custom configurations](https://docs.embedchain.ai/advanced/configuration).
|
||||||
|
To explore more examples of config YAMLs for Embedchain, visit [embedchain/configs](https://github.com/embedchain/embedchain/tree/main/configs).
|
||||||
|
|
||||||
|
Now, you can upload this config file in the request body.
|
||||||
|
|
||||||
|
**Note:** To use custom models, an **API key** might be required. Refer to the table below to determine the necessary API key for your provider.
|
||||||
|
|
||||||
|
| Keys | Providers |
|
||||||
|
| -------------------------- | ------------------------------ |
|
||||||
|
| `OPENAI_API_KEY ` | OpenAI, Azure OpenAI, Jina etc |
|
||||||
|
| `OPENAI_API_TYPE` | Azure OpenAI |
|
||||||
|
| `OPENAI_API_BASE` | Azure OpenAI |
|
||||||
|
| `OPENAI_API_VERSION` | Azure OpenAI |
|
||||||
|
| `COHERE_API_KEY` | Cohere |
|
||||||
|
| `ANTHROPIC_API_KEY` | Anthropic |
|
||||||
|
| `JINACHAT_API_KEY` | Jina |
|
||||||
|
| `HUGGINGFACE_ACCESS_TOKEN` | Huggingface |
|
||||||
|
| `REPLICATE_API_TOKEN` | LLAMA2 |
|
||||||
|
|
||||||
|
To provide them, you can simply run the docker command with the `-e` flag.
|
||||||
|
|
||||||
|
For example,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name embedchain -p 8000:8000 -e OPENAI_API_KEY=YOUR_API_KEY embedchain/app:rest-api-latest
|
||||||
|
```
|
||||||
|
|
||||||
|
Cool! This will create a new Embedchain App with the given `app_id`.
|
||||||
|
|
||||||
|
## Deploying your App to Embedchain Platform
|
||||||
|
|
||||||
|
This feature is very powerful as it allows the creation of a public API endpoint for your app, enabling queries from anywhere. This creates a _pipeline_
|
||||||
|
for your app that can sync the data time to time and provide you with the best results.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
To utilize this functionality, visit app.embedchain.ai and create an account. Subsequently, generate a new [API KEY](https://app.embedchain.ai/settings/keys/).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Using this API key, you can deploy your app to the platform.
|
||||||
3
docs/api-reference/query-an-app.mdx
Normal file
3
docs/api-reference/query-an-app.mdx
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
---
|
||||||
|
openapi: post /{app_id}/query
|
||||||
|
---
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
---
|
|
||||||
title: '🌍 API Server'
|
|
||||||
---
|
|
||||||
|
|
||||||
The API server example can be found [here](https://github.com/embedchain/embedchain/tree/main/examples/api_server).
|
|
||||||
|
|
||||||
It is a Flask based server that integrates the `embedchain` package, offering endpoints to add, query, and chat to engage in conversations with a chatbot using JSON requests.
|
|
||||||
|
|
||||||
### 🐳 Docker Setup
|
|
||||||
|
|
||||||
- Open variables.env, and edit it to add your 🔑 `OPENAI_API_KEY`.
|
|
||||||
- To setup your api server using docker, run the following command inside this folder using your terminal.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker-compose up --build
|
|
||||||
```
|
|
||||||
|
|
||||||
📝 Note: The build command might take a while to install all the packages depending on your system resources.
|
|
||||||
|
|
||||||
### 🚀 Usage Instructions
|
|
||||||
|
|
||||||
- Your api server is running on [http://localhost:5000/](http://localhost:5000/)
|
|
||||||
- To use the api server, make an api call to the endpoints `/add`, `/query` and `/chat` using the json formats discussed below.
|
|
||||||
- To add data sources to the bot (/add):
|
|
||||||
```json
|
|
||||||
// Request
|
|
||||||
{
|
|
||||||
"data_type": "your_data_type_here",
|
|
||||||
"url_or_text": "your_url_or_text_here"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response
|
|
||||||
{
|
|
||||||
"data": "Added data_type: url_or_text"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- To ask queries from the bot (/query):
|
|
||||||
```json
|
|
||||||
// Request
|
|
||||||
{
|
|
||||||
"question": "your_question_here"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response
|
|
||||||
{
|
|
||||||
"data": "your_answer_here"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
- To chat with the bot (/chat):
|
|
||||||
```json
|
|
||||||
// Request
|
|
||||||
{
|
|
||||||
"question": "your_question_here"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response
|
|
||||||
{
|
|
||||||
"data": "your_answer_here"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 📡 Curl Call Formats
|
|
||||||
|
|
||||||
- To add data sources to the bot (/add):
|
|
||||||
```bash
|
|
||||||
curl -X POST \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"data_type": "your_data_type_here",
|
|
||||||
"url_or_text": "your_url_or_text_here"
|
|
||||||
}' \
|
|
||||||
http://localhost:5000/add
|
|
||||||
```
|
|
||||||
- To ask queries from the bot (/query):
|
|
||||||
```bash
|
|
||||||
curl -X POST \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"question": "your_question_here"
|
|
||||||
}' \
|
|
||||||
http://localhost:5000/query
|
|
||||||
```
|
|
||||||
- To chat with the bot (/chat):
|
|
||||||
```bash
|
|
||||||
curl -X POST \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"question": "your_question_here"
|
|
||||||
}' \
|
|
||||||
http://localhost:5000/chat
|
|
||||||
```
|
|
||||||
|
|
||||||
🎉 Happy Chatting! 🎉
|
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
"dark": "#020415"
|
"dark": "#020415"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"openapi": ["/rest-api.json"],
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"og:image": "/images/og.png",
|
"og:image": "/images/og.png",
|
||||||
"twitter:site": "@embedchain"
|
"twitter:site": "@embedchain"
|
||||||
@@ -28,8 +29,8 @@
|
|||||||
"url": "https://twitter.com/embedchain"
|
"url": "https://twitter.com/embedchain"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name":"Slack",
|
"name": "Slack",
|
||||||
"url":"https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw"
|
"url": "https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Discord",
|
"name": "Discord",
|
||||||
@@ -46,11 +47,20 @@
|
|||||||
"navigation": [
|
"navigation": [
|
||||||
{
|
{
|
||||||
"group": "Get started",
|
"group": "Get started",
|
||||||
"pages": ["get-started/quickstart", "get-started/introduction", "get-started/faq", "get-started/examples"]
|
"pages": [
|
||||||
|
"get-started/quickstart",
|
||||||
|
"get-started/introduction",
|
||||||
|
"get-started/faq",
|
||||||
|
"get-started/examples"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "Components",
|
"group": "Components",
|
||||||
"pages": ["components/llms", "components/embedding-models", "components/vector-databases"]
|
"pages": [
|
||||||
|
"components/llms",
|
||||||
|
"components/embedding-models",
|
||||||
|
"components/vector-databases"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "Data sources",
|
"group": "Data sources",
|
||||||
@@ -81,16 +91,34 @@
|
|||||||
"group": "Advanced",
|
"group": "Advanced",
|
||||||
"pages": ["advanced/configuration"]
|
"pages": ["advanced/configuration"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"group": "Rest API",
|
||||||
|
"pages": [
|
||||||
|
"api-reference/getting-started",
|
||||||
|
"api-reference/check-status",
|
||||||
|
"api-reference/get-all-apps",
|
||||||
|
"api-reference/create-app",
|
||||||
|
"api-reference/query-an-app",
|
||||||
|
"api-reference/add-datasource-to-an-app",
|
||||||
|
"api-reference/get-datasources-associated-with-app-id",
|
||||||
|
"api-reference/deploy-app",
|
||||||
|
"api-reference/delete-app"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"group": "Examples",
|
"group": "Examples",
|
||||||
"pages": ["examples/full_stack", "examples/api_server", "examples/discord_bot", "examples/slack_bot", "examples/telegram_bot", "examples/whatsapp_bot", "examples/poe_bot"]
|
"pages": [
|
||||||
|
"examples/full_stack",
|
||||||
|
"examples/discord_bot",
|
||||||
|
"examples/slack_bot",
|
||||||
|
"examples/telegram_bot",
|
||||||
|
"examples/whatsapp_bot",
|
||||||
|
"examples/poe_bot"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "Community",
|
"group": "Community",
|
||||||
"pages": [
|
"pages": ["community/connect-with-us", "community/showcase"]
|
||||||
"community/connect-with-us",
|
|
||||||
"community/showcase"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "Integrations",
|
"group": "Integrations",
|
||||||
@@ -108,16 +136,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"group": "Product",
|
"group": "Product",
|
||||||
"pages": [
|
"pages": ["product/release-notes"]
|
||||||
"product/release-notes"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
"footerSocials": {
|
"footerSocials": {
|
||||||
"website": "https://embedchain.ai",
|
"website": "https://embedchain.ai",
|
||||||
"github": "https://github.com/embedchain/embedchain",
|
"github": "https://github.com/embedchain/embedchain",
|
||||||
"slack":"https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw",
|
"slack": "https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw",
|
||||||
"discord": "https://discord.gg/6PzXDgEjG5",
|
"discord": "https://discord.gg/6PzXDgEjG5",
|
||||||
"twitter": "https://twitter.com/embedchain",
|
"twitter": "https://twitter.com/embedchain",
|
||||||
"linkedin": "https://www.linkedin.com/company/embedchain"
|
"linkedin": "https://www.linkedin.com/company/embedchain"
|
||||||
|
|||||||
428
docs/rest-api.json
Normal file
428
docs/rest-api.json
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
{
|
||||||
|
"openapi": "3.1.0",
|
||||||
|
"info": {
|
||||||
|
"title": "Embedchain REST API",
|
||||||
|
"description": "This is the REST API for Embedchain.",
|
||||||
|
"license": {
|
||||||
|
"name": "Apache 2.0",
|
||||||
|
"url": "https://github.com/embedchain/embedchain/blob/main/LICENSE"
|
||||||
|
},
|
||||||
|
"version": "0.0.1"
|
||||||
|
},
|
||||||
|
"paths": {
|
||||||
|
"/ping": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Utility"],
|
||||||
|
"summary": "Check Status",
|
||||||
|
"description": "Endpoint to check the status of the API.",
|
||||||
|
"operationId": "check_status_ping_get",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": { "application/json": { "schema": {} } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/apps": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Get All Apps",
|
||||||
|
"description": "Get all apps.",
|
||||||
|
"operationId": "get_all_apps_apps_get",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": { "application/json": { "schema": {} } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/create": {
|
||||||
|
"post": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Create App",
|
||||||
|
"description": "Create a new app using App ID.",
|
||||||
|
"operationId": "create_app_using_default_config_create_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "query",
|
||||||
|
"required": true,
|
||||||
|
"schema": { "type": "string", "title": "App Id" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"content": {
|
||||||
|
"multipart/form-data": {
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/schemas/Body_create_app_using_default_config_create_post"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"title": "Body"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/DefaultResponse" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/{app_id}/data": {
|
||||||
|
"get": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Get Datasources Associated With App Id",
|
||||||
|
"description": "Get all datasources for an app.",
|
||||||
|
"operationId": "get_datasources_associated_with_app_id__app_id__data_get",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": { "type": "string", "title": "App Id" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": { "application/json": { "schema": {} } }
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/{app_id}/add": {
|
||||||
|
"post": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Add Datasource To An App",
|
||||||
|
"description": "Add a source to an existing app.",
|
||||||
|
"operationId": "add_datasource_to_an_app__app_id__add_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": { "type": "string", "title": "App Id" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/SourceApp" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/DefaultResponse" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/{app_id}/query": {
|
||||||
|
"post": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Query An App",
|
||||||
|
"description": "Query an existing app.",
|
||||||
|
"operationId": "query_an_app__app_id__query_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": { "type": "string", "title": "App Id" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/QueryApp" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/DefaultResponse" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/{app_id}/chat": {
|
||||||
|
"post": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Chat With An App",
|
||||||
|
"description": "Query an existing app.\n\napp_id: The ID of the app. Use \"default\" for the default app.\n\nmessage: The message that you want to send to the App.",
|
||||||
|
"operationId": "chat_with_an_app__app_id__chat_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": { "type": "string", "title": "App Id" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/MessageApp" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/DefaultResponse" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/{app_id}/deploy": {
|
||||||
|
"post": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Deploy App",
|
||||||
|
"description": "Deploy an existing app.",
|
||||||
|
"operationId": "deploy_app__app_id__deploy_post",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": { "type": "string", "title": "App Id" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/DeployAppRequest" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/DefaultResponse" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/{app_id}/delete": {
|
||||||
|
"delete": {
|
||||||
|
"tags": ["Apps"],
|
||||||
|
"summary": "Delete App",
|
||||||
|
"description": "Delete an existing app.",
|
||||||
|
"operationId": "delete_app__app_id__delete_delete",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "app_id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true,
|
||||||
|
"schema": { "type": "string", "title": "App Id" }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Successful Response",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/DefaultResponse" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"description": "Validation Error",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": { "$ref": "#/components/schemas/HTTPValidationError" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"components": {
|
||||||
|
"schemas": {
|
||||||
|
"Body_create_app_using_default_config_create_post": {
|
||||||
|
"properties": {
|
||||||
|
"config": { "type": "string", "format": "binary", "title": "Config" }
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"title": "Body_create_app_using_default_config_create_post"
|
||||||
|
},
|
||||||
|
"DefaultResponse": {
|
||||||
|
"properties": { "response": { "type": "string", "title": "Response" } },
|
||||||
|
"type": "object",
|
||||||
|
"required": ["response"],
|
||||||
|
"title": "DefaultResponse"
|
||||||
|
},
|
||||||
|
"DeployAppRequest": {
|
||||||
|
"properties": {
|
||||||
|
"api_key": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Api Key",
|
||||||
|
"description": "The Embedchain API key for App deployments.",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"title": "DeployAppRequest",
|
||||||
|
"example":{
|
||||||
|
"api_key":"ec-xxx"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"HTTPValidationError": {
|
||||||
|
"properties": {
|
||||||
|
"detail": {
|
||||||
|
"items": { "$ref": "#/components/schemas/ValidationError" },
|
||||||
|
"type": "array",
|
||||||
|
"title": "Detail"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"title": "HTTPValidationError"
|
||||||
|
},
|
||||||
|
"MessageApp": {
|
||||||
|
"properties": {
|
||||||
|
"message": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Message",
|
||||||
|
"description": "The message that you want to send to the App.",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"title": "MessageApp"
|
||||||
|
},
|
||||||
|
"QueryApp": {
|
||||||
|
"properties": {
|
||||||
|
"query": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Query",
|
||||||
|
"description": "The query that you want to ask the App.",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"title": "QueryApp",
|
||||||
|
"example":{
|
||||||
|
"query":"Who is Elon Musk?"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SourceApp": {
|
||||||
|
"properties": {
|
||||||
|
"source": {
|
||||||
|
"type": "string",
|
||||||
|
"title": "Source",
|
||||||
|
"description": "The source that you want to add to the App.",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"data_type": {
|
||||||
|
"anyOf": [{ "type": "string" }, { "type": "null" }],
|
||||||
|
"title": "Data Type",
|
||||||
|
"description": "The type of data to add, remove it if you want Embedchain to detect it automatically.",
|
||||||
|
"default": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"title": "SourceApp",
|
||||||
|
"example":{
|
||||||
|
"source":"https://en.wikipedia.org/wiki/Elon_Musk"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ValidationError": {
|
||||||
|
"properties": {
|
||||||
|
"loc": {
|
||||||
|
"items": { "anyOf": [{ "type": "string" }, { "type": "integer" }] },
|
||||||
|
"type": "array",
|
||||||
|
"title": "Location"
|
||||||
|
},
|
||||||
|
"msg": { "type": "string", "title": "Message" },
|
||||||
|
"type": { "type": "string", "title": "Error Type" }
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"required": ["loc", "msg", "type"],
|
||||||
|
"title": "ValidationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -313,6 +313,15 @@ class Pipeline(EmbedChain):
|
|||||||
)
|
)
|
||||||
self.connection.commit()
|
self.connection.commit()
|
||||||
|
|
||||||
|
def get_data_sources(self):
|
||||||
|
db_data = self.cursor.execute("SELECT * FROM data_sources WHERE pipeline_id = ?", (self.local_id,)).fetchall()
|
||||||
|
|
||||||
|
data_sources = []
|
||||||
|
for data in db_data:
|
||||||
|
data_sources.append({"data_type": data[2], "data_value": data[3], "metadata": data[4]})
|
||||||
|
|
||||||
|
return data_sources
|
||||||
|
|
||||||
def deploy(self):
|
def deploy(self):
|
||||||
if self.client is None:
|
if self.client is None:
|
||||||
self._init_client()
|
self._init_client()
|
||||||
@@ -348,7 +357,7 @@ class Pipeline(EmbedChain):
|
|||||||
with open(yaml_path, "r") as file:
|
with open(yaml_path, "r") as file:
|
||||||
config_data = yaml.safe_load(file)
|
config_data = yaml.safe_load(file)
|
||||||
|
|
||||||
pipeline_config_data = config_data.get("pipeline", {}).get("config", {})
|
pipeline_config_data = config_data.get("app", {}).get("config", {})
|
||||||
db_config_data = config_data.get("vectordb", {})
|
db_config_data = config_data.get("vectordb", {})
|
||||||
embedding_model_config_data = config_data.get("embedding_model", {})
|
embedding_model_config_data = config_data.get("embedding_model", {})
|
||||||
llm_config_data = config_data.get("llm", {})
|
llm_config_data = config_data.get("llm", {})
|
||||||
|
|||||||
4
examples/rest-api/.dockerignore
Normal file
4
examples/rest-api/.dockerignore
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.env
|
||||||
|
app.db
|
||||||
|
configs/**.yaml
|
||||||
|
db
|
||||||
4
examples/rest-api/.gitignore
vendored
Normal file
4
examples/rest-api/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
.env
|
||||||
|
app.db
|
||||||
|
configs/**.yaml
|
||||||
|
db
|
||||||
15
examples/rest-api/Dockerfile
Normal file
15
examples/rest-api/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt /app/
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
|
COPY . /app
|
||||||
|
|
||||||
|
EXPOSE 8000
|
||||||
|
|
||||||
|
ENV NAME embedchain
|
||||||
|
|
||||||
|
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
||||||
21
examples/rest-api/README.md
Normal file
21
examples/rest-api/README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
## Single command to rule them all,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d --name embedchain -p 8000:8000 embedchain/app:rest-api-latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### To run the app locally,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# will help reload on changes
|
||||||
|
DEVELOPMENT=True && python -m main
|
||||||
|
```
|
||||||
|
|
||||||
|
Using docker (locally),
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker build -t embedchain/app:rest-api-latest .
|
||||||
|
docker run -d --name embedchain -p 8000:8000 embedchain/app:rest-api-latest
|
||||||
|
docker image push embedchain/app:rest-api-latest
|
||||||
|
```
|
||||||
|
|
||||||
0
examples/rest-api/__init__.py
Normal file
0
examples/rest-api/__init__.py
Normal file
5
examples/rest-api/bruno/ec-rest-api/bruno.json
Normal file
5
examples/rest-api/bruno/ec-rest-api/bruno.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"version": "1",
|
||||||
|
"name": "ec-rest-api",
|
||||||
|
"type": "collection"
|
||||||
|
}
|
||||||
18
examples/rest-api/bruno/ec-rest-api/default_add.bru
Normal file
18
examples/rest-api/bruno/ec-rest-api/default_add.bru
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
meta {
|
||||||
|
name: default_add
|
||||||
|
type: http
|
||||||
|
seq: 3
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: http://localhost:8000/add
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"source": "source_url",
|
||||||
|
"data_type": "data_type"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
examples/rest-api/bruno/ec-rest-api/default_chat.bru
Normal file
17
examples/rest-api/bruno/ec-rest-api/default_chat.bru
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
meta {
|
||||||
|
name: default_chat
|
||||||
|
type: http
|
||||||
|
seq: 4
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: http://localhost:8000/chat
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"message": "message"
|
||||||
|
}
|
||||||
|
}
|
||||||
17
examples/rest-api/bruno/ec-rest-api/default_query.bru
Normal file
17
examples/rest-api/bruno/ec-rest-api/default_query.bru
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
meta {
|
||||||
|
name: default_query
|
||||||
|
type: http
|
||||||
|
seq: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
post {
|
||||||
|
url: http://localhost:8000/query
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
|
|
||||||
|
body:json {
|
||||||
|
{
|
||||||
|
"query": "Who is Elon Musk?"
|
||||||
|
}
|
||||||
|
}
|
||||||
11
examples/rest-api/bruno/ec-rest-api/ping.bru
Normal file
11
examples/rest-api/bruno/ec-rest-api/ping.bru
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
meta {
|
||||||
|
name: ping
|
||||||
|
type: http
|
||||||
|
seq: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get {
|
||||||
|
url: http://localhost:8000/ping
|
||||||
|
body: json
|
||||||
|
auth: none
|
||||||
|
}
|
||||||
3
examples/rest-api/configs/README.md
Normal file
3
examples/rest-api/configs/README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
### Config directory
|
||||||
|
|
||||||
|
Here, all the YAML files will get stored.
|
||||||
11
examples/rest-api/database.py
Normal file
11
examples/rest-api/database.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from sqlalchemy import create_engine
|
||||||
|
from sqlalchemy.ext.declarative import declarative_base
|
||||||
|
from sqlalchemy.orm import sessionmaker
|
||||||
|
|
||||||
|
SQLALCHEMY_DATABASE_URI = "sqlite:///./app.db"
|
||||||
|
|
||||||
|
engine = create_engine(SQLALCHEMY_DATABASE_URI, connect_args={"check_same_thread": False})
|
||||||
|
|
||||||
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
||||||
|
|
||||||
|
Base = declarative_base()
|
||||||
17
examples/rest-api/default.yaml
Normal file
17
examples/rest-api/default.yaml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
app:
|
||||||
|
config:
|
||||||
|
id: 'default'
|
||||||
|
|
||||||
|
llm:
|
||||||
|
provider: gpt4all
|
||||||
|
config:
|
||||||
|
model: 'orca-mini-3b.ggmlv3.q4_0.bin'
|
||||||
|
temperature: 0.5
|
||||||
|
max_tokens: 1000
|
||||||
|
top_p: 1
|
||||||
|
stream: false
|
||||||
|
|
||||||
|
embedder:
|
||||||
|
provider: gpt4all
|
||||||
|
config:
|
||||||
|
model: 'all-MiniLM-L6-v2'
|
||||||
321
examples/rest-api/main.py
Normal file
321
examples/rest-api/main.py
Normal file
@@ -0,0 +1,321 @@
|
|||||||
|
import os
|
||||||
|
import yaml
|
||||||
|
from fastapi import FastAPI, UploadFile, Depends, HTTPException
|
||||||
|
from sqlalchemy.orm import Session
|
||||||
|
from embedchain import Pipeline as App
|
||||||
|
from embedchain.client import Client
|
||||||
|
from models import (
|
||||||
|
QueryApp,
|
||||||
|
SourceApp,
|
||||||
|
DefaultResponse,
|
||||||
|
DeployAppRequest,
|
||||||
|
)
|
||||||
|
from database import Base, engine, SessionLocal
|
||||||
|
from services import get_app, save_app, get_apps, remove_app
|
||||||
|
from utils import generate_error_message_for_api_keys
|
||||||
|
|
||||||
|
Base.metadata.create_all(bind=engine)
|
||||||
|
|
||||||
|
|
||||||
|
def get_db():
|
||||||
|
db = SessionLocal()
|
||||||
|
try:
|
||||||
|
yield db
|
||||||
|
finally:
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
|
||||||
|
app = FastAPI(
|
||||||
|
title="Embedchain REST API",
|
||||||
|
description="This is the REST API for Embedchain.",
|
||||||
|
version="0.0.1",
|
||||||
|
license_info={
|
||||||
|
"name": "Apache 2.0",
|
||||||
|
"url": "https://github.com/embedchain/embedchain/blob/main/LICENSE",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/ping", tags=["Utility"])
|
||||||
|
def check_status():
|
||||||
|
"""
|
||||||
|
Endpoint to check the status of the API.
|
||||||
|
"""
|
||||||
|
return {"ping": "pong"}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/apps", tags=["Apps"])
|
||||||
|
async def get_all_apps(db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
Get all apps.
|
||||||
|
"""
|
||||||
|
apps = get_apps(db)
|
||||||
|
return {"results": apps}
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/create", tags=["Apps"], response_model=DefaultResponse)
|
||||||
|
async def create_app_using_default_config(app_id: str, config: UploadFile = None, db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
Create a new app using App ID.
|
||||||
|
If you don't provide a config file, Embedchain will use the default config file\n
|
||||||
|
which uses opensource GPT4ALL model.\n
|
||||||
|
app_id: The ID of the app.\n
|
||||||
|
config: The YAML config file to create an App.\n
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if app_id is None:
|
||||||
|
raise HTTPException(detail="App ID not provided.", status_code=400)
|
||||||
|
|
||||||
|
if get_app(db, app_id) is not None:
|
||||||
|
raise HTTPException(detail=f"App with id '{app_id}' already exists.", status_code=400)
|
||||||
|
|
||||||
|
yaml_path = "default.yaml"
|
||||||
|
if config is not None:
|
||||||
|
contents = await config.read()
|
||||||
|
try:
|
||||||
|
yaml.safe_load(contents)
|
||||||
|
# TODO: validate the config yaml file here
|
||||||
|
yaml_path = f"configs/{app_id}.yaml"
|
||||||
|
with open(yaml_path, "w") as file:
|
||||||
|
file.write(str(contents, "utf-8"))
|
||||||
|
except yaml.YAMLError as exc:
|
||||||
|
raise HTTPException(detail=f"Error parsing YAML: {exc}", status_code=400)
|
||||||
|
|
||||||
|
save_app(db, app_id, yaml_path)
|
||||||
|
|
||||||
|
return DefaultResponse(response=f"App created successfully. App ID: {app_id}")
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(detail=f"Error creating app: {e}", status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
@app.get(
|
||||||
|
"/{app_id}/data",
|
||||||
|
tags=["Apps"],
|
||||||
|
)
|
||||||
|
async def get_datasources_associated_with_app_id(app_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
Get all datasources for an app.\n
|
||||||
|
app_id: The ID of the app. Use "default" for the default app.\n
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if app_id is None:
|
||||||
|
raise HTTPException(
|
||||||
|
detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.",
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
db_app = get_app(db, app_id)
|
||||||
|
|
||||||
|
if db_app is None:
|
||||||
|
raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400)
|
||||||
|
|
||||||
|
app = App.from_config(yaml_path=db_app.config)
|
||||||
|
|
||||||
|
response = app.get_data_sources()
|
||||||
|
return {"results": response}
|
||||||
|
except ValueError as ve:
|
||||||
|
if "OPENAI_API_KEY" in str(ve) or "OPENAI_ORGANIZATION" in str(ve):
|
||||||
|
raise HTTPException(
|
||||||
|
detail=generate_error_message_for_api_keys(ve),
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(detail=f"Error occurred: {e}", status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post(
|
||||||
|
"/{app_id}/add",
|
||||||
|
tags=["Apps"],
|
||||||
|
response_model=DefaultResponse,
|
||||||
|
)
|
||||||
|
async def add_datasource_to_an_app(body: SourceApp, app_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
Add a source to an existing app.\n
|
||||||
|
app_id: The ID of the app. Use "default" for the default app.\n
|
||||||
|
source: The source to add.\n
|
||||||
|
data_type: The data type of the source. Remove it if you want Embedchain to detect it automatically.\n
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if app_id is None:
|
||||||
|
raise HTTPException(
|
||||||
|
detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.",
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
db_app = get_app(db, app_id)
|
||||||
|
|
||||||
|
if db_app is None:
|
||||||
|
raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400)
|
||||||
|
|
||||||
|
app = App.from_config(yaml_path=db_app.config)
|
||||||
|
|
||||||
|
response = app.add(source=body.source, data_type=body.data_type)
|
||||||
|
return DefaultResponse(response=response)
|
||||||
|
except ValueError as ve:
|
||||||
|
if "OPENAI_API_KEY" in str(ve) or "OPENAI_ORGANIZATION" in str(ve):
|
||||||
|
raise HTTPException(
|
||||||
|
detail=generate_error_message_for_api_keys(ve),
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(detail=f"Error occurred: {e}", status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post(
|
||||||
|
"/{app_id}/query",
|
||||||
|
tags=["Apps"],
|
||||||
|
response_model=DefaultResponse,
|
||||||
|
)
|
||||||
|
async def query_an_app(body: QueryApp, app_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
Query an existing app.\n
|
||||||
|
app_id: The ID of the app. Use "default" for the default app.\n
|
||||||
|
query: The query that you want to ask the App.\n
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if app_id is None:
|
||||||
|
raise HTTPException(
|
||||||
|
detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.",
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
db_app = get_app(db, app_id)
|
||||||
|
|
||||||
|
if db_app is None:
|
||||||
|
raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400)
|
||||||
|
|
||||||
|
app = App.from_config(yaml_path=db_app.config)
|
||||||
|
|
||||||
|
response = app.query(body.query)
|
||||||
|
return DefaultResponse(response=response)
|
||||||
|
except ValueError as ve:
|
||||||
|
if "OPENAI_API_KEY" in str(ve) or "OPENAI_ORGANIZATION" in str(ve):
|
||||||
|
raise HTTPException(
|
||||||
|
detail=generate_error_message_for_api_keys(ve),
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(detail=f"Error occurred: {e}", status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME: The chat implementation of Embedchain needs to be modified to work with the REST API.
|
||||||
|
# @app.post(
|
||||||
|
# "/{app_id}/chat",
|
||||||
|
# tags=["Apps"],
|
||||||
|
# response_model=DefaultResponse,
|
||||||
|
# )
|
||||||
|
# async def chat_with_an_app(body: MessageApp, app_id: str, db: Session = Depends(get_db)):
|
||||||
|
# """
|
||||||
|
# Query an existing app.\n
|
||||||
|
# app_id: The ID of the app. Use "default" for the default app.\n
|
||||||
|
# message: The message that you want to send to the App.\n
|
||||||
|
# """
|
||||||
|
# try:
|
||||||
|
# if app_id is None:
|
||||||
|
# raise HTTPException(
|
||||||
|
# detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.",
|
||||||
|
# status_code=400,
|
||||||
|
# )
|
||||||
|
|
||||||
|
# db_app = get_app(db, app_id)
|
||||||
|
|
||||||
|
# if db_app is None:
|
||||||
|
# raise HTTPException(
|
||||||
|
# detail=f"App with id {app_id} does not exist, please create it first.",
|
||||||
|
# status_code=400
|
||||||
|
# )
|
||||||
|
|
||||||
|
# app = App.from_config(yaml_path=db_app.config)
|
||||||
|
|
||||||
|
# response = app.chat(body.message)
|
||||||
|
# return DefaultResponse(response=response)
|
||||||
|
# except ValueError as ve:
|
||||||
|
# if "OPENAI_API_KEY" in str(ve) or "OPENAI_ORGANIZATION" in str(ve):
|
||||||
|
# raise HTTPException(
|
||||||
|
# detail=generate_error_message_for_api_keys(ve),
|
||||||
|
# status_code=400,
|
||||||
|
# )
|
||||||
|
# except Exception as e:
|
||||||
|
# raise HTTPException(detail=f"Error occurred: {e}", status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
@app.post(
|
||||||
|
"/{app_id}/deploy",
|
||||||
|
tags=["Apps"],
|
||||||
|
response_model=DefaultResponse,
|
||||||
|
)
|
||||||
|
async def deploy_app(body: DeployAppRequest, app_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
Query an existing app.\n
|
||||||
|
app_id: The ID of the app. Use "default" for the default app.\n
|
||||||
|
api_key: The API key to use for deployment. If not provided,
|
||||||
|
Embedchain will use the API key previously used (if any).\n
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if app_id is None:
|
||||||
|
raise HTTPException(
|
||||||
|
detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.",
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
db_app = get_app(db, app_id)
|
||||||
|
|
||||||
|
if db_app is None:
|
||||||
|
raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400)
|
||||||
|
|
||||||
|
app = App.from_config(yaml_path=db_app.config)
|
||||||
|
|
||||||
|
api_key = body.api_key
|
||||||
|
# this will save the api key in the embedchain.db
|
||||||
|
Client(api_key=api_key)
|
||||||
|
|
||||||
|
app.deploy()
|
||||||
|
return DefaultResponse(response="App deployed successfully.")
|
||||||
|
except ValueError as ve:
|
||||||
|
if "OPENAI_API_KEY" in str(ve) or "OPENAI_ORGANIZATION" in str(ve):
|
||||||
|
raise HTTPException(
|
||||||
|
detail=generate_error_message_for_api_keys(ve),
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(detail=f"Error occurred: {e}", status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
@app.delete(
|
||||||
|
"/{app_id}/delete",
|
||||||
|
tags=["Apps"],
|
||||||
|
response_model=DefaultResponse,
|
||||||
|
)
|
||||||
|
async def delete_app(app_id: str, db: Session = Depends(get_db)):
|
||||||
|
"""
|
||||||
|
Delete an existing app.\n
|
||||||
|
app_id: The ID of the app to be deleted.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if app_id is None:
|
||||||
|
raise HTTPException(
|
||||||
|
detail="App ID not provided. If you want to use the default app, use 'default' as the app_id.",
|
||||||
|
status_code=400,
|
||||||
|
)
|
||||||
|
|
||||||
|
db_app = get_app(db, app_id)
|
||||||
|
|
||||||
|
if db_app is None:
|
||||||
|
raise HTTPException(detail=f"App with id {app_id} does not exist, please create it first.", status_code=400)
|
||||||
|
|
||||||
|
app = App.from_config(yaml_path=db_app.config)
|
||||||
|
|
||||||
|
# reset app.db
|
||||||
|
app.db.reset()
|
||||||
|
|
||||||
|
remove_app(db, app_id)
|
||||||
|
return DefaultResponse(response=f"App with id {app_id} deleted successfully.")
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(detail=f"Error occurred: {e}", status_code=400)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
is_dev = os.getenv("DEVELOPMENT", "False")
|
||||||
|
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=bool(is_dev))
|
||||||
45
examples/rest-api/models.py
Normal file
45
examples/rest-api/models.py
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
from typing import Optional
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from sqlalchemy import Column, String, Integer
|
||||||
|
from database import Base
|
||||||
|
|
||||||
|
|
||||||
|
class QueryApp(BaseModel):
|
||||||
|
query: str = Field("", description="The query that you want to ask the App.")
|
||||||
|
|
||||||
|
model_config = {
|
||||||
|
"json_schema_extra": {
|
||||||
|
"example": {
|
||||||
|
"query": "Who is Elon Musk?",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SourceApp(BaseModel):
|
||||||
|
source: str = Field("", description="The source that you want to add to the App.")
|
||||||
|
data_type: Optional[str] = Field("", description="The type of data to add, remove it for autosense.")
|
||||||
|
|
||||||
|
model_config = {"json_schema_extra": {"example": {"source": "https://en.wikipedia.org/wiki/Elon_Musk"}}}
|
||||||
|
|
||||||
|
|
||||||
|
class DeployAppRequest(BaseModel):
|
||||||
|
api_key: str = Field("", description="The Embedchain API key for App deployments.")
|
||||||
|
|
||||||
|
model_config = {"json_schema_extra": {"example": {"api_key": "ec-xxx"}}}
|
||||||
|
|
||||||
|
|
||||||
|
class MessageApp(BaseModel):
|
||||||
|
message: str = Field("", description="The message that you want to send to the App.")
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultResponse(BaseModel):
|
||||||
|
response: str
|
||||||
|
|
||||||
|
|
||||||
|
class AppModel(Base):
|
||||||
|
__tablename__ = "apps"
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
app_id = Column(String, unique=True, index=True)
|
||||||
|
config = Column(String, unique=True, index=True)
|
||||||
5
examples/rest-api/requirements.txt
Normal file
5
examples/rest-api/requirements.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
fastapi==0.104.0
|
||||||
|
uvicorn==0.23.2
|
||||||
|
embedchain==0.0.86
|
||||||
|
embedchain[dataloaders]==0.0.86
|
||||||
|
sqlalchemy==2.0.22
|
||||||
33
examples/rest-api/sample-config.yaml
Normal file
33
examples/rest-api/sample-config.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
app:
|
||||||
|
config:
|
||||||
|
id: 'default-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.
|
||||||
|
If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||||
|
|
||||||
|
$context
|
||||||
|
|
||||||
|
Query: $query
|
||||||
|
|
||||||
|
Helpful Answer:
|
||||||
|
|
||||||
|
vectordb:
|
||||||
|
provider: chroma
|
||||||
|
config:
|
||||||
|
collection_name: 'rest-api-app'
|
||||||
|
dir: db
|
||||||
|
allow_reset: true
|
||||||
|
|
||||||
|
embedder:
|
||||||
|
provider: openai
|
||||||
|
config:
|
||||||
|
model: 'text-embedding-ada-002'
|
||||||
26
examples/rest-api/services.py
Normal file
26
examples/rest-api/services.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from sqlalchemy.orm import Session
|
||||||
|
|
||||||
|
from models import AppModel
|
||||||
|
|
||||||
|
|
||||||
|
def get_app(db: Session, app_id: str):
|
||||||
|
return db.query(AppModel).filter(AppModel.app_id == app_id).first()
|
||||||
|
|
||||||
|
|
||||||
|
def get_apps(db: Session, skip: int = 0, limit: int = 100):
|
||||||
|
return db.query(AppModel).offset(skip).limit(limit).all()
|
||||||
|
|
||||||
|
|
||||||
|
def save_app(db: Session, app_id: str, config: str):
|
||||||
|
db_app = AppModel(app_id=app_id, config=config)
|
||||||
|
db.add(db_app)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(db_app)
|
||||||
|
return db_app
|
||||||
|
|
||||||
|
|
||||||
|
def remove_app(db: Session, app_id: str):
|
||||||
|
db_app = db.query(AppModel).filter(AppModel.app_id == app_id).first()
|
||||||
|
db.delete(db_app)
|
||||||
|
db.commit()
|
||||||
|
return db_app
|
||||||
21
examples/rest-api/utils.py
Normal file
21
examples/rest-api/utils.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
def generate_error_message_for_api_keys(error: ValueError) -> str:
|
||||||
|
env_mapping = {
|
||||||
|
"OPENAI_API_KEY": "OPENAI_API_KEY",
|
||||||
|
"OPENAI_API_TYPE": "OPENAI_API_TYPE",
|
||||||
|
"OPENAI_API_BASE": "OPENAI_API_BASE",
|
||||||
|
"OPENAI_API_VERSION": "OPENAI_API_VERSION",
|
||||||
|
"COHERE_API_KEY": "COHERE_API_KEY",
|
||||||
|
"ANTHROPIC_API_KEY": "ANTHROPIC_API_KEY",
|
||||||
|
"JINACHAT_API_KEY": "JINACHAT_API_KEY",
|
||||||
|
"HUGGINGFACE_ACCESS_TOKEN": "HUGGINGFACE_ACCESS_TOKEN",
|
||||||
|
"REPLICATE_API_TOKEN": "REPLICATE_API_TOKEN",
|
||||||
|
}
|
||||||
|
|
||||||
|
missing_keys = [env_mapping[key] for key in env_mapping if key in str(error)]
|
||||||
|
if missing_keys:
|
||||||
|
missing_keys_str = ", ".join(missing_keys)
|
||||||
|
return f"""Please set the {missing_keys_str} environment variable(s) when running the Docker container.
|
||||||
|
Example: `docker run -e {missing_keys[0]}=xxx embedchain/app:rest-api-latest`
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
return "Unknown error occurred."
|
||||||
Reference in New Issue
Block a user