Initial commit

This commit is contained in:
thecookingsenpai 2023-12-25 13:26:31 +01:00
commit d1f16eb40d
9 changed files with 307 additions and 0 deletions

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
### AL ###
#Template for AL projects for Dynamics 365 Business Central
#launch.json folder
.vscode/
#Cache folder
.alcache/
#Symbols folder
.alpackages/
#Snapshots folder
.snapshots/
#Testing Output folder
.output/
#Extension App-file
*.app
#Rapid Application Development File
rad.json
#Translation Base-file
*.g.xlf
#License-file
*.flf
#Test results file
TestResults.xml

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Blockdrops LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

91
README.md Normal file
View File

@ -0,0 +1,91 @@
# Delaimain
Delaimain is an AI-Powered personal assistant that runs on your CPU (no GPU needed!) and locally (no OpenAI API keys needed!). It is designed to be flexible and extensible, allowing it to be customized for specific needs. One of the main features of Delaimain is the modular architecture: you can create modules for Delamain to run using basically any language installed on your computer.
This repository contains the source code for Delaimain. It includes the core components of the assistant, as well as example plugins and language support.
## Requirements and Models
This software with the default model has been tested against a 14GB RAM (heh, it's a laptop) Ryzen 7730U (yeah, it's a laptop) machine running Kubuntu 23.10 .
Theoretically, if you can run gpt4all client on your computer you can also run Delaimain as it uses gpt4all python bindings.
You are free to change the model in config.json using any model supported by gpt4all. As an additional tip, many external models like the ones available on huggingface work like a charm.
## Getting Started
To get started using Delaimain, follow these steps:
1. Clone this repository to your local machine.
2. Install the required dependencies by running `pip install -r requirements.txt` in the root directory of the repository.
3. Start the assistant by running `python delaMain.py` in the root directory of the repository.
4. Chat with the assistant or use one of the configured commands
## Language Support
Delaimain supports a wide range of programming languages.
Besides the growing officially supported languages, Delamain will fallback to a standalone binary if it detects an unsupported language.
For example, if a language named "xyz" is installed and is runnable through "xyz script.x", Delaimain is able to execute it anyway.
Other languages (like nodeJS which is officially supported) requires a proper configuration as their binary does not correspond to their names.
## Scripting
By following the examples in modules.json and the linked modules in scripts/, it is easy to create a new module for your Delaimain.
Let's say you want to execute a script that shutdown your Linux machine:
sudo shutdown now
While being quite simple, this script is useful to show how Delaimain can be configured.
Let's save this script as shutdown.sh in scripts/ and let's open modules.json.
We now want to add our script in response to a command. Let's add:
{
"goBed": {
"script": "shutdown.sh",
"type": "sh",
"description": "Shutting down your computer"
}
}
After reloading Delaimain, you will be able to write 'goBed' to see your script executed.
Of course you are encouraged to hack and change everything in Delaimain so to have your perfect assistant.
## Optional features
The following features are disabled by default and can be enabled by setting the related flag in config.json .
Please note that experimental features can lead to unexpected behaviour. Report bugs and feedback please.
### Face
By setting the parameter 'face' to 'true', Delaimain will spawn a little window representing a (work in progess) visual GIF animation of Delaimain itself. By replacing the corresponding GIF in your code you can give Delaimain any aspect you want.
### TTS
The TTS module is currently not working and is a work in progress.
## Future features
The following features are ordered by priority but they can change anytime.
Contributions to this features are welcome and prioritized: please open an issue to notify the others of your contribution.
Feedback is greatly appreciated.
- [ ] Working TTS engine (feel free to change the library used)
- [ ] Smoother face.py engine and management (now is an horrible subprocess)
- [ ] CLI Interface (using https://www.textualize.io)
- [ ] Microphone support (privacy oriented of course)
- [ ] Consequently, hotword support using or on the model of https://thalhammer.github.io/snowman/ or any other alternative that works
- [ ] face.py animations
- [ ] Better overall user experience
## Contributing
We welcome contributions from the community to help make Delaimain even better. If you would like to contribute, please follow these steps:
1. Fork this repository.
2. Create a new branch for your changes.
3. Make your changes and ensure they pass all tests.
4. Submit a pull request to merge your changes into the main repository.
## License
Delaimain is licensed under the MIT License. See the [LICENSE](LICENSE) file for more information.

BIN
base_small.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

BIN
call_talking.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

6
config.json Normal file
View File

@ -0,0 +1,6 @@
{
"tts": false,
"face": false,
"model": "mistral-7b-openorca.Q4_0.gguf",
"supported_languages": ["python", "tsx", "tsc", "perl", "php", "ruby"]
}

141
delaMain.py Normal file
View File

@ -0,0 +1,141 @@
import json
import os
import subprocess
import pyttsx3
from gpt4all import GPT4All
engine = pyttsx3.init() # FIXME aplay error?
# ANCHOR Configuration and pre-flight globals
config = None
with open("config.json", "r") as conf:
config = json.load(conf)
print("Loaded configuration:")
for key, value in config.items():
print(key, value)
config["face_process"] = None
model = GPT4All(model_name=config["model"])
# ANCHOR Modules loading
with open("modules.json", "r") as f:
modules = json.load(f)
print("Loaded configuration:")
for key, value in modules.items():
print(key, value)
# NOTE Chat handler: this is the main loop for the program to work
def chat_session():
global tts
print(".:: Delamain is starting ::.")
with model.chat_session():
# Endless chat session with ctrl-c interrupt
try:
# Being polite is important
output = model.generate(prompt="Hello!")
print("Delamain > " + output)
while True:
text = input("> ")
# Custom modules
is_done = view_modules(text)
if is_done:
continue
# SECTION Built in modules are defined here
# Also 'exit' can be used to exit the chat session
if text == "exit":
print("Exiting...")
do_exit()
elif text.startswith("complete the following: "):
to_complete = text.split("complete the following: ")[1]
print("Completing message: " + to_complete)
output = complete(to_complete)
else:
# Here delamain generates its own message if nothing has been requested above
output = model.generate(text, max_tokens=1024)
# Is reply time!
print("Delamain >" + output)
if config["tts"]:
engine.say(output)
engine.runAndWait()
except KeyboardInterrupt:
print("Exiting...")
do_exit()
# INFO Simple completion module
def complete(text):
output = model.generate(text, max_tokens=20)
return output
# INFO Priority to custom modules
def view_modules(text):
# SECTION Modules are defined here
global modules
is_done = False
for key, value in modules.items():
if text.startswith(key):
is_done = True
arguments = text.split(key)[1]
if arguments == "":
print("Warning: no arguments given for module: " + key)
script = value["script"]
typeOf = value["type"]
description = value["description"]
print("Executing script: " + description)
dispatcher(script, typeOf, arguments)
return is_done
# INFO Heavy work is done here
def dispatcher(script, typeOf, arguments):
global config
cmd = ""
# NOTE We avoid defining types that have the same syntax as the invocation module
if typeOf == "javascript":
cmd = "node "
else:
supported_languages = config["supported_languages"]
if typeOf not in supported_languages:
print("Language not officially supported: " + typeOf)
print("Trying to append it like a standalone binary: " + typeOf)
cmd = typeOf + " "
# Finding the script
path = os.path.dirname(os.path.realpath(__file__)) + "/scripts/" + script
if not os.path.isfile(path):
print("Script not found: " + script)
return
# Executing the script
print("Executing script: " + cmd + path + " " + arguments)
proc = subprocess.run(
cmd + path + " " + arguments,
# TODO Try to remove this shell=True to improve security
# trunk-ignore(bandit/B602)
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
)
out = proc.stdout.decode("utf-8")
print(out)
if config["tts"]:
engine.say(out)
engine.runAndWait()
# Terminating gracefully
def do_exit():
global config
if config["face_process"]:
config["face_process"].terminate()
exit()
if __name__ == "__main__":
# Starting face in background
if config["face"]:
config["face_process"] = subprocess.Popen(["python3", "face.py"])
# Chatting session
chat_session()

25
face.py Normal file
View File

@ -0,0 +1,25 @@
import pyglet
# Replace 'your_gif_file.gif' with the path to your GIF file
gif_path = 'base_small.gif'
# Create a window
window = pyglet.window.Window()
window.set_exclusive_mouse(True)
# Load the GIF
animation = pyglet.image.load_animation(gif_path)
sprite = pyglet.sprite.Sprite(animation)
# Set the window size to match the GIF
window.width = 180
window.height = 180
@window.event
def on_draw():
window.clear()
window.set_caption = "Delamain"
sprite.draw()
# Start the application
pyglet.app.run()

1
scripts/nodeVersion.js Normal file
View File

@ -0,0 +1 @@
console.log(process.version)