Browse Source

working single login

master
Hendrik Langer 1 year ago
commit
46bdcd5087
  1. 166
      .gitignore
  2. 0
      Dockerfile
  3. 0
      LICENSE
  4. 18
      Pipfile
  5. 1397
      Pipfile.lock
  6. 17
      README.md
  7. 0
      matrix_pygmalion_bot/__init__.py
  8. 0
      matrix_pygmalion_bot/ai/__init__.py
  9. 118
      matrix_pygmalion_bot/ai/llama_cpp.py
  10. 228
      matrix_pygmalion_bot/ai/runpod_pygmalion.py
  11. 284
      matrix_pygmalion_bot/core.py
  12. 15
      matrix_pygmalion_bot/helpers.py
  13. 25
      matrix_pygmalion_bot/translate.py
  14. 7
      requirements.txt
  15. 9
      run.py
  16. 9
      runpod/example/Dockerfile
  17. 21
      runpod/example/handler.py
  18. 18
      runpod/runpod-worker-deliberate/Dockerfile
  19. 39
      runpod/runpod-worker-deliberate/handler.py
  20. 11
      runpod/runpod-worker-deliberate/start.sh
  21. 18
      runpod/runpod-worker-hassanblend/Dockerfile
  22. 39
      runpod/runpod-worker-hassanblend/handler.py
  23. 11
      runpod/runpod-worker-hassanblend/start.sh
  24. 6
      setup.py

166
.gitignore

@ -0,0 +1,166 @@
# Custom
bot.conf
.store
images/
runpod-test*
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

0
Dockerfile

0
LICENSE

18
Pipfile

@ -0,0 +1,18 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
matrix-nio = "*"
transformers = "*"
huggingface-hub = "*"
asyncio = "*"
python-magic = "*"
pillow = "*"
argostranslate = "*"
[dev-packages]
[requires]
python_version = "3.11"

1397
Pipfile.lock

File diff suppressed because it is too large

17
README.md

@ -0,0 +1,17 @@
# matrix-pygmalion-bot
## Setup
```sh
# install dependencies
pipenv install --dev
pipenv shell
python3 run.py
```
## Other
```sh
python3 -m venv env
source env/bin/activate
pip install -r requirements.txt
```

0
matrix_pygmalion_bot/__init__.py

0
matrix_pygmalion_bot/ai/__init__.py

118
matrix_pygmalion_bot/ai/llama_cpp.py

