From e1a484de90bb0a006f874bb7f6ac46e67ab342d1 Mon Sep 17 00:00:00 2001
From: Kuldeep <71772185+neokd@users.noreply.github.com>
Date: Thu, 30 Nov 2023 19:39:36 +0530
Subject: [PATCH] pre-release beta
---
README.md | 8 +-
docs/content/about/changelog.md | 29 ++++++
docs/content/advance/configuration.md | 20 +++-
docs/content/agents/index.md | 60 +++++++++++
docs/content/index.md | 10 +-
docs/content/persona/persona.md | 11 ++
docs/content/persona/shell.md | 44 ++++++++
docs/mkdocs.yml | 3 +
main.py | 31 +++++-
neogpt/agents/__init__.py | 7 ++
neogpt/agents/examples/calculate.py | 43 ++++++++
neogpt/agents/examples/file_uploader.py | 45 ++++++++
neogpt/agents/examples/password_generator.py | 27 +++++
neogpt/agents/examples/sentiment.py | 39 +++++++
neogpt/agents/examples/snake.py | 97 ++++++++++++++++++
.../examples/streamlit_visualization.py | 49 +++++++++
neogpt/agents/examples/translator_app.py | 23 +++++
neogpt/agents/ml_engineer.py | 47 +++++++++
neogpt/agents/qa_engineer.py | 95 +++++++++++++++++
neogpt/callback_handler.py | 76 +++++++++++++-
neogpt/config.py | 7 ++
.../data_level0.bin | Bin 1676000 -> 1676000 bytes
neogpt/load_llm.py | 11 +-
neogpt/manager.py | 83 +++++++++++++--
neogpt/prompts/prompt.py | 35 ++++++-
neogpt/ui.py | 3 +-
neogpt/workspace/chatterbot.py | 29 ++++++
neogpt/workspace/main.py | 43 ++++++++
28 files changed, 939 insertions(+), 36 deletions(-)
create mode 100644 docs/content/agents/index.md
create mode 100644 docs/content/persona/shell.md
create mode 100644 neogpt/agents/__init__.py
create mode 100644 neogpt/agents/examples/calculate.py
create mode 100644 neogpt/agents/examples/file_uploader.py
create mode 100644 neogpt/agents/examples/password_generator.py
create mode 100644 neogpt/agents/examples/sentiment.py
create mode 100644 neogpt/agents/examples/snake.py
create mode 100644 neogpt/agents/examples/streamlit_visualization.py
create mode 100644 neogpt/agents/examples/translator_app.py
create mode 100644 neogpt/agents/ml_engineer.py
create mode 100644 neogpt/agents/qa_engineer.py
create mode 100644 neogpt/workspace/chatterbot.py
create mode 100644 neogpt/workspace/main.py
diff --git a/README.md b/README.md
index da1ad54..d7e8659 100644
--- a/README.md
+++ b/README.md
@@ -103,11 +103,11 @@ Join our [Discord](https://discord.gg/qNqjsGuCTG) community to stay up to date w
- β User Interface π» (Streamlit)
- β Chat with SQL DB π€
- β Support for other search engines (DuckDuckGo) π
-- β Add support for other LLM types (Ollama) π§
+- β Add support for other LLM types (Ollama) π§
- β Add other database support (MongoDB, ElasticSearch, etc.) ππ
-- β Docker Support π³
-- β Better Documentation π
-- β Agent based chatbot π€
+- β Docker Support π³
+- β Better Documentation π
+- β Agent based chatbot π€
## Features
diff --git a/docs/content/about/changelog.md b/docs/content/about/changelog.md
index 96388e7..52e4e47 100644
--- a/docs/content/about/changelog.md
+++ b/docs/content/about/changelog.md
@@ -4,6 +4,33 @@
This page lists the highlights, bug fixes and known issues for each release of NeoGPT.
+## v0.1.0-beta π΅οΈββοΈπ
+
+__Release Date:__ 30th November 2023
+
+Features:
+
+- __Agent based chatbot π€__ : 2 New agents are added (ML Engineer, QA Engineer).
+
+- __Writing Assistant π__ : NeoGPT can now help you write your documents and assignments with `--write` flag.
+
+- __Shell Mode π__ : NeoGPT can now be used as a shell by passing the `--persona shell` flag.
+
+- __Docker Support π³__ : NeoGPT can now be run in a docker container.
+
+- __Ollama Support π§ __ : NeoGPT can now be used with Ollama.
+
+- __Timer for User Input in UI β±__ : Timed user input for ui mode by @savyez in [#105](https://github.com/neokd/NeoGPT/pull/105)
+
+
+Bug Fixes:
+- Fixed Dockerfile
+
+### New Contributors
+* @Tashuuuu [#98](https://github.com/neokd/NeoGPT/pull/98)
+* @C0DE-SLAYER [#99](https://github.com/neokd/NeoGPT/pull/99)
+
+
## v0.1.0-alpha ππ€β¨
@@ -77,5 +104,7 @@ Project Roadmap Achievements:
* @ha36d
* @bryce-seefieldt
* @kehsihba19
+* @Tashuuuu
+* @C0DE-SLAYER
We would like to thank all the contributors for their valuable contributions to NeoGPT. :heart_on_fire:
diff --git a/docs/content/advance/configuration.md b/docs/content/advance/configuration.md
index 810e431..2b2e2ac 100644
--- a/docs/content/advance/configuration.md
+++ b/docs/content/advance/configuration.md
@@ -106,6 +106,22 @@ Supported URL patterns for ingestion.
- **Log File:** The log file name.
Default: `logs/builder.log`
+## Agent
-!!! info "Release Note"
- You cannot change config directly from the CLI or UI. We will add support for that in the future releases.
+- **Agent Name:** The name of the agent.
+ Default: `NeoGPT`
+
+- **Agent Thoughts:** List of agent thoughts.
+ Default: `[]` (empty list)
+
+- **QA feedback:** List of QA feedback.
+ Default: `[]` (empty list)
+
+
+
+!!! info "Update Note"
+ You can update the configurations by using `export` command. For example, to update the `MODEL_NAME` configuration, you can use the following command:
+
+ ```bash
+ export MODEL_NAME="TheBloke/Mistral-7B-Instruct-v0.1-GGUF"
+ ```
diff --git a/docs/content/agents/index.md b/docs/content/agents/index.md
new file mode 100644
index 0000000..6490a7c
--- /dev/null
+++ b/docs/content/agents/index.md
@@ -0,0 +1,60 @@
+# __Agents & NeoGPT π΅οΈπ€__
+
+## What is an Agent?
+
+In artificial intelligence, an agent is a computer program or system that is designed to perceive its environment, make decisions and take actions to achieve a specific goal or set of goals. The agent operates autonomously, meaning it is not directly controlled by a human operator.
+
+!!! info "Info"
+ Agents are in very early stages of development. They may produce unexpected results or errors. Please use them with caution.
+
+## Agents & NeoGPT
+
+Agents are a new feature in NeoGPT. They are designed to be able to interact with the world around them. Currently there are only two agents, but more are planned to be added in the future.
+
+## Agents in Focus
+
+Agents within the NeoGPT ecosystem are designed to collaborate with the language model, enabling a broader range of interactions and problem-solving capabilities. Stay tuned for further updates and the introduction of additional agents, expanding the collaborative intelligence of NeoGPT.
+
+## Meet the Agents
+
+### __ML Engineer π€π§ __
+
+The ML Engineer is a specialized agent for machine learning tasks, thinking like an experienced ML professional. It understands and solves various ML-related queries, making it a valuable asset for those needing support in Python programming, data science, and machine learning basics.
+
+### __QA Engineer π΅οΈπ__
+
+The QA Engineer, or Quality Assurance Engineer, is an agent with expertise in validating and assessing code and solutions. When presented with a problem, the QA Engineer can analyze the solution and provide feedback, helping to ensure the quality and correctness of the code.
+
+
+## How to use Agents
+
+Run the below command to see the agents in action.
+
+=== "Command"
+ ```bash title="Terminal"
+ python main.py --task "Your task goes here"
+ ```
+
+=== "Example"
+ ```bash title="Terminal"
+ python main.py --task "Write a program to find the sum of all numbers stored in a list"
+ ```
+
+
+## How do Agents work?
+
+1. The `hire()` method is like an assistant manager overseeing the collaboration between a machine learning (ML) specialist (ML Engineer) and a quality assurance (QA) expert (QA Engineer) to solve a task.
+
+2. __Load Model__: The `hire()` function initiates by loading the machine learning model designed for the task.
+
+3. __Collaboration Setup__: It establishes collaboration between two key roles - the ML Engineer and the QA Engineer.
+
+4. __Task Assignment__: A task is assigned to the ML Engineer, who employs the loaded model to generate a solution.
+
+5. __Quality Check__: The QA Engineer assesses the proposed solution for correctness and quality.
+
+6. __Termination or Retry__: If the solution is approved, the program terminates. In case of disapproval, the process retries for a defined number of attempts.
+
+7. __Collaborative Iteration__: Steps 3 to 5 are iteratively performed, facilitating collaboration until a satisfactory solution is achieved or attempts are exhausted.
+
+
diff --git a/docs/content/index.md b/docs/content/index.md
index 1e23b7e..2278923 100644
--- a/docs/content/index.md
+++ b/docs/content/index.md
@@ -52,15 +52,15 @@ Join our [Discord](https://discord.gg/qNqjsGuCTG) community to stay up to date w
- [x] Support for other search engines (DuckDuckGo) π
-- [ ] Add support for other LLM types (Ollama) π§
+- [x] Add support for other LLM types (Ollama) π§
-- [ ] Add other database support (MongoDB, ElasticSearch, etc.) ππ
+- [x] Docker Support π³
-- [ ] Docker Support π³
+- [x] Better Documentation π
-- [ ] Better Documentation π
+- [x] Agent based chatbot π€
-- [ ] Agent based chatbot π€
+- [ ] Add other database support (MongoDB, ElasticSearch, etc.) ππ
!!! info "Release Note"
diff --git a/docs/content/persona/persona.md b/docs/content/persona/persona.md
index ca6ba51..fa8e448 100644
--- a/docs/content/persona/persona.md
+++ b/docs/content/persona/persona.md
@@ -18,6 +18,7 @@ The following personas are currently available:
- `ML_ENGINEER`: Explains complex ML concepts in an easy-to-understand manner.
- `CEO`: Acts as the CEO, making strategic decisions.
- `RESEARCHER`: Analyzes, synthesizes, and provides insights.
+- `SHELL`: Executes shell commands.
### Default Persona
@@ -84,6 +85,16 @@ For data exploration and analysis, NeoGPT becomes a researcher. Dive into the wo
python main.py --persona researcher
```
+### Shell Persona
+
+NeoGPT's shell persona is a powerful tool for executing shell commands. It can be used to perform a variety of tasks, such as installing software, managing files, and more. However, it is important to note that this persona can be dangerous if used incorrectly. Always review the generated commands before executing them.
+
+```bash title="Terminal"
+python main.py --persona shell
+```
+
+Refer to the [Executing Shell Commands with NeoGPT π€](/NeoGPT/persona/shell) section for more information.
+
### Conclusion
diff --git a/docs/content/persona/shell.md b/docs/content/persona/shell.md
new file mode 100644
index 0000000..1704e13
--- /dev/null
+++ b/docs/content/persona/shell.md
@@ -0,0 +1,44 @@
+# __Executing Shell Commands with NeoGPT π€__
+
+
+
+## Introduction
+
+NeoGPT π€ has a special persona known as "shell," which allows it to generate shell commands based on user input. It's important to note that these commands have the potential to make changes to your system, and you should use them at your own risk.
+
+## Warning
+
+When using NeoGPT π€ in the "shell" persona, be cautious, as it may generate commands that can be harmful to your system. Always review the generated commands before executing them. The following steps guide you through the process of executing or manually reviewing commands.
+
+## Steps
+
+!!! warning "Warning"
+ When using NeoGPT π€ in the "shell" persona, be cautious, as it may generate commands that can be harmful to your system. Always review the generated commands before executing them. The following steps guide you through the process of executing or manually reviewing commands.
+
+
+### Step 1: Persona Selection
+
+If you choose the "shell" persona, NeoGPT π€ will inform you about the potential risks and ask whether you want to execute the generated commands.
+
+```bash
+You are using NeoGPT π€ as a shell. It may generate commands that can be harmful to your system. Use it at your own risk. β οΈ
+```
+
+### Step 2: User Input
+You will be prompted to decide whether you want to execute the generated commands.
+
+```bash
+Do you want to execute the commands? (Y/N):
+```
+
+### Step 3: Execution Confirmation
+If you choose to execute the commands, NeoGPT π€ will inform you that it will execute the commands in your default shell.
+
+```bash
+NeoGPT π€ will execute the commands in your default shell.
+```
+
+### Conclusion
+Using NeoGPT π€ in the "shell" persona can be a powerful tool, but it comes with risks. Always exercise caution, review the generated commands, and ensure they align with your intentions.
+
+
diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml
index f8c5030..5f5986f 100644
--- a/docs/mkdocs.yml
+++ b/docs/mkdocs.yml
@@ -79,6 +79,9 @@ nav:
- SQL : retrievers/sql.md
- Persona:
- Persona & NeoGPT: persona/persona.md
+ - Shell Persona: persona/shell.md
+ - Agents:
+ - Agents & NeoGPT: agents/index.md
- Settings:
- Configure Search: advance/search.md
- Configuration: advance/configuration.md
diff --git a/main.py b/main.py
index fdd601e..bea654a 100644
--- a/main.py
+++ b/main.py
@@ -6,7 +6,7 @@
from neogpt.builder import builder
from neogpt.config import DEVICE_TYPE, NEOGPT_LOG_FILE
-from neogpt.manager import db_retriver
+from neogpt.manager import db_retriver, hire
def main():
@@ -39,7 +39,7 @@ def main():
"ml_engineer",
"ceo",
"researcher",
- "shell"
+ "shell",
],
default="default",
help="Specify the persona (default, recruiter). It allows you to customize the persona i.e. how the chatbot should behave.",
@@ -92,13 +92,22 @@ def main():
action="version",
version="You are using NeoGPTπ€ v0.1.0-alpha.",
)
+ parser.add_argument("--task", type=str, help="Task to be performed by the Agent")
+ parser.add_argument(
+ "--tries",
+ type=int,
+ default=5,
+ help="Number of retries if the Agent fails to perform the task",
+ )
+
args = parser.parse_args()
if args.debug:
log_level = logging.DEBUG
-
- if args.verbose:
+ elif args.verbose:
log_level = logging.INFO
+ else:
+ log_level = logging.WARNING
if args.log:
log_level = logging.INFO
@@ -107,6 +116,11 @@ def main():
level=log_level,
filename=NEOGPT_LOG_FILE,
)
+ else:
+ logging.basicConfig(
+ format="%(asctime)s - %(levelname)s - %(filename)s:%(lineno)s - %(message)s",
+ level=log_level,
+ )
# if not os.path.exists(FAISS_PERSIST_DIRECTORY):
# builder(vectorstore="FAISS")
@@ -127,6 +141,15 @@ def main():
logging.info("Note: The UI server only supports local retriever and Chroma DB")
sys.argv = ["streamlit", "run", "neogpt/ui.py"]
sys.exit(stcli.main())
+
+ elif args.task is not None:
+ print()
+ hire(
+ task=args.task,
+ tries=args.tries,
+ LOGGING=logging,
+ )
+
else:
db_retriver(
device_type=args.device_type,
diff --git a/neogpt/agents/__init__.py b/neogpt/agents/__init__.py
new file mode 100644
index 0000000..a7bc951
--- /dev/null
+++ b/neogpt/agents/__init__.py
@@ -0,0 +1,7 @@
+from neogpt.agents.ml_engineer import ML_Engineer
+from neogpt.agents.qa_engineer import QA_Engineer
+
+__all__ = [
+ "ML_Engineer",
+ "QA_Engineer",
+]
diff --git a/neogpt/agents/examples/calculate.py b/neogpt/agents/examples/calculate.py
new file mode 100644
index 0000000..e716d45
--- /dev/null
+++ b/neogpt/agents/examples/calculate.py
@@ -0,0 +1,43 @@
+import math
+
+from flask import Flask, request
+
+app = Flask(__name__)
+
+
+@app.route("/calculate", methods=["GET", "POST"])
+def calculate():
+ if request.method == "GET":
+ return """
+
Calculator
+
+ """
+ else:
+ operation = request.form["operation"]
+ num1 = float(request.form["num1"])
+ num2 = float(request.form["num2"])
+
+ if operation == "add":
+ result = num1 + num2
+ elif operation == "subtract":
+ result = num1 - num2
+ elif operation == "multiply":
+ result = num1 * num2
+ elif operation == "divide":
+ result = num1 / num2
+ else:
+ result = "Invalid operation"
+
+ return f"""Result: {result}
"""
+
+
+if __name__ == "__main__":
+ app.run()
diff --git a/neogpt/agents/examples/file_uploader.py b/neogpt/agents/examples/file_uploader.py
new file mode 100644
index 0000000..f4e3608
--- /dev/null
+++ b/neogpt/agents/examples/file_uploader.py
@@ -0,0 +1,45 @@
+from io import BytesIO
+
+import pandas as pd
+import streamlit as st
+from pdfminer.high_level import extract_text
+
+# Initialize the app
+st.title("File Uploader")
+
+# Create a file uploader
+with st.form("Upload File"):
+ file_upload = st.file_uploader("Select a file to upload:")
+
+ # Check if a file is uploaded
+ if file_upload is not None:
+ # Display the file information
+ st.subheader("File Information")
+ filename = file_upload.name
+ size = file_upload.size
+ st.write(f"Filename: {filename}")
+ st.write(f"Size: {size} bytes")
+
+ # Read the file content as bytes
+ content = file_upload.read()
+
+ # Check file extension
+ file_extension = filename.split(".")[-1].lower()
+
+ # Display the file content based on file extension
+ st.subheader("File Content")
+
+ if file_extension == "pdf":
+ # Extract text from PDF using pdfminer.six
+ pdf_text = extract_text(BytesIO(content))
+ st.text_area("Content:", pdf_text, height=300)
+ elif file_extension in ["xls", "xlsx"]:
+ # Read Excel file using pandas
+ excel_df = pd.read_excel(BytesIO(content))
+ st.write("Preview of Excel Data:")
+ st.write(excel_df)
+ else:
+ # For other file types, display raw content
+ st.text_area("Content:", content.decode("utf-8"), height=300)
+
+ st.form_submit_button("Upload")
diff --git a/neogpt/agents/examples/password_generator.py b/neogpt/agents/examples/password_generator.py
new file mode 100644
index 0000000..4af0b4d
--- /dev/null
+++ b/neogpt/agents/examples/password_generator.py
@@ -0,0 +1,27 @@
+import streamlit as st
+import secrets
+
+def generate_password(length):
+ password = (secrets.token_hex(length) +
+ secrets.token_hex(length) +
+ secrets.token_hex(length)).replace('\n', '').strip()
+ return password
+
+if __name__ == "__main__":
+ st.title("Strong Password Generator")
+ st.write("Enter the desired password length:")
+
+ # Get the user input for password length
+ length_input = st.text_input(label="Enter length")
+
+ if length_input:
+ # Check if the input is not empty
+ length = int(length_input)
+
+ if length < 8:
+ st.write("Password length should be at least 8 characters.")
+ else:
+ password = generate_password(length)
+ st.write(f"Generated Password: {password}")
+ else:
+ st.write("Please enter a valid password length.")
diff --git a/neogpt/agents/examples/sentiment.py b/neogpt/agents/examples/sentiment.py
new file mode 100644
index 0000000..3f422fd
--- /dev/null
+++ b/neogpt/agents/examples/sentiment.py
@@ -0,0 +1,39 @@
+# Import required libraries
+import streamlit as st
+from textblob import TextBlob
+from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer
+
+# Define the app layout with input boxes and dropdowns for model selection
+st.set_page_config(page_title="Sentiment Analysis", layout="wide")
+st.title("Sentiment Analysis")
+st.subheader("Enter text to analyze sentiment")
+
+text_input = st.text_area("Text Input", value="", max_chars=200)
+model_select = st.selectbox("Select a model:", ["TextBlob", "VADER"], index=0)
+submit_button = st.button("Submit")
+
+
+# Define the function to implement the sentiment analysis task using the selected model
+def analyze_sentiment(text, model):
+ if model == "TextBlob":
+ blob = TextBlob(text)
+ return blob.sentiment.polarity
+ elif model == "VADER":
+ analyzer = SentimentIntensityAnalyzer()
+ return analyzer.polarity_scores(text)["compound"]
+
+
+# Implement the sentiment analysis task using the selected model when the submit button is clicked
+if submit_button:
+ if text_input:
+ sentiment = analyze_sentiment(text_input, model_select)
+ st.subheader("Sentiment Analysis Result")
+ if sentiment >= 0.5:
+ result = "Positive"
+ elif sentiment <= -0.5:
+ result = "Negative"
+ else:
+ result = "Neutral"
+ st.write(result)
+ else:
+ st.write("Please enter text to analyze sentiment")
diff --git a/neogpt/agents/examples/snake.py b/neogpt/agents/examples/snake.py
new file mode 100644
index 0000000..d61c15b
--- /dev/null
+++ b/neogpt/agents/examples/snake.py
@@ -0,0 +1,97 @@
+import random
+import time
+
+import pygame
+
+pygame.init()
+
+window_width = 800
+window_height = 600
+
+screen = pygame.display.set_mode((window_width, window_height))
+pygame.display.set_caption("Snake Game")
+
+snake_width = 10
+snake_height = 10
+head_position = [300, 250]
+move_direction = "right"
+snake_length = 1
+snake_segments = [head_position.copy()]
+
+apple_position = [
+ random.randrange(1, (window_width // 10)) * 10,
+ random.randrange(1, (window_height // 10)) * 10,
+]
+
+clock = pygame.time.Clock()
+
+
+def draw_snake(snake_segments):
+ for segment in snake_segments:
+ pygame.draw.rect(
+ screen,
+ (0, 0, 255),
+ pygame.Rect(segment[0], segment[1], snake_width, snake_height),
+ )
+
+
+def draw_apple(apple_position):
+ pygame.draw.rect(
+ screen,
+ (255, 0, 0),
+ pygame.Rect(apple_position[0], apple_position[1], snake_width, snake_height),
+ )
+
+
+while True:
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ pygame.quit()
+ quit()
+ elif event.type == pygame.KEYDOWN:
+ if event.key == pygame.K_LEFT:
+ move_direction = "left"
+ elif event.key == pygame.K_RIGHT:
+ move_direction = "right"
+ elif event.key == pygame.K_UP:
+ move_direction = "up"
+ elif event.key == pygame.K_DOWN:
+ move_direction = "down"
+
+ if move_direction == "right":
+ head_position[0] += 10
+ elif move_direction == "left":
+ head_position[0] -= 10
+ elif move_direction == "up":
+ head_position[1] -= 10
+ elif move_direction == "down":
+ head_position[1] += 10
+
+ # Check if the snake hits the wall
+ if (
+ head_position[0] < 0
+ or head_position[0] >= window_width
+ or head_position[1] < 0
+ or head_position[1] >= window_height
+ ):
+ pygame.quit()
+ quit()
+
+ snake_segments.insert(0, list(head_position))
+
+ if head_position == apple_position:
+ apple_position = [
+ random.randrange(1, (window_width // 10)) * 10,
+ random.randrange(1, (window_height // 10)) * 10,
+ ]
+ snake_length += 1
+ else:
+ snake_segments.pop()
+
+ screen.fill((0, 0, 0))
+ draw_apple(apple_position)
+ draw_snake(snake_segments)
+
+ pygame.display.update()
+
+ clock.tick(15) # Adjust the speed of the snake
diff --git a/neogpt/agents/examples/streamlit_visualization.py b/neogpt/agents/examples/streamlit_visualization.py
new file mode 100644
index 0000000..f14e089
--- /dev/null
+++ b/neogpt/agents/examples/streamlit_visualization.py
@@ -0,0 +1,49 @@
+# filename: streamlit_visualization.py
+
+import matplotlib.pyplot as plt
+import numpy as np
+import streamlit as st
+from sklearn.datasets import load_iris
+from sklearn.linear_model import LogisticRegression
+from sklearn.metrics import accuracy_score, classification_report
+
+# Load the iris dataset
+iris = load_iris()
+X = iris["data"]
+y = iris["target"]
+
+# Create a logistic regression model and fit it to the data
+model = LogisticRegression(max_iter=1000)
+model.fit(X, y)
+st.set_option("deprecation.showPyplotGlobalUse", False)
+st.title("Iris Dataset Visualization")
+# Make predictions on the test set
+y_pred = model.predict(X)
+
+
+# Calculate the accuracy of the model
+accuracy = accuracy_score(y, y_pred)
+print("Accuracy:", accuracy)
+
+# Get the classification report
+classification_report_text = classification_report(y, y_pred)
+print("\nClassification Report:\n", classification_report_text)
+
+st.write("Classification Report:\n", classification_report_text)
+
+# Create a scatter plot of the features and target variable
+plt.scatter(X[:, 0], X[:, 1], c=y)
+plt.xlabel("Sepal Length (cm)")
+plt.ylabel("Sepal Width (cm)")
+plt.title("Iris Dataset Visualization")
+# plt.show()
+st.subheader("Scatter Plot")
+st.pyplot()
+
+# Create a histogram of the target variable
+plt.hist(y, bins=[0, 1, 2], align="left", rwidth=0.8)
+plt.xlabel("Target Variable")
+plt.title("Iris Dataset Visualization")
+plt.show()
+st.subheader("Histogram")
+st.pyplot()
diff --git a/neogpt/agents/examples/translator_app.py b/neogpt/agents/examples/translator_app.py
new file mode 100644
index 0000000..24a519d
--- /dev/null
+++ b/neogpt/agents/examples/translator_app.py
@@ -0,0 +1,23 @@
+# filename: translator_app.py
+import streamlit as st
+from googletrans import LANGUAGES, Translator
+
+
+def translate_text(text, target_language):
+ translator = Translator()
+ translation = translator.translate(text, dest=target_language)
+ return translation.text
+
+
+if __name__ == "__main__":
+ st.title("Basic Translator App")
+ st.subheader("Enter text to translate:")
+
+ text = st.text_area(label="Text", value="", height=200, max_chars=200)
+
+ target_language = st.selectbox("Select target language:", list(LANGUAGES.values()))
+
+ if st.button("Translate"):
+ translated_text = translate_text(text, target_language)
+ st.write("Translated Text:")
+ st.write(translated_text)
diff --git a/neogpt/agents/ml_engineer.py b/neogpt/agents/ml_engineer.py
new file mode 100644
index 0000000..f6f50ab
--- /dev/null
+++ b/neogpt/agents/ml_engineer.py
@@ -0,0 +1,47 @@
+from colorama import Fore, Style
+from langchain.chains import LLMChain
+from langchain.prompts import PromptTemplate
+
+from neogpt.config import AGENT_THOUGHTS, CURRENT_WORKING_AGENT, QA_ENGINEER_FEEDBACK
+from neogpt.prompts.prompt import ML_ENGINEER_PROMPT
+
+
+class ML_Engineer:
+ def __init__(self, llm) -> None:
+ self.ai_prefix = "AI: "
+ self.user_prefix = "Human: "
+ self.ml_engineer_prompt = ML_ENGINEER_PROMPT
+ self.llm = llm
+ self.role = "ML Engineer π€π§ "
+
+ def think(self, query):
+ global CURRENT_WORKING_AGENT, AGENT_THOUGHTS, QA_ENGINEER_FEEDBACK
+ CURRENT_WORKING_AGENT.append(str(self.role))
+ print(QA_ENGINEER_FEEDBACK)
+ template = (
+ "[INST]"
+ + self.user_prefix
+ + self.ml_engineer_prompt
+ + self.ai_prefix
+ + "[/INST]"
+ )
+ prompt = PromptTemplate(
+ template=template, input_variables=["question", "thoughts", "feedback"]
+ )
+
+ llm_chain = LLMChain(
+ llm=self.llm,
+ prompt=prompt,
+ )
+
+ res = llm_chain.invoke(
+ {
+ "question": query,
+ "thoughts": AGENT_THOUGHTS,
+ "feedback": QA_ENGINEER_FEEDBACK,
+ }
+ )
+
+ AGENT_THOUGHTS.append(res["text"])
+
+ return res["text"]
diff --git a/neogpt/agents/qa_engineer.py b/neogpt/agents/qa_engineer.py
new file mode 100644
index 0000000..34ff8ea
--- /dev/null
+++ b/neogpt/agents/qa_engineer.py
@@ -0,0 +1,95 @@
+import os
+import re
+import string
+from colorama import Fore, Style
+from langchain.chains import LLMChain
+from langchain.prompts import PromptTemplate
+
+from neogpt.config import (
+ AGENT_THOUGHTS,
+ CURRENT_WORKING_AGENT,
+ QA_ENGINEER_FEEDBACK,
+ WORKSPACE_DIRECTORY,
+)
+from neogpt.prompts.prompt import QA_ENGINEER_PROMPT
+
+
+class QA_Engineer:
+ def __init__(self, llm) -> None:
+ self.qa_engineer_prompt = QA_ENGINEER_PROMPT
+ self.ai_prefix = "AI: "
+ self.user_prefix = "Human: "
+ self.llm = llm
+ self.agent_thoughts = AGENT_THOUGHTS
+ self.role = "QA Engineer π€π"
+
+ def parse_code(self, code):
+ code = "\n".join(code)
+ code_pattern = re.compile(r"```python(.*?)```", re.DOTALL)
+ matches = re.findall(code_pattern, code)
+
+ file_pattern = re.search(
+ r"# filename: (.+\.py)|(\w+\.py)|# (\w+\.py)|# File: (\w+\.py)|# file_name: (.+\.py)|`(.+\.py)`",
+ code,
+ )
+ filename = (
+ file_pattern.group(1)
+ if (file_pattern and file_pattern.group(1))
+ else "main.py"
+ )
+
+ # Check if the file already exists in the workspace directory
+ base_filename, extension = os.path.splitext(filename)
+ suffix = 1
+ file_path = os.path.join(WORKSPACE_DIRECTORY, filename)
+
+ while os.path.exists(file_path):
+ # If the file exists, append a suffix and construct the new file path
+ filename = f"{base_filename}_{suffix}{extension}"
+ file_path = os.path.join(WORKSPACE_DIRECTORY, filename)
+ suffix += 1
+
+ if len(matches) > 0:
+ python_code = matches[0].strip()
+ with open(file_path, "w") as f:
+ f.write(python_code)
+ print(
+ "\n"
+ + Fore.LIGHTYELLOW_EX
+ + f"Your task is been writtern to {WORKSPACE_DIRECTORY}/{filename}"
+ + Fore.RESET
+ )
+
+ return code
+
+ def analyse(self, query):
+ global CURRENT_WORKING_AGENT, QA_ENGINEER_FEEDBACK
+ CURRENT_WORKING_AGENT.append(str(self.role))
+
+ validation_prompt = PromptTemplate(
+ template=self.qa_engineer_prompt,
+ input_variables=["question", "latest_thought"],
+ )
+
+ self.moderator = LLMChain(
+ llm=self.llm,
+ prompt=validation_prompt,
+ )
+ # print(self.agent_thoughts)
+ validate = self.moderator.invoke(
+ {
+ "question": query,
+ "latest_thought": self.agent_thoughts[-1],
+ }
+ )
+
+ if (
+ ("CORRECT" in validate["text"] or "TERMINATE" in validate["text"])
+ and ("CORRECT BUT NOT SOLVED" not in validate["text"].strip(string.punctuation) or "INCORRECT AND NOT SOLVED" not in validate["text"].strip(string.punctuation))
+):
+ self.parse_code(self.agent_thoughts)
+ return True
+ else:
+ # print("INCORRECT")
+ QA_ENGINEER_FEEDBACK.append(validate["text"])
+ return False
diff --git a/neogpt/callback_handler.py b/neogpt/callback_handler.py
index c6738cb..8db2502 100644
--- a/neogpt/callback_handler.py
+++ b/neogpt/callback_handler.py
@@ -9,7 +9,7 @@
from langchain.callbacks.base import BaseCallbackHandler
from langchain.schema.output import LLMResult
-from neogpt.config import QUERY_COST, TOTAL_COST
+from neogpt.config import CURRENT_WORKING_AGENT, PROJECT_COST, QUERY_COST, TOTAL_COST
class StreamingStdOutCallbackHandler(BaseCallbackHandler):
@@ -125,3 +125,77 @@ def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
# Remove info message
st.empty()
+
+
+class AgentCallbackHandler(BaseCallbackHandler):
+ def __init__(self):
+ super().__init__()
+ self._tokens = []
+ self.loading_thread = None
+ self.streaming = False
+ self.thinking_animation_thread = None
+ self.agent_printed = False
+ self.current_working_agent = CURRENT_WORKING_AGENT
+
+ def on_llm_start(
+ self, serialized: dict[str, Any], prompts: list[str], **kwargs: Any
+ ) -> None:
+ # Start a new line for a clean display
+ # sys.stdout.write("\n")
+
+ # Start a thread for the "NeoGPT π€ is thinking..." message
+ self.thinking_animation_thread = threading.Thread(
+ target=self.thinking_animation
+ )
+ self.thinking_animation_thread.start()
+
+ def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
+ self._tokens.append(token)
+ # Stop the thinking animation thread when a new token is generated
+ self.streaming = True
+
+ if self.thinking_animation_thread and self.thinking_animation_thread.is_alive():
+ self.thinking_animation_thread.join() # Wait for the thread to finish
+
+ if not self.agent_printed:
+ sys.stdout.write(Fore.BLUE + f"\n{self.current_working_agent[-1]}:")
+ self.agent_printed = True
+
+ # Display the generated token in a friendly way
+ sys.stdout.write(Fore.WHITE + token)
+ sys.stdout.flush()
+
+ def thinking_animation(self):
+ thinking_message = f"\n{self.current_working_agent[-1]} is thinking..."
+ loading_chars = "/-\\"
+ animation_idx = 0
+
+ sys.stdout.write(Fore.BLUE + thinking_message)
+
+ while not self.streaming:
+ sys.stdout.write(loading_chars[animation_idx])
+ sys.stdout.flush()
+ time.sleep(0.1)
+ sys.stdout.write("\b") # Move the cursor back to overwrite the animation
+ animation_idx = (animation_idx + 1) % len(loading_chars)
+
+ def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
+ """Run when LLM ends running."""
+ self.agent_printed = False
+ self.streaming = False
+ global TOTAL_COST, QUERY_COST # Use the global variables
+ # Cost are based on OpenAI's pricing model
+ QUERY_COST = round(
+ ((len(self._tokens) / 1000) * 0.002) * 83.33, 5
+ ) # INR Cost per token, rounded to 5 decimal places
+ TOTAL_COST += round(
+ QUERY_COST, 5
+ ) # Accumulate the cost, rounded to 5 decimal places
+ final_cost()
+ # print(Fore.WHITE + f"Total cost: {TOTAL_COST} INR")
+
+
+def final_cost():
+ global PROJECT_COST
+ PROJECT_COST += TOTAL_COST
+ return PROJECT_COST
diff --git a/neogpt/config.py b/neogpt/config.py
index 2523bc3..e5b5b5f 100644
--- a/neogpt/config.py
+++ b/neogpt/config.py
@@ -193,3 +193,10 @@
# with open("settings/settings.yaml", "w") as file:
# yaml.dump(config, file,sort_keys=False)
+
+
+# AGENT CONFIG
+PROJECT_COST = 0
+AGENT_THOUGHTS = []
+QA_ENGINEER_FEEDBACK = ""
+CURRENT_WORKING_AGENT = ["NeoGPT"]
diff --git a/neogpt/db/chroma/d7cde6d1-0002-4dab-a3d4-59f5fe57cde3/data_level0.bin b/neogpt/db/chroma/d7cde6d1-0002-4dab-a3d4-59f5fe57cde3/data_level0.bin
index f4e9bb1886d481ef84d89829eb15f024412225c1..6420a641f7a372f2c7c8244c058dc92b217066b7 100644
GIT binary patch
literal 1676000
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