Skip to content

Commit

Permalink
feat: support langchain powered by flowise
Browse files Browse the repository at this point in the history
Bump requests from 2.28.2 to 2.31.0

Bumps [requests](https://github.com/psf/requests) from 2.28.2 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](psf/requests@v2.28.2...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
  • Loading branch information
hibobmaster committed May 26, 2023
1 parent 6ff585d commit 600c5e1
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 11 deletions.
4 changes: 3 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ BING_AUTH_COOKIE="xxxxxxxxxxxxxxxxxxx" # _U cookie, Optional, for Bing Image Cre
MARKDOWN_FORMATTED="true" # Optional
OUTPUT_FOUR_IMAGES="true" # Optional
IMPORT_KEYS_PATH="element-keys.txt" # Optional
IMPORT_KEYS_PASSWORD="xxxxxxx" # Optional
IMPORT_KEYS_PASSWORD="xxxxxxx" # Optional
FLOWISE_API_URL="http://localhost:3000/api/v1/prediction/xxxx" # Optional
FLOWISE_API_KEY="xxxxxxxxxxxxxxxxxxxxxxx" # Optional
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
## Introduction

This is a simple Matrix bot that uses OpenAI's GPT API and Bing AI and Google Bard to generate responses to user inputs. The bot responds to five types of prompts: `!gpt`, `!chat` and `!bing` and `!pic` and `!bard` depending on the first word of the prompt.
This is a simple Matrix bot that uses OpenAI's GPT API and Bing AI and Google Bard to generate responses to user inputs. The bot responds to six types of prompts: `!gpt`, `!chat` and `!bing` and `!pic` and `!bard` and `!lc` depending on the first word of the prompt.
![Bing](https://user-images.githubusercontent.com/32976627/231073146-3e380217-a6a2-413d-9203-ab36965b909d.png)
![image](https://user-images.githubusercontent.com/32976627/232036790-e830145c-914e-40be-b3e6-c02cba93329c.png)
![ChatGPT](https://i.imgur.com/kK4rnPf.jpeg)

## Feature

1. Support Openai ChatGPT and Bing AI and Google Bard(US only at the moment)
1. Support Openai ChatGPT and Bing AI and Google Bard and Langchain([Flowise](https://github.com/FlowiseAI/Flowise))
2. Support Bing Image Creator
3. Support E2E Encrypted Room
4. Colorful code blocks
Expand All @@ -26,7 +26,7 @@ sudo docker compose up -d

<hr>
Normal Method:<br>
system dependece: `libolm-dev`
system dependece: <code>libolm-dev</code>

1. Clone the repository and create virtual environment:

Expand Down Expand Up @@ -99,7 +99,10 @@ To interact with the bot, simply send a message to the bot in the Matrix room wi
```
!bard Building a website can be done in 10 simple steps
```

- `!lc` To chat using langchain api endpoint
```
!lc 人生如音乐,欢乐且自由
```
- `!pic` To generate an image from Microsoft Bing

```
Expand Down
53 changes: 49 additions & 4 deletions bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from send_message import send_room_message
from v3 import Chatbot
from bard import Bardbot
from flowise import flowise_query

logger = getlogger()

Expand All @@ -45,6 +46,8 @@ def __init__(
output_four_images: Union[bool, None] = False,
import_keys_path: Optional[str] = None,
import_keys_password: Optional[str] = None,
flowise_api_url: Optional[str] = None,
flowise_api_key: Optional[str] = None
):
if (homeserver is None or user_id is None
or device_id is None):
Expand All @@ -66,6 +69,8 @@ def __init__(
self.chatgpt_api_endpoint = chatgpt_api_endpoint
self.import_keys_path = import_keys_path
self.import_keys_password = import_keys_password
self.flowise_api_url = flowise_api_url
self.flowise_api_key = flowise_api_key

self.session = aiohttp.ClientSession()

Expand Down Expand Up @@ -124,6 +129,7 @@ def __init__(
self.bing_prog = re.compile(r"^\s*!bing\s*(.+)$")
self.bard_prog = re.compile(r"^\s*!bard\s*(.+)$")
self.pic_prog = re.compile(r"^\s*!pic\s*(.+)$")
self.lc_prog = re.compile(r"^\s*!lc\s*(.+)$")
self.help_prog = re.compile(r"^\s*!help\s*.*$")

# initialize chatbot and chatgpt_api_endpoint
Expand Down Expand Up @@ -281,6 +287,24 @@ async def message_callback(self, room: MatrixRoom, event: RoomMessageText) -> No
logger.error(e, exc_info=True)
await send_room_message(self.client, room_id, reply_message={e})

# lc command
if self.flowise_api_url is not None:
m = self.lc_prog.match(content_body)
if m:
prompt = m.group(1)
try:
asyncio.create_task(self.lc(
room_id,
reply_to_event_id,
prompt,
sender_id,
raw_user_message
)
)
except Exception as e:
logger.error(e, exc_info=True)
await send_room_message(self.client, room_id, reply_message={e})

# help command
h = self.help_prog.match(content_body)
if h:
Expand Down Expand Up @@ -598,6 +622,26 @@ async def bard(self, room_id, reply_to_event_id, prompt, sender_id,
except Exception as e:
logger.error(e, exc_info=True)

# !lc command
async def lc(self, room_id, reply_to_event_id, prompt, sender_id,
raw_user_message) -> None:
try:
# sending typing state
await self.client.room_typing(room_id)
if self.flowise_api_key is not None:
headers = {'Authorization': f'Bearer {self.flowise_api_key}'}
response = await asyncio.to_thread(flowise_query,
self.flowise_api_url, prompt, headers)
else:
response = await asyncio.to_thread(flowise_query,
self.flowise_api_url, prompt)
await send_room_message(self.client, room_id, reply_message=response,
reply_to_event_id="", sender_id=sender_id,
user_message=raw_user_message,
markdown_formatted=self.markdown_formatted)
except Exception as e:
raise Exception(e)

# !pic command

async def pic(self, room_id, prompt):
Expand Down Expand Up @@ -629,11 +673,12 @@ async def help(self, room_id):
try:
# sending typing state
await self.client.room_typing(room_id)
help_info = "!gpt [content], generate response without context conversation\n" + \
"!chat [content], chat with context conversation\n" + \
"!bing [content], chat with context conversation powered by Bing AI\n" + \
"!bard [content], chat with Google's Bard\n" + \
help_info = "!gpt [prompt], generate response without context conversation\n" + \
"!chat [prompt], chat with context conversation\n" + \
"!bing [prompt], chat with context conversation powered by Bing AI\n" + \
"!bard [prompt], chat with Google's Bard\n" + \
"!pic [prompt], Image generation by Microsoft Bing\n" + \
"!lc [prompt], chat using langchain api\n" + \
"!help, help message" # noqa: E501

await send_room_message(self.client, room_id, reply_message=help_info)
Expand Down
4 changes: 3 additions & 1 deletion config.json.sample
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,7 @@
"markdown_formatted": true,
"output_four_images": true,
"import_keys_path": "element-keys.txt",
"import_keys_password": "xxxxxxxxx"
"import_keys_password": "xxxxxxxxx",
"flowise_api_url": "http://localhost:3000/api/v1/prediction/6deb3c89-45bf-4ac4-a0b0-b2d5ef249d21",
"flowise_api_key": "U3pe0bbVDWOyoJtsDzFJjRvHKTP3FRjODwuM78exC3A="
}
19 changes: 19 additions & 0 deletions flowise.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import requests

def flowise_query(api_url: str, prompt: str, headers: dict = None) -> str:
"""
Sends a query to the Flowise API and returns the response.
Args:
api_url (str): The URL of the Flowise API.
prompt (str): The question to ask the API.
Returns:
str: The response from the API.
"""
if headers:
response = requests.post(api_url, json={"question": prompt},
headers=headers, timeout=120)
else:
response = requests.post(api_url, json={"question": prompt}, timeout=120)
return response.text
4 changes: 4 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ async def main():
import_keys_path=config.get('import_keys_path'),
import_keys_password=config.get(
'import_keys_password'),
flowise_api_url=config.get('flowise_api_url'),
flowise_api_key=config.get('flowise_api_key'),
)
if config.get('import_keys_path') and \
config.get('import_keys_password') is not None:
Expand Down Expand Up @@ -57,6 +59,8 @@ async def main():
import_keys_path=os.environ.get("IMPORT_KEYS_PATH"),
import_keys_password=os.environ.get(
"IMPORT_KEYS_PASSWORD"),
flowise_api_url=os.environ.get("FLOWISE_API_URL"),
flowise_api_key=os.environ.get("FLOWISE_API_KEY"),
)
if os.environ.get("IMPORT_KEYS_PATH") \
and os.environ.get("IMPORT_KEYS_PASSWORD") is not None:
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ python-magic==0.4.27
python-olm==3.1.3
python-socks==2.2.0
regex==2023.3.23
requests==2.28.2
requests==2.31.0
rfc3986==1.5.0
six==1.16.0
sniffio==1.3.0
Expand Down

0 comments on commit 600c5e1

Please sign in to comment.