@ -0,0 +1,118 @@
# https://github.com/nsarrazin/serge/blob/main/api/utils/generate.py
import subprocess, os
import asyncio
import logging
logger = logging.getLogger(__name__)
async def generate(
prompt: str,
):
CHUNK_SIZE = 4
args = (
"/home/hendrik/Projects/AI/alpaca.cpp/chat",
"--model",
"/home/hendrik/Projects/AI/alpaca.cpp/" + "ggml-alpaca-7b-q4.bin",
"--prompt",
prompt,
"--n_predict",
str(256),
"--temp",
str(0.1),
"--top_k",
str(50),
"--top_p",
str(0.95),
"--repeat_last_n",
str(64),
"--repeat_penalty",
str(1.3),
"--ctx_size",
str(512),
"--threads",
str(4)
)
logger.debug(f"Calling LLaMa with arguments", args)
print(prompt)
procLlama = await asyncio.create_subprocess_exec(
*args, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
while True:
chunk = await procLlama.stdout.read(CHUNK_SIZE)
if not chunk:
return_code = await procLlama.wait()
if return_code != 0:
error_output = await procLlama.stderr.read()
logger.error(error_output.decode("utf-8"))
raise ValueError(f"RETURN CODE {return_code}\n\n"+error_output.decode("utf-8"))
else:
return
try:
chunk = chunk.decode("utf-8")
except UnicodeDecodeError:
return
yield chunk
async def get_full_prompt(simple_prompt: str, chat_history=None):
prompt = "Below is an instruction that describes a task. Write a response that appropriately completes the request." + "\n\n"
HISTORY_LEN = 5
if chat_history:
for message in chat_history[-HISTORY_LEN:]:
if not message["is_own_message"]:
prompt += "### Instruction:\n" + message["message"] + "\n"
else:
prompt += "### Response:\n" + message["message"] + "\n"
prompt += "### Instruction:\n" + simple_prompt + "\n"
prompt += "### Response:\n"
return prompt
async def get_full_prompt_with_input(simple_prompt: str, additional_input: str, chat_history=None):
prompt_with_input = "Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request." + "\n\n"
HISTORY_LEN = 5
if chat_history:
for message in chat_history[-HISTORY_LEN:]:
if not message["is_own_message"]:
prompt += "### Instruction:\n" + message["message"] + "\n"
else:
prompt += "### Response:\n" + message["message"] + "\n"
prompt += "### Instruction:\n" + simple_prompt + "\n"
prompt += "### Input:\n" + additional_input + "\n"
prompt += "### Response:\n"
return prompt
async def get_full_prompt_chat_style(simple_prompt: str, chat_history=None):
prompt = "Transcript of a dialog, where the User interacts with an Assistant named Julia. Julia is helpful, kind, honest, good at writing, and never fails to answer the User's requests immediately and with precision." + "\n\n"
HISTORY_LEN = 5
if chat_history:
for message in chat_history[-HISTORY_LEN:]:
if not message["is_own_message"]:
prompt += "User: " + message["message"] + "\n"
else:
prompt += "Julia: " + message["message"] + "\n"
prompt += "User: " + simple_prompt + "\n"
prompt += "Julia: "
return prompt

228
matrix_pygmalion_bot/ai/runpod_pygmalion.py

@ -0,0 +1,228 @@
import asyncio
import os, tempfile
import logging
import requests
from transformers import AutoTokenizer, AutoConfig
from huggingface_hub import hf_hub_download
logger = logging.getLogger(__name__)
async def generate_sync(
prompt: str,
api_key: str,
):
# Set the API endpoint URL
endpoint = "https://api.runpod.ai/v2/pygmalion-6b/runsync"
# Set the headers for the request
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
max_new_tokens = 200
prompt_num_tokens = await num_tokens(prompt)
# Define your inputs
input_data = {
"input": {
"prompt": prompt,
"max_length": max(prompt_num_tokens+max_new_tokens, 2048),
"temperature": 0.75
}
}
logger.info(f"sending request to runpod.io")
# Make the request
r = requests.post(endpoint, json=input_data, headers=headers, timeout=180)
r_json = r.json()
logger.info(r_json)
status = r_json["status"]
if status == 'COMPLETED':
text = r_json["output"]
answer = text.removeprefix(prompt)
# lines = reply.split('\n')
# reply = lines[0].strip()
idx = answer.find(f"\nYou:")
if idx != -1:
reply = answer[:idx].strip()
else:
reply = answer.removesuffix('<|endoftext|>').strip()
return reply
elif status == 'IN_PROGRESS' or status == 'IN_QUEUE':
job_id = r_json["id"]
TIMEOUT = 180
DELAY = 5
for i in range(TIMEOUT//DELAY):
endpoint = "https://api.runpod.ai/v2/pygmalion-6b/status/" + job_id
r = requests.get(endpoint, headers=headers)
r_json = r.json()
logger.info(r_json)
status = r_json["status"]
if status == 'IN_PROGRESS':
await asyncio.sleep(DELAY)
elif status == 'IN_QUEUE':
await asyncio.sleep(DELAY)
elif status == 'COMPLETED':
text = r_json["output"]
answer = text.removeprefix(prompt)
# lines = reply.split('\n')
# reply = lines[0].strip()
idx = answer.find(f"\nYou:")
if idx != -1:
reply = answer[:idx].strip()
else:
reply = answer.removesuffix('<|endoftext|>').strip()
return reply
else:
return "<ERROR>"
else:
return "<ERROR>"
async def get_full_prompt(simple_prompt: str, bot):
# Prompt without history
prompt = bot.name + "'s Persona: " + bot.persona + "\n"
prompt += "Scenario: " + bot.scenario + "\n"
prompt += "<START>" + "\n"
#prompt += bot.name + ": " + bot.greeting + "\n"
prompt += "You: " + simple_prompt + "\n"
prompt += bot.name + ":"
MAX_TOKENS = 2048
max_new_tokens = 200
total_num_tokens = await num_tokens(prompt)
visible_history = []
current_message = True
for key, chat_item in reversed(bot.chat_history.items()):
if current_message:
current_message = False
continue
if chat_item.message.startswith('!begin'):
break
if chat_item.message.startswith('!'):
continue
#if chat_item.message == bot.greeting:
# continue
print("History: " + str(chat_item))
if chat_item.num_tokens == None:
chat_item.num_tokens = await num_tokens(chat_item.getLine())
# TODO: is it MAX_TOKENS or MAX_TOKENS - max_new_tokens??
if total_num_tokens < (MAX_TOKENS - max_new_tokens):
visible_history.append(chat_item)
total_num_tokens += chat_item.num_tokens
print(total_num_tokens)
print("Finally: "+ str(total_num_tokens))
visible_history = reversed(visible_history)
prompt = bot.name + "'s Persona: " + bot.persona + "\n"
prompt += "Scenario: " + bot.scenario + "\n"
prompt += "<START>" + "\n"
#prompt += bot.name + ": " + bot.greeting + "\n"
for chat_item in visible_history:
if chat_item.is_own_message:
prompt += bot.name + ": " + chat_item.message + "\n"
else:
prompt += "You" + ": " + chat_item.message + "\n"
prompt += "You: " + simple_prompt + "\n"
prompt += bot.name + ":"
return prompt
async def num_tokens(input_text: str):
# os.makedirs("./models/pygmalion-6b", exist_ok=True)
# hf_hub_download(repo_id="PygmalionAI/pygmalion-6b", filename="config.json", cache_dir="./models/pygmalion-6b")
# config = AutoConfig.from_pretrained("./models/pygmalion-6b/config.json")
tokenizer = AutoTokenizer.from_pretrained("PygmalionAI/pygmalion-6b")
encoding = tokenizer.encode(input_text, add_special_tokens=False)
max_input_size = tokenizer.max_model_input_sizes
return len(encoding)
async def estimate_num_tokens(input_text: str):
return len(input_text)//4+1
async def generate_image(input_prompt: str, negative_prompt: str, api_key: str):
# Set the API endpoint URL
endpoint = "https://api.runpod.ai/v1/sd-anything-v4/run"
# Set the headers for the request
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {api_key}"
}
# Define your inputs
input_data = {
"input": {
"prompt": input_prompt,
"negative_prompt": negative_prompt,
"width": 512,
"height": 768,
"nsfw": True
}
}
logger.info(f"sending request to runpod.io")
# Make the request
r = requests.post(endpoint, json=input_data, headers=headers)
r_json = r.json()
logger.info(r_json)
if r.status_code == 200:
status = r_json["status"]
if status != 'IN_QUEUE':
raise ValueError(f"RETURN CODE {status}")
job_id = r_json["id"]
TIMEOUT = 180
DELAY = 5
for i in range(TIMEOUT//DELAY):
endpoint = "https://api.runpod.ai/v1/sd-anything-v4/status/" + job_id
r = requests.get(endpoint, headers=headers)
r_json = r.json()
logger.info(r_json)
status = r_json["status"]
if status == 'IN_PROGRESS':
await asyncio.sleep(DELAY)
elif status == 'IN_QUEUE':
await asyncio.sleep(DELAY)
elif status == 'COMPLETED':
output = r_json["output"]
break
else:
raise ValueError(f"RETURN CODE {status}")
os.makedirs("./images", exist_ok=True)
files = []
for image in output:
temp_name = next(tempfile._get_candidate_names())
filename = "./images/" + temp_name + ".jpg"
await download_image(image["image"], filename)
files.append(filename)
return files
async def download_image(url, path):
r = requests.get(url, stream=True)
if r.status_code == 200:
with open(path, 'wb') as f:
for chunk in r:
f.write(chunk)

284
matrix_pygmalion_bot/core.py

@ -0,0 +1,284 @@
import asyncio
import nio
from nio import (AsyncClient, AsyncClientConfig, MatrixRoom, RoomMessageText, InviteEvent, UploadResponse)
import os, sys
import importlib
import configparser
import logging
import aiofiles.os
import magic
from PIL import Image
from .helpers import ChatItem
ai = importlib.import_module("matrix_pygmalion_bot.ai.runpod_pygmalion")
#from .llama_cpp import generate, get_full_prompt, get_full_prompt_chat_style
#from .runpod_pygmalion import generate_sync, get_full_prompt
import matrix_pygmalion_bot.translate as translate
STORE_PATH = "./.store/"
logger = logging.getLogger(__name__)
config = configparser.ConfigParser()
bots = []
class Callbacks(object):
"""Class to pass client to callback methods."""
def __init__(self, client: AsyncClient, bot):
self.client = client
self.bot = bot
async def message_cb(self, room: MatrixRoom, event: RoomMessageText) -> None:
message = event.body
is_own_message = False
if event.sender == self.client.user:
is_own_message = True
is_command = False
if event.body.startswith('!'):
is_command = True
relates_to = None
if 'm.relates_to' in event.source["content"]:
relates_to = event.source["content"]['m.relates_to']["event_id"]
translated_message = message
if not (self.bot.translate is None) and not is_command:
if 'original_message' in event.source["content"]:
translated_message = event.source["content"]['original_message']
else:
translated_message = translate.translate(message, self.bot.translate, "en")
if hasattr(event, 'body'):
self.bot.chat_history[event.event_id] = ChatItem(event.event_id, event.server_timestamp, room.user_name(event.sender), is_own_message, relates_to, translated_message)
if self.bot.not_synced:
return
print(
"Message received for room {} | {}: {}".format(
room.display_name, room.user_name(event.sender), event.body
)
)
await self.client.room_read_markers(room.room_id, event.event_id, event.event_id)
# Ignore messages from ourselves
if is_own_message:
return
if hasattr(event, 'body') and event.body.startswith('!replybot'):
print(event)
await self.bot.send_message(self.client, room.room_id, "Hello World!")
return
elif hasattr(event, 'body') and event.body.startswith('!image'):
prompt = event.body.removeprefix('!image').strip()
negative_prompt = "out of frame, (ugly:1.3), (fused fingers), (too many fingers), (bad anatomy:1.5), (watermark:1.5), (words), letters, untracked eyes, asymmetric eyes, floating head, (logo:1.5), (bad hands:1.3), (mangled hands:1.2), (missing hands), (missing arms), backward hands, floating jewelry, unattached jewelry, floating head, doubled head, unattached head, doubled head, head in body, (misshapen body:1.1), (badly fitted headwear:1.2), floating arms, (too many arms:1.5), limbs fused with body, (facial blemish:1.5), badly fitted clothes, imperfect eyes, untracked eyes, crossed eyes, hair growing from clothes, partial faces, hair not attached to head"
if len(prompt) == 0:
prompt = "a beautiful woman"
output = await ai.generate_image(prompt, negative_prompt, self.bot.runpod_api_key)
for imagefile in output:
await self.bot.send_image(self.client, room.room_id, imagefile)
return
elif hasattr(event, 'body') and event.body.startswith('!begin'):
self.bot.chat_history = {}
await self.bot.send_message(self.client, room.room_id, self.bot.greeting)
return
elif event.body.startswith('!!!'):
return
# chat_history_event_id, chat_history_item = self.bot.chat_history.popitem() # current
# await self.client.room_redact(room.room_id, chat_history_item.event_id, reason="user-request")
# chat_history_event_id, chat_history_item = self.bot.chat_history.popitem()
# await self.client.room_redact(room.room_id, chat_history_item.event_id, reason="user-request")
# chat_history_event_id, chat_history_item = self.bot.chat_history.popitem()
# await self.client.room_redact(room.room_id, chat_history_item.event_id, reason="user-request")
# return
elif event.body.startswith('!!'):
return
# chat_history_event_id, chat_history_item = self.bot.chat_history.popitem() # current
# await self.client.room_redact(room.room_id, chat_history_item.event_id, reason="user-request")
# chat_history_event_id, chat_history_item = self.bot.chat_history.popitem()
# await self.client.room_redact(room.room_id, chat_history_item.event_id, reason="user-request")
# chat_history_event_id, chat_history_item = self.bot.chat_history.popitem() # new current
# self.bot.chat_history[chat_history_event_id] = chat_history_item
# message = chat_history_item.message
# # don't return, we generate a new answer
full_prompt = await ai.get_full_prompt(translated_message, self.bot)
num_tokens = await ai.num_tokens(full_prompt)
logger.info(full_prompt)
logger.info(f"num tokens:" + str(num_tokens))
# answer = ""
# time = 0
# error = None
# try:
# async for output in generate(full_prompt):
# await asyncio.sleep(0.1)
# answer += output
# if time % 5 == 0:
# await self.client.room_typing(room.room_id, True, 15000)
# time +=1
# print(output, end='', flush=True)
# except Exception as e:
# error = e.__str__()
# answer = answer.strip()
# print("")
await self.client.room_typing(room.room_id, True, 15000)
answer = await ai.generate_sync(full_prompt, self.bot.runpod_api_key)
answer = answer.strip()
await self.client.room_typing(room.room_id, False)
translated_answer = answer
if not (self.bot.translate is None):
translated_answer = translate.translate(answer, "en", self.bot.translate)
await self.bot.send_message(self.client, room.room_id, translated_answer, reply_to=event.event_id, original_message=answer)
else:
await self.bot.send_message(self.client, room.room_id, answer, reply_to=event.event_id)
async def invite_cb(self, room: MatrixRoom, event: InviteEvent) -> None:
"""Automatically join all rooms we get invited to"""
result = await self.client.join(room.room_id)
print('Invited to room: {} {}'.format(room.name, room.room_id))
if isinstance(result, nio.responses.JoinResponse):
print('Joined')
else:
print("Error joining room: {}".format(str(result)))
class ChatBot(object):
"""Main chatbot"""
def __init__(self, homeserver, user_id, password):
self.homeserver = homeserver
self.user_id = user_id
self.password = password
self.runpod_api_key = None
self.client = None
self.callbacks = None
self.config = None
self.not_synced = True
self.owner = None
self.translate = None
self.name = None
self.persona = None
self.scenario = None
self.greeting = None
self.chat_history = {}
if STORE_PATH and not os.path.isdir(STORE_PATH):
os.mkdir(STORE_PATH)
def character_init(self, name, persona, scenario, greeting):
self.name = name
self.persona = persona
self.scenario = scenario
self.greeting = greeting
async def login(self):
self.config = AsyncClientConfig(store_sync_tokens=True)
self.client = AsyncClient(self.homeserver, self.user_id, store_path=STORE_PATH, config=self.config)
self.callbacks = Callbacks(self.client, self)
self.client.add_event_callback(self.callbacks.message_cb, RoomMessageText)
self.client.add_event_callback(self.callbacks.invite_cb, InviteEvent)
sync_task = asyncio.create_task(self.watch_for_sync(self.client.synced))
try:
response = await self.client.login(self.password)
print(response)
await self.client.sync_forever(timeout=30000, full_state=True)
except (asyncio.CancelledError, KeyboardInterrupt):
print("Received interrupt.")
await self.client.close()
async def watch_for_sync(self, sync_event):
print("Awaiting sync")
await sync_event.wait()
print("Client is synced")
self.not_synced = False
async def send_message(self, client, room_id, message, reply_to=None, original_message=None):
content={"msgtype": "m.text", "body": message}
if reply_to:
content["m.relates_to"] = {"event_id": reply_to, "rel_type": "de.xd0.mpygbot.in_reply_to"}
if original_message:
content["original_message"] = original_message
await client.room_send(
room_id=room_id,
message_type="m.room.message",
content=content,
)
async def send_image(self, client, room_id, image):
"""Send image to room
https://matrix-nio.readthedocs.io/en/latest/examples.html#sending-an-image
"""
mime_type = magic.from_file(image, mime=True) # e.g. "image/jpeg"
if not mime_type.startswith("image/"):
logger.error("Drop message because file does not have an image mime type.")
return
im = Image.open(image)
(width, height) = im.size # im.size returns (width,height) tuple
# first do an upload of image, then send URI of upload to room
file_stat = await aiofiles.os.stat(image)
async with aiofiles.open(image, "r+b") as f:
resp, maybe_keys = await client.upload(
f,
content_type=mime_type, # image/jpeg
filename=os.path.basename(image),
filesize=file_stat.st_size,
)
if isinstance(resp, UploadResponse):
print("Image was uploaded successfully to server. ")
else:
print(f"Failed to upload image. Failure response: {resp}")
content = {
"body": os.path.basename(image), # descriptive title
"info": {
"size": file_stat.st_size,
"mimetype": mime_type,
"thumbnail_info": None, # TODO
"w": width, # width in pixel
"h": height, # height in pixel
"thumbnail_url": None, # TODO
},
"msgtype": "m.image",
"url": resp.content_uri,
}
try:
await client.room_send(room_id, message_type="m.room.message", content=content)
print("Image was sent successfully")
except Exception:
print(f"Image send of file {image} failed.")
async def main() -> None:
config.read('bot.conf')
logging.basicConfig(level=logging.INFO)
for section in config.sections():
if section == 'DEFAULT' or section == 'Common':
pass
botname = section
homeserver = config[section]['url']
user_id = config[section]['username']
password = config[section]['password']
bot = ChatBot(homeserver, user_id, password)
bot.character_init(botname, config[section]['persona'], config[section]['scenario'], config[section]['greeting'])
if config.has_option(section, 'owner'):
bot.owner = config[section]['owner']
if config.has_option(section, 'translate'):
bot.translate = config[section]['translate']
translate.init(bot.translate, "en")
translate.init("en", bot.translate)
if config.has_option(section, 'image_prompt'):
bot.image_prompt = config[section]['image_prompt']
if config.has_option('DEFAULT', 'runpod_api_key'):
bot.runpod_api_key = config['DEFAULT']['runpod_api_key']
bots.append(bot)
await bot.login()
print("logged in")
asyncio.get_event_loop().run_until_complete(main())

15
matrix_pygmalion_bot/helpers.py

@ -0,0 +1,15 @@
class ChatItem:
def __init__(self, event_id, timestamp, user_name, is_own_message, relates_to_event, message):
self.event_id = event_id
self.timestamp = timestamp
self.user_name = user_name
self.is_own_message = is_own_message
self.relates_to_event = relates_to_event
self.message = message
self.num_tokens = None
def __str__(self):
return str("{}: {}".format(self.user_name, self.message))
def getLine(self):
return str("{}: {}".format(self.user_name, self.message))

25
matrix_pygmalion_bot/translate.py

@ -0,0 +1,25 @@
import argostranslate.package
import argostranslate.translate
#from_code = "de"
#to_code = "en"
def init(from_code, to_code):
# Download and install Argos Translate package
argostranslate.package.update_package_index()
available_packages = argostranslate.package.get_available_packages()
package_to_install = next(
filter(
lambda x: x.from_code == from_code and x.to_code == to_code, available_packages
)
)
argostranslate.package.install_from_path(package_to_install.download())
def translate(text, from_code, to_code):
if (from_code is None) or (to_code is None):
return text
# Translate
translatedText = argostranslate.translate.translate(text, from_code, to_code)
print('Translated: \"{}\" -> \"{}\"'.format(text, translatedText))
return translatedText
# '¡Hola Mundo!'

7
requirements.txt

@ -0,0 +1,7 @@
asyncio
matrix-nio
transformers
huggingface_hub
python-magic
pillow
argostranslate

9
run.py

@ -0,0 +1,9 @@
#!/usr/bin/env python3
import asyncio
try:
from matrix_pygmalion_bot import core
asyncio.get_event_loop().run_until_complete(core.main())
except ImportError as e:
print("Unable to import matrix-pygmalion-bot.main:", e)

9
runpod/example/Dockerfile

@ -0,0 +1,9 @@
from python:3.11.1-buster
WORKDIR /
RUN pip install runpod
ADD handler.py .
CMD [ "python", "-u", "/handler.py" ]

21
runpod/example/handler.py

@ -0,0 +1,21 @@
#!/usr/bin/env python
''' Contains the handler function that will be called by the serverless. '''
import runpod
# Load models into VRAM here so they can be warm between requests
def handler(event):
'''
This is the handler function that will be called by the serverless.
'''
print(event)
# do the things
# return the output that you want to be returned like pre-signed URLs to output artifacts
return "Hello World"
runpod.serverless.start({"handler": handler})

18
runpod/runpod-worker-deliberate/Dockerfile

@ -0,0 +1,18 @@
FROM runpod/stable-diffusion:web-automatic-1.5.16
SHELL ["/bin/bash", "-c"]
ENV PATH="${PATH}:/workspace/stable-diffusion-webui/venv/bin"
WORKDIR /
RUN rm /workspace/v1-5-pruned-emaonly.ckpt
RUN wget -O model.safetensors https://civitai.com/api/download/models/5616
RUN pip install -U xformers
RUN pip install runpod
ADD handler.py .
ADD start.sh /start.sh
RUN chmod +x /start.sh
CMD [ "/start.sh" ]

39
runpod/runpod-worker-deliberate/handler.py

@ -0,0 +1,39 @@
import runpod
import subprocess
import requests
import time
def check_api_availability(host):
while True:
try:
response = requests.get(host)
return
except requests.exceptions.RequestException as e:
print(f"API is not available, retrying in 200ms... ({e})")
except Exception as e:
print('something went wrong')
time.sleep(200/1000)
check_api_availability("http://127.0.0.1:3000/sdapi/v1/txt2img")
print('run handler')
def handler(event):
'''
This is the handler function that will be called by the serverless.
'''
print('got event')
print(event)
response = requests.post(url=f'http://127.0.0.1:3000/sdapi/v1/txt2img', json=event["input"])
json = response.json()
# do the things
print(json)
# return the output that you want to be returned like pre-signed URLs to output artifacts
return json
runpod.serverless.start({"handler": handler})

11
runpod/runpod-worker-deliberate/start.sh

@ -0,0 +1,11 @@
#!/bin/bash
echo "Container Started"
export PYTHONUNBUFFERED=1
source /workspace/stable-diffusion-webui/venv/bin/activate
cd /workspace/stable-diffusion-webui
echo "starting api"
python webui.py --port 3000 --nowebui --api --xformers --ckpt /model.safetensors &
cd /
echo "starting worker"
python -u handler.py

18
runpod/runpod-worker-hassanblend/Dockerfile

@ -0,0 +1,18 @@
FROM runpod/stable-diffusion:web-automatic-1.5.16
SHELL ["/bin/bash", "-c"]
ENV PATH="${PATH}:/workspace/stable-diffusion-webui/venv/bin"
WORKDIR /
RUN rm /workspace/v1-5-pruned-emaonly.ckpt
RUN wget -O model.safetensors https://civitai.com/api/download/models/5616
RUN pip install -U xformers
RUN pip install runpod
ADD handler.py .
ADD start.sh /start.sh
RUN chmod +x /start.sh
CMD [ "/start.sh" ]

39
runpod/runpod-worker-hassanblend/handler.py

@ -0,0 +1,39 @@
import runpod
import subprocess
import requests
import time
def check_api_availability(host):
while True:
try:
response = requests.get(host)
return
except requests.exceptions.RequestException as e:
print(f"API is not available, retrying in 200ms... ({e})")
except Exception as e:
print('something went wrong')
time.sleep(200/1000)
check_api_availability("http://127.0.0.1:3000/sdapi/v1/txt2img")
print('run handler')
def handler(event):
'''
This is the handler function that will be called by the serverless.
'''
print('got event')
print(event)
response = requests.post(url=f'http://127.0.0.1:3000/sdapi/v1/txt2img', json=event["input"])
json = response.json()
# do the things
print(json)
# return the output that you want to be returned like pre-signed URLs to output artifacts
return json
runpod.serverless.start({"handler": handler})

11
runpod/runpod-worker-hassanblend/start.sh

@ -0,0 +1,11 @@
#!/bin/bash
echo "Container Started"
export PYTHONUNBUFFERED=1
source /workspace/stable-diffusion-webui/venv/bin/activate
cd /workspace/stable-diffusion-webui
echo "starting api"
python webui.py --port 3000 --nowebui --api --xformers --ckpt /model.safetensors &
cd /
echo "starting worker"
python -u handler.py

6
setup.py

@ -0,0 +1,6 @@
from setuptools import find_packages, setup
setup(
name='matrix-pygmalion-bot',
packages=find_packages(),
)
Loading…
Cancel
Save