diff --git a/.env b/.env new file mode 100644 index 0000000..a65378c --- /dev/null +++ b/.env @@ -0,0 +1,2 @@ +OPENAI_API_KEY="INSERTYOURAPIKEYHERE" +GROQ_API_KEY="INSERTYOURAPIKEYHERE" diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..dd84ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Smartphone (please complete the following information):** + - Device: [e.g. iPhone6] + - OS: [e.g. iOS8.1] + - Browser [e.g. stock browser, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..bbcbbe7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0f28be2 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,13 @@ +## Contributing + +We welcome contributions! Please read the [CONTRIBUTING](CONTRIBUTING.md) guidelines before submitting a pull request. + +### Note for Contributors + +This project is based on Groq's API, not the original Together API. If you are contributing, please ensure compatibility and optimizations are aligned with Groq's specifications and guidelines. + +## Contact + +For any questions or feedback, please open an issue in this repository. + +--- diff --git a/README.md b/README.md index 9ad8e66..d6d1e4b 100644 --- a/README.md +++ b/README.md @@ -1,160 +1,162 @@ -# Mixture-of-Agents (MoA) -[![License](https://img.shields.io/badge/License-Apache_2.0-green.svg)](LICENSE) -[![arXiv](https://img.shields.io/badge/ArXiv-2406.04692-b31b1b.svg)](https://arxiv.org/abs/2406.04692) -[![Discord](https://img.shields.io/badge/Discord-Together%20AI-blue?logo=discord&logoColor=white)](https://discord.com/invite/9Rk6sSeWEG) -[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/togethercompute.svg?style=social&label=Follow%20%40togethercompute)](https://twitter.com/togethercompute) -MoA architecture + ```sh + git clone https://github.com/LebToki/MoA.git + cd MoA + ``` -

- Overview · - Quickstart · - Advanced example · - Interactive CLI Demo - · - Evaluation - · - Results - . - Credits -

+2. **Install Dependencies**: -## Overview + ```sh + pip install -r requirements.txt + ``` + +2.1. **List of Dependencies** -Mixture of Agents (MoA) is a novel approach that leverages the collective strengths of multiple LLMs to enhance performance, achieving state-of-the-art results. By employing a layered architecture where each layer comprises several LLM agents, **MoA significantly outperforms GPT-4 Omni’s 57.5% on AlpacaEval 2.0 with a score of 65.1%**, using only open-source models! +- **openai**: OpenAI API client library. +- **fire**: A Python library for creating command line interfaces. +- **loguru**: A library to make logging in Python simpler and more readable. +- **datasets**: Hugging Face's library for accessing and managing datasets. +- **typer**: A library for building command line interface applications. +- **rich**: A Python library for rich text and beautiful formatting in the terminal. +- **Flask**: A micro web framework for Python. +- **Flask-SQLAlchemy**: Adds SQLAlchemy support to Flask applications. +- **Flask-Uploads**: A flexible library to handle file uploading in Flask. +- **Werkzeug**: A comprehensive WSGI web application library. +- **Flask-Migrate**: Handles SQLAlchemy database migrations for Flask applications using Alembic. +- **PyMuPDF (fitz)**: A Python binding for MuPDF – a lightweight PDF and XPS viewer. +- **python-docx**: A Python library for creating and updating Microsoft Word (.docx) files. -## Quickstart: MoA in 50 LOC -To get to get started with using MoA in your own apps, see `moa.py`. In this simple example, we'll use 2 layers and 4 LLMs. You'll need to: +3. **Set Up Environment Variables**: -1. Install the Together Python library: `pip install together` -2. Get your [Together API Key](https://api.together.xyz/settings/api-keys) & export it: `export TOGETHER_API_KEY=` -3. Run the python file: `python moa.py` + Create a `.env` file in the root directory and add your API keys: -MoA explained + ``` + GROQ_API_KEY=your_groq_api_key + OPENAI_API_KEY=your_openai_api_key + DEBUG=0 + ``` -## Multi-layer MoA Example +### Running the Application -In the previous example, we went over how to implement MoA with 2 layers (4 LLMs answering and one LLM aggregating). However, one strength of MoA is being able to go through several layers to get an even better response. In this example, we'll go through how to run MoA with 3+ layers in `advanced-moa.py`. - -```python -python advanced-moa.py + Open your web browser and navigate to the following URL to access the web-based interface: +```sh + http://127.0.0.1:5000/ ``` -MoA – 3 layer example -## Interactive CLI Demo +## Usage -This interactive CLI demo showcases a simple multi-turn chatbot where the final response is aggregated from various reference models. +### Interacting with the MoA Grog Chatbot -To run the interactive demo, follow these 3 steps: +- **Model Selection**: Choose the model you want to use from the dropdown menu. The default model is `llama3-70b-8192`, which balances performance and speed. + +- **Temperature Control**: Adjust the temperature setting to control the randomness and creativity of the chatbot's responses. The default value is `0.7`, providing a good balance between deterministic and varied outputs. + +- **Max Tokens**: Define the maximum number of tokens (words or characters) for the response. The default is `2048`, which ensures comprehensive answers without overwhelming verbosity. + +- **Create Your Topics**: Easily create new conversation topics by entering your desired topic names in the text field provided. This helps organize your interactions and revisit previous conversations. + +- **Choose Your Topic**: Select a topic by clicking on it in the sidebar. The chat interface will load on the right, allowing you to continue your discussion seamlessly. + +- **Instruction Input**: Enter your prompt or instruction in the text area. This is where you ask questions or provide commands to the chatbot. + +- **Theme Toggle**: Enhance your user experience by switching between light and dark modes. Use the "Switch to Dark Mode" button to toggle themes based on your preference. + +- **Submit and View Responses**: After filling in the necessary fields, submit the form to receive a response from the MoA Grog Chatbot. The response will be displayed on the same page, within the chat interface. -1. Export Your API Key: `export TOGETHER_API_KEY={your_key}` -2. Install Requirements: `pip install -r requirements.txt` -3. Run the script: `python bot.py` +### Additional Features -The CLI will prompt you to input instructions interactively: +- **Create New Conversations**: Use the sidebar to create new conversation topics, helping you manage different discussions effectively. + +- **Reset All Conversations**: If needed, reset all conversations from the sidebar to start fresh. -1. Start by entering your instruction at the ">>>" prompt. -2. The system will process your input using the predefined reference models. -3. It will generate a response based on the aggregated outputs from these models. -4. You can continue the conversation by inputting more instructions, with the system maintaining the context of the multi-turn interaction. +This intuitive interface makes it easy to engage with the MoA Grog Chatbot, providing a seamless and interactive user experience. -### [Optional] Additional Configuration -The demo will ask you to specify certain options but if you want to do additional configuration, you can specify these parameters: +### Planned Features -- `--aggregator`: The primary model used for final response generation. -- `--reference_models`: List of models used as references. -- `--temperature`: Controls the randomness of the response generation. -- `--max_tokens`: Maximum number of tokens in the response. -- `--rounds`: Number of rounds to process the input for refinement. (num rounds == num of MoA layers - 1) -- `--num_proc`: Number of processes to run in parallel for faster execution. -- `--multi_turn`: Boolean to toggle multi-turn interaction capability. +- **Uploading Documents**: The MoA Groq Chatbot will support file uploads and interact with the content of the uploaded documents, adding functionality to handle file uploads, process the contents of these files, and integrate the results into the chatbot's conversation flow. +- **Refine the styling**: With the latest Bootstrap and jQuery, we have room to enhance the UI/UX further. +- **Chronological ordering**: Move recent chats to the top (DESC order) to cut down on scrolling. +- **Further enhancement of the output**: Currently, not much has been implemented to control the output except basic styling. This is an area to be worked on based on various use cases. -## Evaluation -We provide scripts to quickly reproduce some of the results presented in our paper -For convenience, we have included the code from [AlpacaEval](https://github.com/tatsu-lab/alpaca_eval), -[MT-Bench](https://github.com/lm-sys/FastChat), and [FLASK](https://github.com/kaistAI/FLASK), with necessary modifications. -We extend our gratitude to these projects for creating the benchmarks. +## File Structure -### Preparation +- **MoA/** + - `app.py` - Flask application + - `bot.py` - Main chatbot logic + - `utils.py` - Utility functions + - `requirements.txt` - Python dependencies + - **templates/** + - `index.html` - HTML template for the web interface + - `chat.html` - HTML template for the chat interface + - **static/** + - `style.css` - CSS styles for the web interface + - `script.css` - JavaScript for theme switching and UI enhancements + - `bot.png` - favicon -```bash -# install requirements -pip install -r requirements.txt -cd alpaca_eval -pip install -e . -cd FastChat -pip install -e ".[model_worker,llm_judge]" -cd .. -# setup api keys -export TOGETHER_API_KEY= -export OPENAI_API_KEY= -``` +## Changelog +What's New in 1.1.0 · [02/07/2024] +- Implemented Dark Mode Support: Switch between light and dark themes for better usability. +- Enhanced UI/UX: Updated the styling of the chat interface, including better message formatting and improved layout. +- Improved Form Layout: Grouped form inputs on a single row for better space utilization. +- Sidebar Adjustment: Reduced the sidebar width to 180px to provide more space for the main chat interface. +- Document Upload Support: Added the ability to upload documents and interact with the content within the chatbot. +- Improved Sorting: Ensured conversation messages are displayed in descending order to prioritize the most recent interactions. -### Run AlpacaEval 2 +
+Previous Releases +Initial Release · [01/07/2024] -To run AlpacaEval 2, execute the following scripts: +- Code Organization: Initial setup of the project with organized structure for controllers, models, and views. +- Error Handling: Basic error handling for API requests and user inputs. +- Front-end Enhancements: Initial design of the UI with Bootstrap and FontAwesome integration. Responsive design for better accessibility on all devices. +- Performance Considerations: Basic optimizations for faster loading times. +- Accessibility and Usability: Added alt attributes to all images for better accessibility. +
-``` -bash run_eval_alpaca_eval.sh -``` +## Acknowledgements -### Run MT-Bench +- **Original Creator**: Special thanks to the original creator of this amazing project. [togethercomputer](https://github.com/togethercomputer/MoA) +- **Matthew Berman**: A special thanks to [Matthew Berman](https://www.youtube.com/@matthew_berman) for showcasing this project and providing valuable insights. -For a minimal example of MT-Bench evaluation, run: - -``` -bash run_eval_mt_bench.sh -``` - -### Run FLASK +## License -For a minimal example of FLASK evaluation, run: +

This work by Tarek Tarabichi is licensed under CC BY 4.0

-``` -bash run_eval_flask.sh -``` +## Contributing -### Results +We welcome contributions! Please read the [CONTRIBUTING](CONTRIBUTING.md) guidelines before submitting a pull request. -
- alpaca_mtbench -
-
+# Note for Contributors +This project is based on Groq's API, not the original Together API. +If you are contributing, please ensure compatibility and optimizations are aligned with Groq's specifications and guidelines. -We achieved top positions on both the AlpacaEval 2.0 leaderboard and MT-Bench. Notably, on AlpacaEval 2.0, using solely open-source models, we achieved a margin of 7.6% absolute improvement from 57.5% (GPT-4 Omni) to 65.1% (MoA). +## Contact -
- flask -
-
+For any questions or feedback, please open an issue in this repository. -FLASK offers fine-grained evaluation of models across multiple dimensions. Our MoA method significantly outperforms the original Qwen1.5-110B-Chat on harmlessness, robustness, correctness, efficiency, factuality, commonsense, insightfulness, completeness. Additionally, MoA also outperforms GPT-4 Omni in terms of correctness, factuality, insightfulness, completeness, and metacognition. +--- +# Get Involved +Whether you're a developer, system integrator, or enterprise user, you can trust that we did everything possible to make it as smooth and easy as 1,2,3 to set up MoA Groq Chatbot. -Please feel free to contact us if you have difficulties in reproducing the results. +⭐ Give us a star on GitHub 👆 -## Credits +⭐ Fork the project on GitHub and contribute👆 -Notably, this work was made possible by the collaborative spirit and contributions of active organizations in the AI field. We appreciate the efforts of Meta AI, Mistral AI, Microsoft, Alibaba Cloud, and DataBricks for developing the Llama 3, Mixtral, WizardLM 2, Qwen 1.5, and DBRX models. Additionally, we extend our gratitude to Tatsu Labs, LMSYS, and KAIST AI for developing the AlpacaEval, MT-Bench, and FLASK evaluation benchmarks. +🚀 Do you like to code? You're more than welcome to contribute Join the Discussions! -## License +💡 Got a feature suggestion? Add your roadmap ideas -This project is licensed under the Apache 2.0 License - see the LICENSE file for details. +
-## Citation +This project is licensed under the Attribution License. +2024 · Tarek Tarabichi from 2TInteractive.com · Made with 💙 -If you find this work helpful, please consider citing: +Thank you for using MoA Groq Chatbot! +We hope you find it useful and look forward to your contributions. -```bibtex -@article{wang2024mixture, - title={Mixture-of-Agents Enhances Large Language Model Capabilities}, - author={Wang, Junlin and Wang, Jue and Athiwaratkun, Ben and Zhang, Ce and Zou, James}, - journal={arXiv preprint arXiv:2406.04692}, - year={2024} -} -``` diff --git a/app.py b/app.py new file mode 100644 index 0000000..f3b24de --- /dev/null +++ b/app.py @@ -0,0 +1,128 @@ +from flask import Flask, request, render_template, redirect, url_for +from flask_sqlalchemy import SQLAlchemy +from flask_uploads import UploadSet, configure_uploads, DOCUMENTS +from werkzeug.utils import secure_filename +from datetime import datetime +from flask_migrate import Migrate +import os + +# Ensure the 'uploads' directory exists +if not os.path.exists('uploads'): + os.makedirs('uploads') + +from utils import generate_with_references, generate_together_stream # Ensure these functions are defined or imported + +app = Flask(__name__) +app.config['SECRET_KEY'] = os.urandom(24) +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///instance/conversations.db' +app.config['UPLOADED_FILES_DEST'] = 'uploads' +app.config['UPLOADED_FILES_ALLOW'] = DOCUMENTS + +db = SQLAlchemy(app) +migrate = Migrate(app, db) + +files = UploadSet('files', DOCUMENTS) +configure_uploads(app, files) + + +class Conversation(db.Model): + id = db.Column(db.Integer, primary_key=True) + topic = db.Column(db.String(100), nullable=False) + messages = db.Column(db.Text, nullable=False) + created_at = db.Column(db.DateTime, default=datetime.utcnow) + + +@app.route('/') +def home(): + conversations = Conversation.query.order_by(Conversation.created_at.desc()).all() + return render_template('index.html', conversations=conversations) + + +@app.route('/chat/', methods=['GET', 'POST']) +def chat(conv_id): + conversation = Conversation.query.get_or_404(conv_id) + conversations = Conversation.query.order_by(Conversation.created_at.desc()).all() + if request.method == 'POST': + if 'file' in request.files: + file = request.files['file'] + filename = secure_filename(file.filename) + file.save(os.path.join(app.config['UPLOADED_FILES_DEST'], filename)) + file_path = os.path.join(app.config['UPLOADED_FILES_DEST'], filename) + + # Process the uploaded file + content = extract_content(file_path) + os.remove(file_path) # Optional: remove file after processing + + # Create a clear instruction for summarizing the document + instruction = f"Please summarize the following document:\n\n{content}" + else: + instruction = request.form['instruction'] + + model = request.form['model'] + temperature = float(request.form['temperature']) + max_tokens = int(request.form['max_tokens']) + + messages = eval(conversation.messages) + messages.append({"role": "user", "content": instruction}) + + output = generate_with_references( + model=model, + temperature=temperature, + max_tokens=max_tokens, + messages=messages, + references=[], + generate_fn=generate_together_stream, + ) + + final_output = "" + for chunk in output: + out = chunk.choices[0].delta.content + if out is not None: + final_output += out + + messages.append({"role": "assistant", "content": final_output}) + conversation.messages = str(messages) + conversation.created_at = datetime.utcnow() # Update timestamp on message addition + db.session.commit() + + return redirect(url_for('chat', conv_id=conv_id)) + + messages = eval(conversation.messages) + return render_template('chat.html', conversation=conversation, messages=messages, conversations=conversations) + + +@app.route('/new', methods=['POST']) +def new_conversation(): + topic = request.form['topic'] + new_conv = Conversation(topic=topic, messages='[]') + db.session.add(new_conv) + db.session.commit() + return redirect(url_for('home')) + + +@app.route('/reset') +def reset(): + db.drop_all() + db.create_all() + return redirect(url_for('home')) + + +def extract_content(file_path): + content = "" + if file_path.endswith('.pdf'): + import fitz # PyMuPDF + doc = fitz.open(file_path) + for page in doc: + content += page.get_text() + elif file_path.endswith('.docx'): + import docx + doc = docx.Document(file_path) + for para in doc.paragraphs: + content += para.text + return content + + +if __name__ == "__main__": + with app.app_context(): + db.create_all() + app.run(debug=True) diff --git a/bot.py b/bot.py index 89f8f19..4af4011 100644 --- a/bot.py +++ b/bot.py @@ -23,19 +23,13 @@ Mixture of Agents (MoA) is a novel approach that leverages the collective strengths of multiple LLMs to enhance performance, achieving state-of-the-art results. By employing a layered architecture where each layer comprises several LLM agents, MoA significantly outperforms GPT-4 Omni’s 57.5% on AlpacaEval 2.0 with a score of 65.1%, using only open-source models! -This demo uses the following LLMs as reference models, then passes the results to the aggregate model for the final response: -- Qwen/Qwen2-72B-Instruct -- Qwen/Qwen1.5-72B-Chat -- mistralai/Mixtral-8x22B-Instruct-v0.1 -- databricks/dbrx-instruct - """ default_reference_models = [ - "Qwen/Qwen2-72B-Instruct", - "Qwen/Qwen1.5-72B-Chat", - "mistralai/Mixtral-8x22B-Instruct-v0.1", - "databricks/dbrx-instruct", + "llama3-70b-8192", + "llama3-8b-8192", + "mixtral-8x7b-32768", + "gemma-7b-it" ] @@ -83,10 +77,10 @@ def process_fn( def main( - model: str = "Qwen/Qwen2-72B-Instruct", + model: str = "llama3-70b-8192", reference_models: list[str] = default_reference_models, temperature: float = 0.7, - max_tokens: int = 512, + max_tokens: int = 2048, rounds: int = 1, multi_turn=True, ): @@ -118,7 +112,7 @@ def main( model = Prompt.ask( "\n1. What main model do you want to use?", - default="Qwen/Qwen2-72B-Instruct", + default="llama3-70b-8192", ) console.print(f"Selected {model}.", style="yellow italic") temperature = float( @@ -131,8 +125,8 @@ def main( console.print(f"Selected {temperature}.", style="yellow italic") max_tokens = int( Prompt.ask( - "3. What max tokens do you want to use? [cyan bold](512) [/cyan bold]", - default=512, + "3. What max tokens do you want to use? [cyan bold](2048) [/cyan bold]", + default=2048, show_default=True, ) ) @@ -199,8 +193,9 @@ def main( for chunk in output: out = chunk.choices[0].delta.content - console.print(out, end="") - all_output += out + if out is not None: + console.print(out, end="") + all_output += out print() if DEBUG: diff --git a/requirements.txt b/requirements.txt index bf9f390..869f118 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,15 @@ -openai -fire -loguru -datasets -typer -rich +Flask==2.3.2 +Flask-SQLAlchemy==2.5.1 +Flask-Uploads==0.2.1 +Werkzeug==3.0.1 +Flask-Migrate==3.0.1 +PyMuPDF==1.18.19 +python-docx==0.8.11 +openai==0.27.4 +fire==0.4.0 +loguru==0.6.0 +datasets==1.11.0 +typer==0.4.0 +rich==10.4.0 +python-dotenv==0.19.2 +requests==2.31.0 diff --git a/static/bot.png b/static/bot.png new file mode 100644 index 0000000..0104a2b Binary files /dev/null and b/static/bot.png differ diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..c0843f2 --- /dev/null +++ b/static/script.js @@ -0,0 +1,26 @@ +$(document).ready(function () { + const body = $('body'); + const toggleButton = $('#toggle-theme'); + + toggleButton.on('click', function () { + body.toggleClass('dark-mode'); + toggleButton.text(body.hasClass('dark-mode') ? 'Switch to Light Mode' : 'Switch to Dark Mode'); + }); + + // Preserve theme across page reloads + if (localStorage.getItem('theme') === 'dark') { + body.addClass('dark-mode'); + toggleButton.text('Switch to Light Mode'); + } + + toggleButton.on('click', function () { + body.toggleClass('dark-mode'); + if (body.hasClass('dark-mode')) { + localStorage.setItem('theme', 'dark'); + toggleButton.text('Switch to Light Mode'); + } else { + localStorage.setItem('theme', 'light'); + toggleButton.text('Switch to Dark Mode'); + } + }); +}); diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..80092bd --- /dev/null +++ b/static/style.css @@ -0,0 +1,131 @@ +/* General Styling */ +body { + font-family: Poppins, sans-serif; +} + +.container-fluid { + padding: 0; +} + +.sidebar { + background-color: #343a40; + color: #ffffff; + height: 100vh; + padding: 20px; +} + +.sidebar h2 { + font-size: 24px; + margin-bottom: 20px; +} + +.sidebar .form-group label { + color: #ffffff; +} + +.main-content { + padding: 20px; + overflow-y: auto; + height: 100vh; +} + +.main-content h1 { + font-size: 28px; + margin-bottom: 20px; +} + +.chat-box { + height: calc(100vh - 220px); + overflow-y: auto; + border: 1px solid #ddd; + padding: 15px; + margin-bottom: 20px; + background-color: #f8f9fa; +} + +.msg { + padding: 10px; + border-radius: 5px; + margin-bottom: 10px; +} + +.msg.user { + background-color: #007bff; + color: #ffffff; + text-align: left; +} + +.msg.assistant { + background-color: #28a745; + color: #ffffff; + text-align: left; +} + +.form-row { + display: flex; + flex-wrap: wrap; +} + +.form-group { + flex: 1; + min-width: 150px; + padding: 10px; +} + +.btn-block { + width: 100%; +} + +/* Dark Mode */ +body.dark-mode { + background-color: #121212; + color: #ffffff; +} + +.sidebar.dark-mode { + background-color: #1e1e1e; + color: #ffffff; +} + +.main-content.dark-mode { + background-color: #1e1e1e; + color: #ffffff; +} + +.chat-box.dark-mode { + background-color: #333333; +} + +.dark-mode .msg.user { + background-color: #1f6feb; +} + +.dark-mode .msg.assistant { + background-color: #2ea043; +} + +.dark-mode .form-control, +.dark-mode .form-control-file, +.dark-mode .form-control:focus { + background-color: #444444; + color: #ffffff; + border-color: #555555; +} + +.dark-mode .btn-primary { + background-color: #3a3a3a; + border-color: #555555; + color: #ffffff; +} + +.dark-mode .btn-secondary { + background-color: #555555; + border-color: #666666; + color: #ffffff; +} + +.dark-mode .btn-danger { + background-color: #c82333; + border-color: #bd2130; + color: #ffffff; +} diff --git a/templates/chat.html b/templates/chat.html new file mode 100644 index 0000000..3091b7d --- /dev/null +++ b/templates/chat.html @@ -0,0 +1,82 @@ + + + + + + MoA Grog Chatbot + + + + + + + +
+
+ +
+

{{ conversation.topic }}

+
+ {% for msg in messages %} +
+ {{ msg['role'] }}: +
{{ msg['content']|safe }}
+
+ {% endfor %} +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+ + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..10758a2 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,85 @@ + + + + + + MoA Chatbot + + + + + + + + +
+
+ +
+

{{ conversation.topic }}

+
+ {% for msg in messages %} +
+ {{ msg['role'] }}: +
{{ msg['content']|safe }}
+
+ {% endfor %} +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ +
+
+
+
+
+ + + diff --git a/utils.py b/utils.py index 4651745..cf6acff 100644 --- a/utils.py +++ b/utils.py @@ -7,16 +7,17 @@ from loguru import logger +from dotenv import load_dotenv +load_dotenv() DEBUG = int(os.environ.get("DEBUG", "0")) - def generate_together( - model, - messages, - max_tokens=2048, - temperature=0.7, - streaming=False, + model, + messages, + max_tokens=2048, + temperature=0.7, + streaming=False, ): output = None @@ -25,7 +26,7 @@ def generate_together( try: - endpoint = "https://api.together.xyz/v1/chat/completions" + endpoint = "https://api.groq.com/openai/v1/chat/completions" if DEBUG: logger.debug( @@ -41,7 +42,7 @@ def generate_together( "messages": messages, }, headers={ - "Authorization": f"Bearer {os.environ.get('TOGETHER_API_KEY')}", + "Authorization": f"Bearer {os.environ.get('GROQ_API_KEY')}", }, ) if "error" in res.json(): @@ -75,16 +76,16 @@ def generate_together( def generate_together_stream( - model, - messages, - max_tokens=2048, - temperature=0.7, + model, + messages, + max_tokens=2048, + temperature=0.7, ): - endpoint = "https://api.together.xyz/v1" + endpoint = "https://api.groq.com/openai/v1/" client = openai.OpenAI( - api_key=os.environ.get("TOGETHER_API_KEY"), base_url=endpoint + api_key=os.environ.get("GROQ_API_KEY"), base_url=endpoint ) - endpoint = "https://api.together.xyz/v1/chat/completions" + endpoint = "https://api.groq.com/openai/v1/chat/completions" response = client.chat.completions.create( model=model, messages=messages, @@ -97,10 +98,10 @@ def generate_together_stream( def generate_openai( - model, - messages, - max_tokens=2048, - temperature=0.7, + model, + messages, + max_tokens=2048, + temperature=0.7, ): client = openai.OpenAI( @@ -135,8 +136,8 @@ def generate_openai( def inject_references_to_messages( - messages, - references, + messages, + references, ): messages = copy.deepcopy(messages) @@ -161,21 +162,27 @@ def inject_references_to_messages( def generate_with_references( - model, - messages, - references=[], - max_tokens=2048, - temperature=0.7, - generate_fn=generate_together, + model, + messages, + references=[], + max_tokens=2048, + temperature=0.7, + generate_fn=generate_together_stream, ): - if len(references) > 0: - messages = inject_references_to_messages(messages, references) - return generate_fn( + # Generate response using the provided generate function + response = generate_fn( model=model, messages=messages, temperature=temperature, max_tokens=max_tokens, ) + + # Check if the response is in the expected format + if hasattr(response, 'choices'): + return response + else: + return [{"choices": [{"delta": {"content": response}}]}] +