Compare commits

..

26 Commits

Author SHA1 Message Date
Taranjeet Singh 12eb16d60b bump version to 0.0.51 (#540) 2023-09-04 01:04:10 +05:30
Dev Khant ec9f454ad1 System prompt at App level (#484)
Co-authored-by: Taranjeet Singh <reachtotj@gmail.com>
2023-09-04 00:55:43 +05:30
Ikko Eltociear Ashimine 9f1f17a611 Fix typo in README.md (#513)
Co-authored-by: cachho <admin@ch-webdev.com>
Co-authored-by: Taranjeet Singh <reachtotj@gmail.com>
2023-09-04 00:54:18 +05:30
aryankhanna475 94369657ef Showcase Update 01-09 (#527)
Co-authored-by: Sahil Kumar Yadav <sahilyadav902@gmail.com>
Co-authored-by: Taranjeet Singh <reachtotj@gmail.com>
2023-09-04 00:52:35 +05:30
Taranjeet Singh 490d7db601 Bump version to 0.0.50 (#530) 2023-09-02 05:56:06 +05:30
Taranjeet Singh ea18b80f90 fix: update chroma init for host & port (#529) 2023-09-02 05:52:10 +05:30
Deshraj Yadav 70077f4e46 Update package version to 0.0.49 (#515) 2023-08-30 11:25:46 -07:00
cachho 85106c7c7e fix: remove stale code (#514) 2023-08-30 11:19:41 -07:00
Taranjeet Singh 1b19d0d19c bump version to 0.0.48 (#503) 2023-08-29 00:31:50 +05:30
Taranjeet Singh 13f01e399c fix: add tiktoken as required dependency in pyproject (#502) 2023-08-29 00:29:12 +05:30
Taranjeet Singh 261e2d088c Bump version to 0.0.47 (#501) 2023-08-29 00:00:35 +05:30
Taranjeet Singh b0ae3e95c7 fix: update poe bot creation docs (#500) 2023-08-28 23:59:34 +05:30
cachho fc633dadeb feat: poe bot (#492)
Co-authored-by: Taranjeet Singh <reachtotj@gmail.com>
2023-08-28 23:47:01 +05:30
Taranjeet Singh aafb334916 fix: improve CTA of book meeting (#496) 2023-08-28 08:19:47 +05:30
Taranjeet Singh 04d851e802 fix: update discord link (#494) 2023-08-28 05:33:03 +05:30
Taranjeet Singh de31c63dac feat: Add cal.com link for feedback (#493) 2023-08-28 05:12:54 +05:30
Deshraj Yadav c068f58543 [version]: bump package version to 0.0.46 2023-08-27 12:24:37 -07:00
Deshraj Yadav 70df373807 [feat]: add support for sending anonymous user_id in telemetry (#491) 2023-08-28 00:53:42 +05:30
Deshraj Yadav 4388f6bfc2 [bug-fix] fix issue related to bot memory when using multiple bots at the same time (#486) 2023-08-25 21:59:39 -07:00
Taranjeet Singh d0956a0dc1 Bump version to 0.0.45 (#479) 2023-08-25 03:22:04 +05:30
cachho ccf515cadd Fix/use poetry for build (#478) 2023-08-25 03:20:57 +05:30
Taranjeet Singh a6e4235bb0 fix: update docs (#477) 2023-08-25 03:16:15 +05:30
Taranjeet Singh 9ba408086e Bump version to 0.0.44 (#476) 2023-08-25 03:12:22 +05:30
cachho bbb3bca1c7 fix: python version string (#475) 2023-08-25 03:10:48 +05:30
Taranjeet Singh 564036a166 Bump version to 0.0.43 (#474) 2023-08-25 03:05:27 +05:30
cachho abf99ce5ea chore: add release workflow (#397) 2023-08-25 03:04:07 +05:30
17 changed files with 302 additions and 98 deletions
+4 -1
View File
@@ -1,5 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: 1-on-1 Session
url: https://cal.com/taranjeetio/ec
about: Speak directly with Taranjeet, the founder, to discuss issues, share feedback, or explore improvements for Embedchain
- name: Discord
url: https://discord.gg/6PzXDgEjG5
about: General community discussions
about: General community discussions
+32 -16
View File
@@ -1,24 +1,40 @@
name: cd
name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI
on:
release:
types:
- published
permissions:
id-token: write
contents: read
types: [published] # This will trigger the workflow when you create a new release
jobs:
publish_to_pypi:
name: publish to pypi on new release
build-n-publish:
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
runs-on: ubuntu-latest
permissions:
# IMPORTANT: this permission is mandatory for trusted publishing
id-token: write
steps:
- uses: actions/checkout@v3
- uses: JRubics/poetry-publish@v1.16
name: Build and publish to PyPI
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
pypi_token: ${{ secrets.PYPI_TOKEN }}
ignore_dev_requirements: "yes"
repository_url: https://upload.pypi.org/legacy/
repository_name: embedchain
python-version: '3.11'
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Install dependencies
run: poetry install
- name: Build a binary wheel and a source tarball
run: poetry build
- name: Publish distribution 📦 to Test PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository_url: https://test.pypi.org/legacy/
- name: Publish distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
+16 -25
View File
@@ -1,42 +1,23 @@
# embedchain
[![PyPI](https://img.shields.io/pypi/v/embedchain)](https://pypi.org/project/embedchain/)
[![Discord](https://dcbadge.vercel.app/api/server/6PzXDgEjG5?style=flat)](https://discord.gg/6PzXDgEjG5)
[![Discord](https://dcbadge.vercel.app/api/server/6PzXDgEjG5?style=flat)](https://discord.gg/CUU9FPhRNt)
[![Twitter](https://img.shields.io/twitter/follow/embedchain)](https://twitter.com/embedchain)
[![Substack](https://img.shields.io/badge/Substack-%23006f5c.svg?logo=substack)](https://embedchain.substack.com/)
[![Open in Colab](https://camo.githubusercontent.com/84f0493939e0c4de4e6dbe113251b4bfb5353e57134ffd9fcab6b8714514d4d1/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667)](https://colab.research.google.com/drive/138lMWhENGeEu7Q1-6lNbNTHGLZXBBz_B?usp=sharing)
Embedchain is a framework to easily create LLM powered bots over any dataset. If you want a javascript version, check out [embedchain-js](https://github.com/embedchain/embedchainjs)
## 🤝 Schedule a 1-on-1 Session
Book a [1-on-1 Session](https://cal.com/taranjeetio/ec) with Taranjeet, the founder, to discuss any issues, provide feedback, or explore how we can improve Embedchain for you.
## 🔧 Quick install
```bash
pip install embedchain
```
## 🔥 Latest
- **[2023/07/19]** Released support for 🦙 `llama2` model. Start creating your `llama2` based bots like this:
```python
import os
from embedchain import Llama2App
os.environ['REPLICATE_API_TOKEN'] = "REPLICATE API TOKEN"
zuck_bot = Llama2App()
# Embed your data
zuck_bot.add("https://www.youtube.com/watch?v=Ff4fRgnuFgQ")
zuck_bot.add("https://en.wikipedia.org/wiki/Mark_Zuckerberg")
# Nice, your bot is ready now. Start asking questions to your bot.
zuck_bot.query("Who is Mark Zuckerberg?")
# Answer: Mark Zuckerberg is an American internet entrepreneur and business magnate. He is the co-founder and CEO of Facebook.
```
## 🔍 Demo
Try out embedchain in your browser:
@@ -51,6 +32,16 @@ The documentation for embedchain can be found at [docs.embedchain.ai](https://do
Embedchain empowers you to create chatbot models similar to ChatGPT, using your own evolving dataset.
### Data Types Supported
* Youtube video
* PDF file
* Web page
* Sitemap
* Doc file
* Code documentation website loader
* Notion
### Queries
For example, you can use Embedchain to create an Elon Musk bot using the following code:
@@ -78,7 +69,7 @@ elon_bot.query("How many companies does Elon Musk run?")
Contributions are welcome! Please check out the issues on the repository, and feel free to open a pull request.
For more information, please see the [contributing guidelines](CONTRIBUTING.md).
For more refrence, please go through [Development Guide](https://docs.embedchain.ai/contribution/dev) and [Documentation Guide](https://docs.embedchain.ai/contribution/docs).
For more reference, please go through [Development Guide](https://docs.embedchain.ai/contribution/dev) and [Documentation Guide](https://docs.embedchain.ai/contribution/docs).
## Citation
+26
View File
@@ -38,6 +38,9 @@ Embedchain community has been super active in creating demos on top of Embedchai
- [Understanding what the LLM framework embedchain does](https://zenn.dev/hijikix/articles/4bc8d60156a436) by Daisuke Hashimoto
- [In bed with GPT and Node.js](https://dev.to/worldlinetech/in-bed-with-gpt-and-nodejs-4kh2) by Raphaël Semeteys, ([LinkedIn Post](https://www.linkedin.com/posts/raphaelsemeteys_in-bed-with-gpt-and-nodejs-activity-7088113552326029313-nn87/))
- [Using Embedchain — A powerful LangChain Python wrapper to build Chat Bots even faster!⚡](https://medium.com/@avra42/using-embedchain-a-powerful-langchain-python-wrapper-to-build-chat-bots-even-faster-35c12994a360) by Avra, ([Tweet](https://twitter.com/Avra_b/status/1686767751560310784/))
- [What is the Embedchain library?](https://jahaniwww.com/%da%a9%d8%aa%d8%a7%d8%a8%d8%ae%d8%a7%d9%86%d9%87-embedchain/) by Ali Jahani, ([LinkedIn Post](https://www.linkedin.com/posts/ajahani_aepaetaeqaexaggahyaeu-aetaexaesabraeaaeqaepaeu-activity-7097605202135904256-ppU-/))
- [LangChain is Nice, But Have You Tried EmbedChain ?](https://medium.com/thoughts-on-machine-learning/langchain-is-nice-but-have-you-tried-embedchain-215a34421cde) by FS Ndzomga, ([Tweet](https://twitter.com/ndzfs/status/1695583640372035951/))
- [Simplest Method to Build a Custom Chatbot with GPT-3.5 (via Embedchain)](https://www.ainewsletter.today/p/simplest-method-to-build-a-custom) by Arjun, ([Tweet](https://twitter.com/aiguy_arjun/status/1696393808467091758/))
### LinkedIn
@@ -50,6 +53,7 @@ Embedchain community has been super active in creating demos on top of Embedchai
- [About embedchain](https://www.linkedin.com/feed/update/urn:li:activity:7080984218914189312/) by Morris Lee
- [How to use Embedchain](https://www.linkedin.com/posts/nehaabansal_github-embedchainembedchain-framework-activity-7085830340136595456-kbW5/) by Neha Bansal
- [Youtube/Webpage summary for Energy Study](https://www.linkedin.com/posts/bar%C4%B1%C5%9F-sanl%C4%B1-34b82715_enerji-python-activity-7082735341563977730-Js0U/) by Barış Sanlı, ([Tweet](https://twitter.com/barissanli/status/1676968784979193857/))
- [Demo: How to use Embedchain? (Contains Collab Notebook link)](https://www.linkedin.com/posts/liorsinclair_embedchain-is-getting-a-lot-of-traction-because-activity-7103044695995424768-RckT/) by Lior Sinclair
### Twitter
@@ -79,9 +83,31 @@ Embedchain community has been super active in creating demos on top of Embedchai
- [AI ChatBot in 5 lines Python Code](https://www.youtube.com/watch?v=zjWvLJLksv8) by Data Engineering
- [Interview with Karl Marx](https://www.youtube.com/watch?v=5Y4Tscwj1xk) by Alexander Ray Williams
- [Vlog where we try to build a bot based on our content on the internet](https://www.youtube.com/watch?v=I2w8CWM3bx4) by DV, ([Tweet](https://twitter.com/dvcoolster/status/1688387017544261632))
- [CHAT with ANY ONLINE RESOURCES using EMBEDCHAIN|STREAMLIT with MEMORY |All OPENSOURCE](https://www.youtube.com/watch?v=TqQIHWoWTDQ&pp=ygUKZW1iZWRjaGFpbg%3D%3D) by DataInsightEdge
- [Build POWERFUL LLM Bots EASILY with Your Own Data - Embedchain - Langchain 2.0? (Tutorial)](https://www.youtube.com/watch?v=jE24Y_GasE8) by WorldofAI, ([Tweet](https://twitter.com/intheworldofai/status/1696229166922780737))
- [Embedchain: An AI knowledge base assistant for customizing enterprise private data, which can be connected to discord, whatsapp, slack, tele and other terminals (with gradio to build a request interface) in Chinese](https://www.youtube.com/watch?v=5RZzCJRk-d0) by AIGC LINK
- [Embedchain Introduction](https://www.youtube.com/watch?v=Jet9zAqyggI) by Fahd Mirza
## Mentions
### Github repos
- [Awesome-LLM](https://github.com/Hannibal046/Awesome-LLM)
- [awesome-chatgpt-api](https://github.com/reorx/awesome-chatgpt-api)
- [awesome-langchain](https://github.com/kyrolabs/awesome-langchain)
- [Awesome-Prompt-Engineering](https://github.com/promptslab/Awesome-Prompt-Engineering)
- [awesome-chatgpt](https://github.com/eon01/awesome-chatgpt)
- [Awesome-LLMOps](https://github.com/tensorchord/Awesome-LLMOps)
- [awesome-generative-ai](https://github.com/filipecalegario/awesome-generative-ai)
- [awesome-gpt](https://github.com/formulahendry/awesome-gpt)
- [awesome-ChatGPT-repositories](https://github.com/taishi-i/awesome-ChatGPT-repositories)
- [awesome-gpt-prompt-engineering](https://github.com/snwfdhmp/awesome-gpt-prompt-engineering)
- [awesome-chatgpt](https://github.com/awesome-chatgpt/awesome-chatgpt)
- [awesome-llm-and-aigc](https://github.com/sjinzh/awesome-llm-and-aigc)
- [awesome-compbio-chatgpt](https://github.com/csbl-br/awesome-compbio-chatgpt)
- [Awesome-LLM4Tool](https://github.com/OpenGVLab/Awesome-LLM4Tool)
## Meetups
- [Dash and ChatGPT: Future of AI-enabled apps 30/08/23](https://go.plotly.com/dash-chatgpt)
- [Pie & AI: Bangalore - Build end-to-end LLM app using Embedchain 01/09/23](https://www.eventbrite.com/e/pie-ai-bangalore-build-end-to-end-llm-app-using-embedchain-tickets-698045722547)
+48
View File
@@ -0,0 +1,48 @@
---
title: '🔮 Poe Bot'
---
### 🚀 Getting started
1. Install embedchain python package:
```bash
pip install embedchain[poe]
```
2. Create a free account on [Poe](https://www.poe.com?utm_source=embedchain).
3. Click "Create Bot" button on top left
4. Give it a handle and an optional description.
5. Select `Use API`.
6. Under `API URL` enter your server or ngrok address. 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.
7. Copy your api key and paste it in `.env` as `POE_API_KEY`.
8. Start the bot.
```bash
python -m embedchain.bots.poe
```
If you want to run the bot on another port, you can pass `--port option` like
```bash
python -m embedchain.bots.poe --port 5000
```
9. Click `Run check` to make sure your machine can be reached.
10. Make sure your bot is private if that's what you want.
11. Click `Create bot` at the bottom to finally create the bot
12. Now you bot is created.
### 💬 How to use
- To include data sources, use this command:
```text
/add <url_or_text>
```
- You can refer the [Supported Data formats](https://docs.embedchain.ai/advanced/data_types) section to refer the supported data types in embedchain.
- To ask the bot questions, just type your query:
```text
<your-question-here>
```
+3 -2
View File
@@ -36,7 +36,7 @@
},
{
"group": "Examples",
"pages": ["examples/full_stack", "examples/api_server", "examples/discord_bot", "examples/slack_bot", "examples/telegram_bot", "examples/whatsapp_bot"]
"pages": ["examples/full_stack", "examples/api_server", "examples/discord_bot", "examples/slack_bot", "examples/telegram_bot", "examples/whatsapp_bot", "examples/poe_bot"]
},
{
"group": "Contribution Guidelines",
@@ -47,7 +47,8 @@
"footerSocials": {
"twitter": "https://twitter.com/embedchain",
"github": "https://github.com/embedchain/embedchain",
"linkedin": "https://www.linkedin.com/company/embedchain"
"linkedin": "https://www.linkedin.com/company/embedchain",
"website": "https://embedchain.ai"
},
"backgroundImage": "/background.png",
"isWhiteLabeled": true
+14 -4
View File
@@ -1,3 +1,5 @@
from typing import Optional
import openai
from embedchain.config import AppConfig, ChatConfig
@@ -14,19 +16,27 @@ class App(EmbedChain):
dry_run(query): test your prompt without consuming tokens.
"""
def __init__(self, config: AppConfig = None):
def __init__(self, config: AppConfig = None, system_prompt: Optional[str] = None):
"""
:param config: AppConfig instance to load as configuration. Optional.
:param system_prompt: System prompt string. Optional.
"""
if config is None:
config = AppConfig()
super().__init__(config)
super().__init__(config, system_prompt)
def get_llm_model_answer(self, prompt, config: ChatConfig):
messages = []
if config.system_prompt:
messages.append({"role": "system", "content": config.system_prompt})
system_prompt = (
self.system_prompt
if self.system_prompt is not None
else config.system_prompt
if config.system_prompt is not None
else None
)
if system_prompt:
messages.append({"role": "system", "content": system_prompt})
messages.append({"role": "user", "content": prompt})
response = openai.ChatCompletion.create(
model=config.model or "gpt-3.5-turbo-0613",
+6 -2
View File
@@ -18,10 +18,11 @@ class CustomApp(EmbedChain):
dry_run(query): test your prompt without consuming tokens.
"""
def __init__(self, config: CustomAppConfig = None):
def __init__(self, config: CustomAppConfig = None, system_prompt: Optional[str] = None):
"""
:param config: Optional. `CustomAppConfig` instance to load as configuration.
:raises ValueError: Config must be provided for custom app
:param system_prompt: Optional. System prompt string.
"""
if config is None:
raise ValueError("Config must be provided for custom app")
@@ -34,7 +35,7 @@ class CustomApp(EmbedChain):
# Because these models run locally, they should have an instance running when the custom app is created
self.open_source_app = OpenSourceApp(config=config.open_source_app_config)
super().__init__(config)
super().__init__(config, system_prompt)
def set_llm_model(self, provider: Providers):
self.provider = provider
@@ -51,6 +52,9 @@ class CustomApp(EmbedChain):
"Streaming responses have not been implemented for this model yet. Please disable."
)
if config.system_prompt is None and self.system_prompt is not None:
config.system_prompt = self.system_prompt
try:
if self.provider == Providers.OPENAI:
return CustomApp._get_openai_answer(prompt, config)
+5 -3
View File
@@ -1,4 +1,5 @@
import os
from typing import Optional
from langchain.llms import Replicate
@@ -15,9 +16,10 @@ class Llama2App(EmbedChain):
query(query): finds answer to the given query using vector database and LLM.
"""
def __init__(self, config: AppConfig = None):
def __init__(self, config: AppConfig = None, system_prompt: Optional[str] = None):
"""
:param config: AppConfig instance to load as configuration. Optional.
:param system_prompt: System prompt string. Optional.
"""
if "REPLICATE_API_TOKEN" not in os.environ:
raise ValueError("Please set the REPLICATE_API_TOKEN environment variable.")
@@ -25,11 +27,11 @@ class Llama2App(EmbedChain):
if config is None:
config = AppConfig()
super().__init__(config)
super().__init__(config, system_prompt)
def get_llm_model_answer(self, prompt, config: ChatConfig = None):
# TODO: Move the model and other inputs into config
if config.system_prompt:
if self.system_prompt or config.system_prompt:
raise ValueError("Llama2App does not support `system_prompt`")
llm = Replicate(
model="a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5",
+5 -4
View File
@@ -1,5 +1,5 @@
import logging
from typing import Iterable, Union
from typing import Iterable, Union, Optional
from embedchain.config import ChatConfig, OpenSourceAppConfig
from embedchain.embedchain import EmbedChain
@@ -18,10 +18,11 @@ class OpenSourceApp(EmbedChain):
query(query): finds answer to the given query using vector database and LLM.
"""
def __init__(self, config: OpenSourceAppConfig = None):
def __init__(self, config: OpenSourceAppConfig = None, system_prompt: Optional[str] = None):
"""
:param config: OpenSourceAppConfig instance to load as configuration. Optional.
`ef` defaults to open source.
:param system_prompt: System prompt string. Optional.
"""
logging.info("Loading open source embedding model. This may take some time...") # noqa:E501
if not config:
@@ -33,7 +34,7 @@ class OpenSourceApp(EmbedChain):
self.instance = OpenSourceApp._get_instance(config.model)
logging.info("Successfully loaded open source embedding model.")
super().__init__(config)
super().__init__(config, system_prompt)
def get_llm_model_answer(self, prompt, config: ChatConfig):
return self._get_gpt4all_answer(prompt=prompt, config=config)
@@ -55,7 +56,7 @@ class OpenSourceApp(EmbedChain):
"OpenSourceApp does not support switching models at runtime. Please create a new app instance."
)
if config.system_prompt:
if self.system_prompt or config.system_prompt:
raise ValueError("OpenSourceApp does not support `system_prompt`")
response = self.instance.generate(
+79
View File
@@ -0,0 +1,79 @@
import argparse
import logging
import os
from typing import List, Optional
from fastapi_poe import PoeBot, run
from embedchain.config import QueryConfig
from .base import BaseBot
class EcPoeBot(BaseBot, PoeBot):
def __init__(self):
self.history_length = 5
super().__init__()
async def get_response(self, query):
last_message = query.query[-1].content
try:
history = (
[f"{m.role}: {m.content}" for m in query.query[-(self.history_length + 1) : -1]]
if len(query.query) > 0
else None
)
except Exception as e:
logging.error(f"Error when processing the chat history. Message is being sent without history. Error: {e}")
logging.warning(history)
answer = self.handle_message(last_message, history)
yield self.text_event(answer)
def handle_message(self, message, history: Optional[List[str]] = None):
if message.startswith("/add "):
response = self.add_data(message)
else:
response = self.ask_bot(message, history)
return response
def add_data(self, message):
data = message.split(" ")[-1]
try:
self.add(data)
response = f"Added data from: {data}"
except Exception:
logging.exception(f"Failed to add data {data}.")
response = "Some error occurred while adding data."
return response
def ask_bot(self, message, history: List[str]):
try:
config = QueryConfig(history=history)
response = self.query(message, config)
except Exception:
logging.exception(f"Failed to query {message}.")
response = "An error occurred. Please try again!"
return response
def start_command():
parser = argparse.ArgumentParser(description="EmbedChain PoeBot command line interface")
# parser.add_argument("--host", default="0.0.0.0", help="Host IP to bind")
parser.add_argument("--port", default=8080, type=int, help="Port to bind")
parser.add_argument("--api-key", type=str, help="Poe API key")
# parser.add_argument(
# "--history-length",
# default=5,
# type=int,
# help="Set the max size of the chat history. Multiplies cost, but improves conversation awareness.",
# )
args = parser.parse_args()
# FIXME: Arguments are automatically loaded by Poebot's ArgumentParser which causes it to fail.
# the port argument here is also just for show, it actually works because poe has the same argument.
run(EcPoeBot(), api_key=args.api_key or os.environ.get("POE_API_KEY"))
if __name__ == "__main__":
start_command()
+37 -9
View File
@@ -1,9 +1,11 @@
import hashlib
import importlib.metadata
import json
import logging
import os
import threading
import uuid
from pathlib import Path
from typing import Dict, Optional
import requests
@@ -25,31 +27,56 @@ load_dotenv()
ABS_PATH = os.getcwd()
DB_DIR = os.path.join(ABS_PATH, "db")
memory = ConversationBufferMemory()
HOME_DIR = str(Path.home())
CONFIG_DIR = os.path.join(HOME_DIR, ".embedchain")
CONFIG_FILE = os.path.join(CONFIG_DIR, "config.json")
class EmbedChain:
def __init__(self, config: BaseAppConfig):
def __init__(self, config: BaseAppConfig, system_prompt: Optional[str] = None):
"""
Initializes the EmbedChain instance, sets up a vector DB client and
creates a collection.
:param config: BaseAppConfig instance to load as configuration.
:param system_prompt: Optional. System prompt string.
"""
self.config = config
self.system_prompt = system_prompt
self.collection = self.config.db._get_or_create_collection(self.config.collection_name)
self.db = self.config.db
self.user_asks = []
self.is_docs_site_instance = False
self.online = False
self.memory = ConversationBufferMemory()
# Send anonymous telemetry
self.s_id = self.config.id if self.config.id else str(uuid.uuid4())
self.u_id = self._load_or_generate_user_id()
thread_telemetry = threading.Thread(target=self._send_telemetry_event, args=("init",))
thread_telemetry.start()
def _load_or_generate_user_id(self):
"""
Loads the user id from the config file if it exists, otherwise generates a new
one and saves it to the config file.
"""
if not os.path.exists(CONFIG_DIR):
os.makedirs(CONFIG_DIR)
if os.path.exists(CONFIG_FILE):
with open(CONFIG_FILE, "r") as f:
data = json.load(f)
if "user_id" in data:
return data["user_id"]
u_id = str(uuid.uuid4())
with open(CONFIG_FILE, "w") as f:
json.dump({"user_id": u_id}, f)
return u_id
def add(
self,
source,
@@ -362,8 +389,7 @@ class EmbedChain:
k["web_search_result"] = self.access_search_and_get_results(input_query)
contexts = self.retrieve_from_database(input_query, config)
global memory
chat_history = memory.load_memory_variables({})["history"]
chat_history = self.memory.load_memory_variables({})["history"]
if chat_history:
config.set_history(chat_history)
@@ -376,14 +402,14 @@ class EmbedChain:
answer = self.get_answer_from_llm(prompt, config)
memory.chat_memory.add_user_message(input_query)
self.memory.chat_memory.add_user_message(input_query)
# Send anonymous telemetry
thread_telemetry = threading.Thread(target=self._send_telemetry_event, args=("chat",))
thread_telemetry.start()
if isinstance(answer, str):
memory.chat_memory.add_ai_message(answer)
self.memory.chat_memory.add_ai_message(answer)
logging.info(f"Answer: {answer}")
return answer
else:
@@ -395,7 +421,7 @@ class EmbedChain:
for chunk in answer:
streamed_answer = streamed_answer + chunk
yield chunk
memory.chat_memory.add_ai_message(streamed_answer)
self.memory.chat_memory.add_ai_message(streamed_answer)
logging.info(f"Answer: {streamed_answer}")
def set_collection(self, collection_name):
@@ -445,9 +471,11 @@ class EmbedChain:
"version": importlib.metadata.version(__package__ or __name__),
"method": method,
"language": "py",
"u_id": self.u_id,
}
if extra_metadata:
metadata.update(extra_metadata)
response = requests.post(url, json={"metadata": metadata})
response.raise_for_status()
if response.status_code != 200:
logging.warning(f"Telemetry event failed with status code {response.status_code}")
-9
View File
@@ -93,15 +93,6 @@ def use_pysqlite3():
"Error:",
e,
)
__import__("pysqlite3")
sys.modules["sqlite3"] = sys.modules.pop("pysqlite3")
# Let the user know what happened.
current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S,%f")[:-3]
print(
f"{current_time} [embedchain] [INFO]",
"Swapped std-lib sqlite3 with pysqlite3 for ChromaDb compatibility.",
f"Your original version was {sqlite3.sqlite_version}.",
)
def format_source(source: str, limit: int = 20) -> str:
+1 -2
View File
@@ -28,8 +28,7 @@ class ChromaDB(BaseVectorDB):
if host and port:
logging.info(f"Connecting to ChromaDB server: {host}:{port}")
self.settings = Settings(chroma_server_host=host, chroma_server_http_port=port)
self.client = chromadb.HttpClient(self.settings)
self.client = chromadb.HttpClient(host=host, port=8000)
else:
if db_dir is None:
db_dir = "db"
+4 -2
View File
@@ -1,6 +1,6 @@
[tool.poetry]
name = "embedchain"
version = "0.0.42"
version = "0.0.51"
description = "embedchain is a framework to easily create LLM powered bots over any dataset"
authors = ["Taranjeet Singh"]
license = "Apache License"
@@ -85,6 +85,7 @@ python-dotenv = "^1.0.0"
langchain = "^0.0.237"
requests = "^2.31.0"
openai = "^0.27.5"
tiktoken = "^0.4.0"
chromadb ="^0.4.2"
youtube-transcript-api = "^0.6.1"
beautifulsoup4 = "^4.12.2"
@@ -98,6 +99,7 @@ gpt4all = { version = "^1.0.8", optional = true }
elasticsearch = { version = "^8.9.0", optional = true }
flask = "^2.3.3"
twilio = "^8.5.0"
fastapi-poe = { version = "0.0.16", optional = true }
@@ -116,10 +118,10 @@ streamlit = ["streamlit"]
community = ["llama-index"]
opensource = ["sentence-transformers", "torch", "gpt4all"]
elasticsearch = ["elasticsearch"]
poe = ["fastapi-poe"]
[tool.poetry.group.docs.dependencies]
[tool.poetry.scripts]
+5 -17
View File
@@ -7,15 +7,13 @@ from embedchain.config import AppConfig
class TestApp(unittest.TestCase):
os.environ["OPENAI_API_KEY"] = "test_key"
def setUp(self):
os.environ["OPENAI_API_KEY"] = "test_key"
self.app = App(config=AppConfig(collect_metrics=False))
@patch("embedchain.embedchain.memory", autospec=True)
@patch.object(App, "retrieve_from_database", return_value=["Test context"])
@patch.object(App, "get_answer_from_llm", return_value="Test answer")
def test_chat_with_memory(self, mock_answer, mock_retrieve, mock_memory):
def test_chat_with_memory(self, mock_get_answer, mock_retrieve):
"""
This test checks the functionality of the 'chat' method in the App class with respect to the chat history
memory.
@@ -23,27 +21,17 @@ class TestApp(unittest.TestCase):
The second call is expected to use the chat history from the first call.
Key assumptions tested:
- After the first call, 'memory.chat_memory.add_user_message' and 'memory.chat_memory.add_ai_message' are
called with correct arguments, adding the correct chat history.
- After the first call, 'memory.chat_memory.add_user_message' and 'memory.chat_memory.add_ai_message' are
- During the second call, the 'chat' method uses the chat history from the first call.
The test isolates the 'chat' method behavior by mocking out 'retrieve_from_database', 'get_answer_from_llm' and
'memory' methods.
"""
mock_memory.load_memory_variables.return_value = {"history": []}
app = App()
# First call to chat
first_answer = app.chat("Test query 1")
self.assertEqual(first_answer, "Test answer")
mock_memory.chat_memory.add_user_message.assert_called_once_with("Test query 1")
mock_memory.chat_memory.add_ai_message.assert_called_once_with("Test answer")
mock_memory.chat_memory.add_user_message.reset_mock()
mock_memory.chat_memory.add_ai_message.reset_mock()
# Second call to chat
self.assertEqual(len(app.memory.chat_memory.messages), 2)
second_answer = app.chat("Test query 2")
self.assertEqual(second_answer, "Test answer")
mock_memory.chat_memory.add_user_message.assert_called_once_with("Test query 2")
mock_memory.chat_memory.add_ai_message.assert_called_once_with("Test answer")
self.assertEqual(len(app.memory.chat_memory.messages), 4)
+17 -2
View File
@@ -43,7 +43,7 @@ class TestApp(unittest.TestCase):
mock_answer.assert_called_once()
@patch("openai.ChatCompletion.create")
def test_query_config_passing(self, mock_create):
def test_query_config_app_passing(self, mock_create):
mock_create.return_value = {"choices": [{"message": {"content": "response"}}]} # Mock response
config = AppConfig()
@@ -52,9 +52,24 @@ class TestApp(unittest.TestCase):
app.get_llm_model_answer("Test query", chat_config)
# Test systemp_prompt: Check that the 'create' method was called with the correct 'messages' argument
# Test system_prompt: Check that the 'create' method was called with the correct 'messages' argument
messages_arg = mock_create.call_args.kwargs["messages"]
self.assertEqual(messages_arg[0]["role"], "system")
self.assertEqual(messages_arg[0]["content"], "Test system prompt")
# TODO: Add tests for other config variables
@patch("openai.ChatCompletion.create")
def test_app_passing(self, mock_create):
mock_create.return_value = {"choices": [{"message": {"content": "response"}}]} # Mock response
config = AppConfig()
chat_config = QueryConfig()
app = App(config=config, system_prompt="Test system prompt")
app.get_llm_model_answer("Test query", chat_config)
# Test system_prompt: Check that the 'create' method was called with the correct 'messages' argument
messages_arg = mock_create.call_args.kwargs["messages"]
self.assertEqual(messages_arg[0]["role"], "system")
self.assertEqual(messages_arg[0]["content"], "Test system prompt")