├── .env ├── .gitignore ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── OAuth.md ├── README.md ├── api.py ├── assets ├── chatbot_setting.png └── chatbot_ui.png ├── data ├── checkmate_moves.csv ├── code_generation.csv ├── cosmic │ ├── statistic │ │ └── 04-2025.csv │ └── vector_db_cosmic │ │ ├── 1 │ │ └── file_list.csv │ │ └── default │ │ └── file_list.csv ├── docs │ ├── Hansen_2017.pdf │ ├── logan_donovan_complete_guide_to_chess.pdf │ ├── memory_update_test.pdf │ └── ucl_2023.pdf ├── finetune_dataset.csv ├── test.csv ├── test_analyser.csv └── test_framework │ ├── attention │ └── rag_questions.csv │ ├── memory │ ├── memory.csv │ ├── memory_2.csv │ └── memory_update.csv │ ├── perception │ ├── capture_analysis_8.csv │ ├── capture_analysis_8_old.csv │ ├── capture_analysis_8_old_old.csv │ ├── fen_perception.csv │ └── perception_20.csv │ └── reasoning_dm_an │ └── puzzle_data_updated.csv ├── default └── file_list.csv ├── demo.py ├── docker-compose.postgres.yaml ├── docker-compose.yaml ├── logs ├── test │ ├── gemma-7b-it.txt │ ├── gpt-3.5-turbo.txt │ ├── gpt-4o.txt │ └── mistral-7b-instruct-v0.1.txt └── test_analyser │ ├── gemma-7b-it.txt │ ├── gpt-3.5-turbo.txt │ ├── gpt-4o.txt │ └── mistral-7b-instruct-v0.1.txt ├── main.py ├── modules ├── chess │ ├── chess_gencot.py │ ├── chess_genfen.py │ ├── chess_qa_puzzle.py │ └── chess_qa_quality.py ├── code_generation │ └── code_generation.py ├── docker │ ├── command.sh │ └── main_docker.py └── query_analyser │ └── test_query_analyser.py ├── pipelines └── cosmic_pipeline.py ├── postgress_setup.txt ├── requirements.txt ├── scripts ├── chatbot │ ├── cosmic.sh │ └── run_chatbot_docker.sh ├── code_generation │ └── start.sh ├── configs │ └── config.yaml └── demo │ └── run_demo.sh ├── src ├── maps.py ├── opensi_cosmic.py ├── query_analyser │ ├── query_analyser.py │ └── user_prompt.py └── services │ ├── base.py │ ├── chess.py │ ├── llms │ ├── LLMBase.py │ ├── Ollama.py │ ├── OllamaPullManager.py │ ├── llm.py │ ├── login.py │ ├── prompts │ │ ├── system_prompt.py │ │ └── user_prompt.py │ └── tokenizer.py │ ├── qa.py │ ├── rag.py │ └── vector_database.py ├── start.sh ├── third_party ├── Fen-To-Board-Image │ ├── LICENSE │ ├── README.md │ ├── documentation │ │ └── logo.png │ ├── examples │ │ ├── arrows │ │ │ ├── Knight.png │ │ │ └── Up.png │ │ ├── fonts │ │ │ ├── Roboto-Bold.ttf │ │ │ └── Roboto-Regular.ttf │ │ ├── pieces │ │ │ ├── black │ │ │ │ ├── Bishop.png │ │ │ │ ├── King.png │ │ │ │ ├── Knight.png │ │ │ │ ├── Pawn.png │ │ │ │ ├── Queen.png │ │ │ │ └── Rook.png │ │ │ └── white │ │ │ │ ├── Bishop.png │ │ │ │ ├── King.png │ │ │ │ ├── Knight.png │ │ │ │ ├── Pawn.png │ │ │ │ ├── Queen.png │ │ │ │ └── Rook.png │ │ ├── render_board.py │ │ ├── render_board_arrows.py │ │ ├── render_board_coordinates.py │ │ └── requirements.txt │ ├── fentoboardimage │ │ ├── Arrows.py │ │ ├── Checkerboard.py │ │ ├── Coordinates.py │ │ ├── FenParser.py │ │ ├── Pieces.py │ │ ├── Utils.py │ │ ├── __init__.py │ │ └── main.py │ ├── poetry.lock │ ├── pyproject.toml │ └── test │ │ ├── __init__.py │ │ ├── arrows1 │ │ ├── Knight.png │ │ └── Up.png │ │ ├── boards │ │ ├── board1.png │ │ ├── board10.png │ │ ├── board11.png │ │ ├── board12.png │ │ ├── board13.png │ │ ├── board14.png │ │ ├── board15.png │ │ ├── board16.png │ │ ├── board17.png │ │ ├── board18.png │ │ ├── board19.png │ │ ├── board2.png │ │ ├── board20.png │ │ ├── board21.png │ │ ├── board22.png │ │ ├── board23.png │ │ ├── board3.png │ │ ├── board4.png │ │ ├── board5.png │ │ ├── board6.png │ │ ├── board7.png │ │ ├── board8.png │ │ └── board9.png │ │ ├── fonts │ │ ├── Roboto-Bold.ttf │ │ └── Roboto-Regular.ttf │ │ ├── pieces │ │ ├── black │ │ │ ├── Bishop.png │ │ │ ├── King.png │ │ │ ├── Knight.png │ │ │ ├── Pawn.png │ │ │ ├── Queen.png │ │ │ └── Rook.png │ │ └── white │ │ │ ├── Bishop.png │ │ │ ├── King.png │ │ │ ├── Knight.png │ │ │ ├── Pawn.png │ │ │ ├── Queen.png │ │ │ └── Rook.png │ │ ├── pieces2 │ │ ├── black │ │ │ ├── Bishop.png │ │ │ ├── King.png │ │ │ ├── Knight.png │ │ │ ├── Pawn.png │ │ │ ├── Queen.png │ │ │ └── Rook.png │ │ └── white │ │ │ ├── Bishop.png │ │ │ ├── King.png │ │ │ ├── Knight.png │ │ │ ├── Pawn.png │ │ │ ├── Queen.png │ │ │ └── Rook.png │ │ ├── poetry.lock │ │ ├── pyproject.toml │ │ └── test.py └── stockfish │ └── stockfish-ubuntu-x86-64-avx2 └── utils ├── chat_history.py ├── general.py ├── log_tool.py ├── module.py ├── num2word.py ├── sanitise_input.py └── statistics.py /.env: -------------------------------------------------------------------------------- 1 | DATABASE_USER=cosmic 2 | DATABASE_PASSWORD=cosmic123 3 | PGADMIN_USER=root@root.com 4 | PGADMIN_PASSWORD=root123 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .env 3 | .venv 4 | env/ 5 | venv/ 6 | *__pycache__* 7 | data 8 | third_party 9 | database 10 | database 11 | ./scripts/configs/config_updated.yaml 12 | .idea -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Welcome to Contribute to the OpenSI-CoSMIC Project 2 | 3 | ## Basic Steps for Contributing to Our Project 4 | 5 | We suggest users follow [the standard guidelines](https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project), with each step explained, to contribute to our project. 6 | These include 7 | 8 | - Fork our project. 9 | - Create a topic branch from [release](https://github.com/TheOpenSI/CoSMIC/tree/release). 10 | - Make some commits, either fixing a bug or adding a new service, to improve the project. 11 | - Push this topic branch to your GitHub project. 12 | - Open a Pull Request on GitHub. 13 | - Discuss, and optionally continue committing. 14 | - We will merge or close the Pull Request. 15 | - Sync our updated [release](https://github.com/TheOpenSI/CoSMIC/tree/release) back to your fork. 16 | 17 | ## Raise an Issue 18 | 19 | If any issue is found in our project code, please create an issue ticket on GitHub with detailed description. 20 | We will respond in time and close the ticket once it is solved. 21 | 22 | ## Develop a System Service 23 | 24 | Our project resource code is mainly distributed in [src](src), [modules](modules), [scripts](scripts), and [utils](utils). 25 | 26 | - **Source code** ([src](src)) contains the system entry and basic classes of functions and services. 27 | - **Upper-level developments** ([modules](modules)) contains topics for batch processing, file analysis and parsing, and the deployment and wrapper of [base services](src/services). 28 | Each topic can be stored in a subfolder. 29 | - **Configurations** ([scripts](scripts)) contains the system configuration file and script files of each service. 30 | - **Tools** ([utils](utils)) contains shared tool/utility files and individual such files for each service. 31 | 32 | To develop a new service for our project, please create a pull request for each new service. 33 | 34 | ## Contact 35 | If you have any questions, please feel free to contact us through the email addresses in [README.md](README.md). -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Set Python environment. 2 | FROM python:3.11.12-slim 3 | 4 | # Work directory in container. 5 | WORKDIR /app 6 | 7 | # Port 8 | EXPOSE 3000 9 | 10 | # Copy application files and requirements.txt explicitly. 11 | COPY requirements.txt /app/requirements.txt 12 | COPY . /app 13 | 14 | # Build environment. 15 | RUN pip install -r requirements.txt 16 | 17 | # Entry point. 18 | CMD ["bash", "/app/scripts/chatbot/cosmic.sh"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024-2025 Open Source Institute 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | 1. The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | 2. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /OAuth.md: -------------------------------------------------------------------------------- 1 | # Implementing Microsoft OAuth in Your Application 2 | 3 | ## Azure AD Application Setup 4 | 5 | To enable Microsoft SSO, follow these steps to configure an Azure AD app: 6 | 7 | ### 1. Sign in to Azure Portal 8 | Visit [Azure Portal](https://portal.azure.com) and authenticate with your Microsoft or Azure AD account. 9 | 10 | ### 2. Register a New App 11 | - Navigate to **App registrations** using the search bar. 12 | - Click **+ New registration**. 13 | - Fill in the following details: 14 | - **Name**: cosmic-openwebui 15 | - **Supported account types**: Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox) 16 | > **Note**: You can change these details according to your preference. 17 | - Under **Redirect URI**, select **Web** as the platform and add the following URI: 18 | ``` 19 | /oauth/google/callback 20 | ``` 21 | - In our case, use the URI: 22 | ``` 23 | http://localhost:8080/oauth/microsoft/callback 24 | ``` 25 | - Click **Register**. 26 | 27 | For more detailed instructions, you can also refer to the official Microsoft documentation on registering an app: [Quickstart: Register an application](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app). 28 | 29 | ### 3. Copy IDs 30 | - In the app’s **Overview**, note the **Application (client) ID** and **Directory (tenant) ID**. 31 | - Add these values to your `.env` file. 32 | 33 | ### 4. Create Client Secret 34 | 35 | - Navigate to **Certificates & secrets** under the **Manage** section of your app. 36 | - Select **Client secrets** and click **+ New client secret**. 37 | - Add a description and choose an expiration period for the client secret. 38 | - Click **Add** to create the client secret. 39 | - Copy the **Value** of the client secret and add this to your `.env` file. 40 | 41 | ### 7. Edit Your `.env` File 42 | Place the IDs and secret into your `.env` file alongside your `docker-compose.yaml`: 43 | ```env 44 | AZURE_CLIENT_ID= 45 | AZURE_CLIENT_SECRET= 46 | AZURE_TENANT_ID= 47 | ``` 48 | ### 8. Start Your Application 49 | 50 | - After completing the setup, start your application follwing the [README](README.md). 51 | - Your application is now configured to use Microsoft OAuth! 52 | 53 | ## Configuring Other OAuth Services 54 | 55 | Open WebUI supports federated authentication with various OAuth providers. To configure additional OAuth services, follow the steps outlined in the [Open WebUI Federated Authentication Support documentation](https://docs.openwebui.com/features/sso). -------------------------------------------------------------------------------- /assets/chatbot_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/assets/chatbot_setting.png -------------------------------------------------------------------------------- /assets/chatbot_ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/assets/chatbot_ui.png -------------------------------------------------------------------------------- /data/code_generation.csv: -------------------------------------------------------------------------------- 1 | Question,Answer 2 | Generate a python function that can multipy 2 matrices, 3 | -------------------------------------------------------------------------------- /data/cosmic/statistic/04-2025.csv: -------------------------------------------------------------------------------- 1 | user_id,email,start_date,last_date,average_token_length,query_count 2 | 1,opensi@canberra.edu.au,"30-04-2025,12:27:29","30-04-2025,14:08:30",27,5 3 | -------------------------------------------------------------------------------- /data/cosmic/vector_db_cosmic/1/file_list.csv: -------------------------------------------------------------------------------- 1 | Source,Time,Comment 2 | -------------------------------------------------------------------------------- /data/cosmic/vector_db_cosmic/default/file_list.csv: -------------------------------------------------------------------------------- 1 | Source,Time,Comment 2 | -------------------------------------------------------------------------------- /data/docs/Hansen_2017.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/data/docs/Hansen_2017.pdf -------------------------------------------------------------------------------- /data/docs/logan_donovan_complete_guide_to_chess.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/data/docs/logan_donovan_complete_guide_to_chess.pdf -------------------------------------------------------------------------------- /data/docs/memory_update_test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/data/docs/memory_update_test.pdf -------------------------------------------------------------------------------- /data/docs/ucl_2023.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/data/docs/ucl_2023.pdf -------------------------------------------------------------------------------- /data/test.csv: -------------------------------------------------------------------------------- 1 | Question,Answer,Label 2 | "I have the following DataFrame: Col1 Col2 Col3 Type 0 1 2 3 1 1 4 5 6 1 2 7 8 9 2 3 10 11 12 2 4 13 14 15 3 5 16 17 18 3 The DataFrame is read from a CSV file. All rows which have Type 1 are on top, followed by the rows with Type 2, followed by the rows with Type 3, etc. I would like to shuffle the order of the DataFrame's rows according to a list. \ For example, give a list [2, 4, 0, 3, 1, 5] and desired result should be: Col1 Col2 Col3 Type 2 7 8 9 2 4 13 14 15 3 0 1 2 3 1 3 10 11 12 2 1 4 5 6 1 5 16 17 18 3 ... How can I achieve this? A: import pandas as pd import numpy as np df = pd.DataFrame({'Col1': [1, 4, 7, 10, 13, 16], 'Col2': [2, 5, 8, 11, 14, 17], 'Col3': [3, 6, 9, 12, 15, 18], 'Type': [1, 1, 2, 2, 3, 3]}) List = np.random.permutation(len(df)) result = ... # put solution in this variable BEGIN SOLUTION ",,2 3 | Why does White take exf5 given a chess FEN rn1qkbr1/p1p1pppp/5n2/1p1p1b2/2P1P3/1Q1B1N2/PP1P1PPP/RNB1K2R w KQq - 4 6,,3 4 | Who are you and what can you provide?,,3 5 | Tell me something about this system.,,3 6 | Who built this system?,,3 7 | How can I request a new service?,,3 8 | How many services do you provide?,,3 9 | What's the capital of Australia?,Canberra,3 10 | What's the capital of Bangladesh?,Dhaka,3 11 | What's the capital of Germany?,Berlin,3 12 | What's the capital of Spain?,Madrid,3 13 | add the following book to the system: data/docs/logan_donovan_complete_guide_to_chess.pdf,,1 14 | Who is the author of the book complete guide to chess?,Logan Donovan,3 15 | add the following book to the system: data/docs/ucl_2023.pdf,,1 16 | How many UCL titles does Real Madrid have?,14,3 17 | update the following information to the vector database: Real Madrid won 15 UCL titles.,,1 18 | How many UCL titles does Real Madrid have?,15,3 19 | What's the capital of Saudi Arabia?,Riyadh,3 20 | predict the next move given moves: d4 d5 c4 c6 cxd5 e6 dxe6 fxe6 Nf3 Bb4+ Nc3 Ba5,Bf4,0.1 21 | predict the next move given FEN: rn1qkbr1/p1p1pppp/5n2/1p1p1b2/2P1P3/1Q1B1N2/PP1P1PPP/RNB1K2R w KQq - 4 6,exf5,0.0 22 | skip ./data/test_framework/reasoning_dm_an/puzzle_data_updated.csv,, 23 | skip ./data/test_framework/attention/rag_questions.csv,, 24 | skip ./data/test_framework/memory/memory.csv,, 25 | skip ./data/test_framework/memory/memory_2.csv,, 26 | skip ./data/test_framework/memory/memory_update.csv,, 27 | skip ./data/test_framework/perception/capture_analysis_8.csv,, 28 | skip ./data/test_framework/perception/fen_perception.csv,, 29 | skip ./data/test_framework/perception/perception_20.csv,, 30 | skip ./data/checkmate_moves.csv,, 31 | skip ./data/finetune_dataset.csv,, 32 | skip ./data/code_generation.csv,, 33 | -------------------------------------------------------------------------------- /data/test_framework/attention/rag_questions.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer,Source 2 | 0,What are the first three moves in the Ruy Lopez opening?,1. e4 e5 2. Nf3 Nc6 3. Bb5,Page 29 3 | 1,Who discovered the Ruy Lopez opening?,Spanish priest Ruy Lopez in 1561.,Page 30 4 | 2,What is the first move in the Sicilian Defense?,1. e4 c5,Page 31 5 | 3,Why is the Sicilian Defense popular among black players?,It neutralizes any aggressive opening by White and can be used to Black’s advantage.,Page 31 6 | 4,What are the first two moves in the French Defense?,1. e4 e6 2. d4 d5,Page 32 7 | 5,French Defense favors which player?,Black,Page 32 8 | 6,Who discovered the Caro-Kann Defense and when?,Horatio Caro and Marcus Kann in 1886.,Page 33 9 | 7,What are the first moves in the Pirc Defense?,1. e4 d6 2. d4 Nf6 3. Nc3,Page 33 10 | 8,What is the first move in Alekhine’s Defense?,1. e4 f6,Page 34 11 | 9,When was Alekhine’s Defense discovered?,1921,Page 35 12 | 10,What are the first two moves in the Queen’s Gambit?,1. d4 d5 2. c4,Page 35 13 | 11,What is the first move in the Modern Defense?,1. e4 g6 2. d4 Bg7,Page 36 14 | 12,What are the first two moves in the King’s Indian Defense?,1. d4 Nf6 2. c4 g6,Page 37 15 | 13,What are the first two moves in the King’s Indian Attack?,1. Nf3 d5 2. g3,Page 38 16 | 14,What is the first move in the Dutch Defense?,1. d4 f5,Page 39 17 | 15,What are the four key principles behind chess strategies mentioned in the book?,"Piece quality and development, center control, king safety, pawn formation.",Page 64 18 | 16,What is the value of a queen in chess?,9,Page 65 19 | 17,What is the value of a rook in chess?,5,Page 65 20 | 18,What is the value of a bishop or knight in chess?,3,Page 65 21 | 19,What is the value of a pawn in chess?,1,Page 65 22 | 20,What attribute refers to a piece's ability to change its role from passive to active?,Flexibility,Page 65 23 | 21,What attribute ensures a piece is valuable as long as it remains on the board?,Stability,Page 65 24 | 22,What does the attribute 'mobility' refer to in chess?,The space available for a piece to move.,Page 65 25 | 23,What attribute involves understanding the suitability of each piece before employing them in a strategy?,Suitability,Page 65 26 | 24,What are the twin goals of the King’s Indian Attack?,To enable White to develop their pieces and to launch an all-out attack against the black king.,Page 38 27 | 25,What is a Blocked Center?,A situation where it is impossible to open the center,Page 68 28 | 26,What is an Open Center?,An open center is the opposite of the blocked center where both players have equal opportunity to build around the center,Page 70 29 | 27,What is the primary goal of the Sicilian Defense?,To neutralize White's aggressive opening.,Page 31 30 | 28,What opening is also known as the Spanish Game?,Ruy Lopez,Page 30 31 | 29,What can be called a reversed Sicilian defense for easy understanding for all practical purposes?,English opening,Page 34 32 | 30,Alekhine’s Defense is also regraded as what?,Hypermodem Defense,Page 35 33 | 31,What opening is regarded as aggressive and suitable for White players?,Queen’s Gambit,Page 36 34 | 32,What defense move starts with 1. e4 g6?,Modern Defense,Page 36 35 | 33,Who is the author of the book “The Complete Guide to Chess” ,Logan Donovan,Page 29 36 | 34,What is the mirror opposite of Black’s King’s Indian Defense?,King’s Indian Attack,Page 38 37 | 35,What are the weak pawns?,Pawns which are open for attack,Page 45 38 | 36,"In an open position, which is the stronger piece - Bishop or Knight?",Bishop,Page 59 39 | 37,"In a closed position, which is the stronger piece - Bishop or Knight?",Knight,Page 59 40 | 38,What defensive stance was initially considered terrible but is now popular?,Sicilian Defense,Page 31 41 | 39,Which principle involves ensuring your king’s safety?,King safety,Page 71 42 | -------------------------------------------------------------------------------- /data/test_framework/memory/memory.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,What is the name of the piece that moves in an L shape in chess?,Knight 3 | 1,How many squares are there on a standard chessboard?,64 4 | 2,What is the term for a situation where a king cannot escape check?,Checkmate 5 | 3,Which piece is the most powerful in chess?,Queen 6 | 4,What is the initial position of the white queen?,d1 7 | 5,In a game of chess which player moves first?,white 8 | 6,In a game of chess which player moves second?,black 9 | 7,What is the only piece that can jump over others?,Knight 10 | 8,What is it called when a pawn reaches the opposite side of the board?,Promotion 11 | 9,Which two pieces are involved in castling?,King and Rook 12 | 10,"What is the term for a move where the king moves two squares towards a rook, and the rook moves to the square next to the king?",Castling 13 | 11,Which piece starts on e1 for White?,King 14 | 12,How many ranks are there in a chess board?,8 15 | 13,What is the term for a draw in chess?,Stalemate 16 | 14,What is the maximum number of queens a player can have on the board?,9 17 | 15,What are the names of the files on a chessboard?,"a, b, c, d, e, f, g, h" 18 | 16,Which piece can only move diagonally?,Bishop 19 | 17,What is the name of the notation system used to record chess moves?,"Algebraic Notation, PGN, FEN" 20 | 18,Which piece starts on d8 for Black?,Queen 21 | 19,"Which piece can move any number of squares along a rank, file, or diagonal?",Queen 22 | 20,What is the starting position of the White's King side Bishop in algebraic notation?,c1 23 | 21,What is it called when the king is in check and does not have any other legal move?,Checkmate 24 | 22,What is the move called when a pawn captures an opposing piece by moving diagonally?,Pawn Capture 25 | 23,Which piece can move one square in any direction?,King 26 | 24,Which chess piece can move any number of squares along a rank and file only?,Rook 27 | 25,Which chess pieces can participate in castling?,King and Rook 28 | 26,What is the standard number of squares each pawn moves on its first move?,1 or 2 29 | 27,"At the start of the game, how many chess pieces are present on the board?",32 30 | 28,What a pawn that has advanced to the eighth rank gets promoted to?,Queen 31 | 29,Which piece can only move horizontally or vertically?,Rook 32 | 30,What is the starting position of the black king's knight?,g8 33 | 31,What is the special move involving a king and a rook?,Castling 34 | 32,How many pieces does each player start with?,16 35 | 33,How many bishops does each player start with?,2 36 | 34,How many knights does each player start with?,2 37 | 35,How many rooks does each player start with?,2 38 | 36,How many pawns does each player start with?,8 39 | 37,How many queens does each player start with?,1 40 | 38,Which chess piece is being moved when the chess move is e4 in Algebraic notation?,Pawn 41 | 39,Which chess piece is being moved when the chess move is Na3 in Algebraic notation?,Knight -------------------------------------------------------------------------------- /data/test_framework/memory/memory_2.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,"Given a chess move in algebraic notation, which chess pieces have been captured in the following game - d4 Nf6 Bf4?",None 3 | 1,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in this game - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4",3 4 | 2,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - d4 Nf6 Bf4?",0 5 | 3,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - d4 d5 Bf4 e6 Nf3 c5 e3 Bd6 Bg3 Bxg3 hxg3 cxd4 exd4 a6 c3 Nf6 Bd3 Nbd7 Nbd2 b5 Ne5?",2 6 | 4,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4?",3 7 | 5,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - e4 e6 f4 d5 e5 c5 Nf3 Nc6 c3 Nh6 d4 cxd4 cxd4 Qa5+?",2 8 | 6,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - e4 e6 Nf3 d5 exd5 exd5 d4 Bg4 Be2 Qe7 O-O Nc6 Re1 O-O-O Bb5 Qf6 Re3 Bxf3 Rxf3?",4 9 | 7,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in this game - Nf3 g6 g3 Bg7 Bg2 e6 O-O Ne7 c3 c5 d4 Qb6 dxc5 Qxc5 Be3 Qb5 b4 Nd5 a4 Qc4 Ra3",2 -------------------------------------------------------------------------------- /data/test_framework/memory/memory_update.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,How many UCL title does Real Madrid have?,14 3 | 1,What is the record for the most F1 points in a single season?,454 4 | 2,What is the record for highest number of race wins in a single season?,15 5 | 3,__update__store__ Real Madrid won 15 UCL titles., 6 | 4,"__update__store__ Most F1 points in a single season was scored by Max Verstappen in 2023, he scored 575 points in the season. He also won 19 out of 22 races in that season which is the highest number of race wins", 7 | 5,How many UCL title does Real Madrid have?,15 8 | 6,What is the record for the most F1 points in a single season?,575 9 | 7,What is the record for highest number of race wins in a single season?,19 -------------------------------------------------------------------------------- /data/test_framework/perception/capture_analysis_8.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - d4 Nf6 Bf4?",None 3 | 1,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4",3 4 | 2,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - d4 Nf6 Bf4?",0 5 | 3,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - d4 d5 Bf4 e6 Nf3 c5 e3 Bd6 Bg3 Bxg3 hxg3 cxd4 exd4 a6 c3 Nf6 Bd3 Nbd7 Nbd2 b5 Ne5?",4 6 | 4,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4?",3 7 | 5,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - e4 e6 f4 d5 e5 c5 Nf3 Nc6 c3 Nh6 d4 cxd4 cxd4 Qa5+?",2 8 | 6,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - e4 e6 Nf3 d5 exd5 exd5 d4 Bg4 Be2 Qe7 O-O Nc6 Re1 O-O-O Bb5 Qf6 Re3 Bxf3 Rxf3?",4 9 | 7,"Analyse each single move using Algebraic Notation in the following game. While keeping track of any capture marked by 'x', tell me how many captures occurred in the game at the end, it will be same as moves.count('x') - Nf3 g6 g3 Bg7 Bg2 e6 O-O Ne7 c3 c5 d4 Qb6 dxc5 Qxc5 Be3 Qb5 b4 Nd5 a4 Qc4 Ra3",2 10 | -------------------------------------------------------------------------------- /data/test_framework/perception/capture_analysis_8_old.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,"Given a chess move in algebraic notation, which chess pieces have been captured in the following game - d4 Nf6 Bf4?",None 3 | 1,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in this game - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4",3 4 | 2,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - d4 Nf6 Bf4?",0 5 | 3,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - d4 d5 Bf4 e6 Nf3 c5 e3 Bd6 Bg3 Bxg3 hxg3 cxd4 exd4 a6 c3 Nf6 Bd3 Nbd7 Nbd2 b5 Ne5?",4 6 | 4,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4?",3 7 | 5,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - e4 e6 f4 d5 e5 c5 Nf3 Nc6 c3 Nh6 d4 cxd4 cxd4 Qa5+?",2 8 | 6,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in the game - e4 e6 Nf3 d5 exd5 exd5 d4 Bg4 Be2 Qe7 O-O Nc6 Re1 O-O-O Bb5 Qf6 Re3 Bxf3 Rxf3?",4 9 | 7,"Given a chess move in algebraic notation, how many chess pieces have been captured so far in this game - Nf3 g6 g3 Bg7 Bg2 e6 O-O Ne7 c3 c5 d4 Qb6 dxc5 Qxc5 Be3 Qb5 b4 Nd5 a4 Qc4 Ra3",2 10 | -------------------------------------------------------------------------------- /data/test_framework/perception/capture_analysis_8_old_old.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,"How many chess pieces have been captured so far in this game - d4 Nf6 Bf4?",None 3 | 1,"How many chess pieces have been captured so far in this game - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4",3 4 | 2,"How many chess pieces have been captured so far in this game - d4 Nf6 Bf4?",0 5 | 3,"How many chess pieces have been captured so far in this game - d4 d5 Bf4 e6 Nf3 c5 e3 Bd6 Bg3 Bxg3 hxg3 cxd4 exd4 a6 c3 Nf6 Bd3 Nbd7 Nbd2 b5 Ne5?",4 6 | 4,"How many chess pieces have been captured so far in this game - d4 g6 e4 Bg7 Bf4 e6 Bc4 Ne7 Nf3 h6 Ne5 O-O Qg4 d5 exd5 exd5 Bd3 Bxg4?",3 7 | 5,"How many chess pieces have been captured so far in this game - e4 e6 f4 d5 e5 c5 Nf3 Nc6 c3 Nh6 d4 cxd4 cxd4 Qa5+?",2 8 | 6,"How many chess pieces have been captured so far in this game - e4 e6 Nf3 d5 exd5 exd5 d4 Bg4 Be2 Qe7 O-O Nc6 Re1 O-O-O Bb5 Qf6 Re3 Bxf3 Rxf3?",4 9 | 7,"How many chess pieces have been captured so far in this game - Nf3 g6 g3 Bg7 Bg2 e6 O-O Ne7 c3 c5 d4 Qb6 dxc5 Qxc5 Be3 Qb5 b4 Nd5 a4 Qc4 Ra3",2 -------------------------------------------------------------------------------- /data/test_framework/perception/fen_perception.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,"Given a chess board state in the following FEN - 1R6/p3k1p1/2p2b2/2Pn4/1BQPB3/P7/6PP/3q2K1 w - - 1 33, what's the position of the Black Queen?",d1 3 | 1,"Given a chess board state in the following FEN - 1R6/p3k1p1/2p2b2/2Pn4/1BQPB3/P7/6PP/3q2K1 w - - 1 33, what's the position of the White King?",g1 4 | 2,"Given a chess board state in the following FEN - 2r3k1/p4p1p/4pp2/1b6/pP1P3P/P3PN2/2rN1PP1/R3K2R w KQ - 1 20, what's the position of the White King?",e1 5 | 3,"Given a chess board state in the following FEN - 2r3k1/p4p1p/4pp2/1b6/pP1P3P/P3PN2/2rN1PP1/R3K2R w KQ - 1 20, what's the position of the Black King?",g8 6 | 4,"Given a chess board state in the following FEN - 4r1k1/1pR3p1/p2pn1qp/8/PPBP4/1QP1n3/3N2PP/5RK1 w - - 1 26, what's the position of the White Queen?",b3 7 | 5,"Given a chess board state in the following FEN - 4r1k1/1pR3p1/p2pn1qp/8/PPBP4/1QP1n3/3N2PP/5RK1 w - - 1 26, what's the position of the Black King?",g8 8 | 6,"Given a chess board state in the following FEN - 5r1k/p1p3pp/1p4p1/2n1P3/2B3P1/1P2r2P/P5K1/3R1R2 b - - 0 1, what's the position of the White King?",g2 9 | 7,"Given a chess board state in the following FEN - 5r1k/p1p3pp/1p4p1/2n1P3/2B3P1/1P2r2P/P5K1/3R1R2 b - - 0 1, what's the position of the Black King?",h8 10 | 8,"Given a chess board state in the following FEN - 3q3k/p2R3p/1p3bpB/8/2r3P1/5Q1P/PPP2PK1/8 b - - 0 1, what's the position of the White Queen?",f3 11 | 9,"Given a chess board state in the following FEN - 3q3k/p2R3p/1p3bpB/8/2r3P1/5Q1P/PPP2PK1/8 b - - 0 1, what's the position of the Black King?",h8 12 | 10,"Given a chess board state in the following FEN - rn2k2r/1p3ppp/p2b1n2/2p1q1Nb/2P5/2NP3P/PP2BPP1/R1BQ1RK1 w kq - 0 1, what's the position of theWhite Queen?",d1 13 | 11,"Given a chess board state in the following FEN - rn2k2r/1p3ppp/p2b1n2/2p1q1Nb/2P5/2NP3P/PP2BPP1/R1BQ1RK1 w kq - 0 1, what's the position of the Black Queen?",e5 14 | 12,"Given a chess board state in the following FEN - r4rk1/1pp2ppp/p1p2n2/8/3qP3/P1b2Q2/1P2RPPP/R1B3K1 w - - 0 1, what's the position of the Black Queen?",d4 15 | 13,"Given a chess board state in the following FEN - r4rk1/1pp2ppp/p1p2n2/8/3qP3/P1b2Q2/1P2RPPP/R1B3K1 w - - 0 1, what's the position of the White Queen?",f3 16 | 14,"Given a chess board state in the following FEN - rn2k1nr/ppp2ppp/6q1/2b1p1B1/2B1P1Q1/3P4/PPP2PPP/RN3RK1 b kq - 0 8, what's the position of the White King?",g1 17 | 15,"Given a chess board state in the following FEN - rn2k1nr/ppp2ppp/6q1/2b1p1B1/2B1P1Q1/3P4/PPP2PPP/RN3RK1 b kq - 0 8, what's the position of the White Queen?",g4 18 | 16,"Given a chess board state in the following FEN - 3qkb1r/4pppp/p7/1br1NQ2/8/RP6/2P1nPPP/5R1K b k - 1 22, what's the position of the White King?",h1 19 | 17,"Given a chess board state in the following FEN - 3qkb1r/4pppp/p7/1br1NQ2/8/RP6/2P1nPPP/5R1K b k - 1 22, what's the position of the Black King?",e8 20 | 18,"Given a chess board state in the following FEN - r2qk2r/ppp3pp/3pB2B/2b1p3/4P3/3P3Q/PP3PPP/nN1K3R b kq - 0 11, what's the position of the White King?",d1 21 | 19,"Given a chess board state in the following FEN - r2qk2r/ppp3pp/3pB2B/2b1p3/4P3/3P3Q/PP3PPP/nN1K3R b kq - 0 11, what's the position of the Black Queen?",d8 22 | 20,"Given a chess board state in the following FEN - r1b2k1r/ppp3pp/1b1p1q2/4R3/2B5/B7/P4PPP/RN1Q2K1 w - - 1 16, what's the position of the White King?",g1 23 | 21,"Given a chess board state in the following FEN - r1b2k1r/ppp3pp/1b1p1q2/4R3/2B5/B7/P4PPP/RN1Q2K1 w - - 1 16, what's the position of the White Queen?",d1 24 | 22,"Given a chess board state in the following FEN - 1rb1k2r/p1p2ppp/8/3R4/2Q5/4q3/P1P1B1PP/2K2R2 w k - 0 1, what's the position of the White King?",c1 25 | 23,"Given a chess board state in the following FEN - 1rb1k2r/p1p2ppp/8/3R4/2Q5/4q3/P1P1B1PP/2K2R2 w k - 0 1, what's the position of the Black Queen?",e3 26 | 24,"Given a chess board state in the following FEN - r3kb1r/pp3p1p/2n1p1p1/2p5/4N3/1B2P3/PPP3PP/3R1RK1 b kq - 1 16, what's the position of the White King?",g1 27 | 25,"Given a chess board state in the following FEN - r3kb1r/pp3p1p/2n1p1p1/2p5/4N3/1B2P3/PPP3PP/3R1RK1 b kq - 1 16, what's the position of the White Bishop?",b3 28 | 26,"Given a chess board state in the following FEN - 8/3K2k1/R1p2q2/1n2pp2/P3P3/1Q3P2/8/8 w - - 2 44, what's the position of the White King?",d7 29 | 27,"Given a chess board state in the following FEN - 8/3K2k1/R1p2q2/1n2pp2/P3P3/1Q3P2/8/8 w - - 2 44, what's the position of the Black King?",g7 30 | 28,"Given a chess board state in the following FEN - 2r4k/pp3Qpp/4pp2/8/1P1qpR1N/6PP/P1r3PK/8 b - - 0 1, what's the position of the White King?",h2 31 | 29,"Given a chess board state in the following FEN - 2r4k/pp3Qpp/4pp2/8/1P1qpR1N/6PP/P1r3PK/8 b - - 0 1, what's the position of the Black King?",h8 32 | 30,"Given a chess board state in the following FEN - 5R2/1R6/5p2/4n1pk/1p6/1P6/PKP2r2/8 w - - 8 43, what's the position of the White King?",b2 33 | 31,"Given a chess board state in the following FEN - 5R2/1R6/5p2/4n1pk/1p6/1P6/PKP2r2/8 w - - 8 43, what's the position of the Black Rook?",f2 34 | 32,"Given a chess board state in the following FEN - r1b1r3/pp1p1kpp/3P4/6qn/5p2/1Q6/PP1N2PP/4R2K b - - 6 21, what's the position of the White King?",h1 35 | 33,"Given a chess board state in the following FEN - r1b1r3/pp1p1kpp/3P4/6qn/5p2/1Q6/PP1N2PP/4R2K b - - 6 21, what's the position of the White Queen?",b3 36 | 34,"Given a chess board state in the following FEN - 2k1r3/ppp5/2r5/5p2/3P2P1/2N5/PP3P2/R2Q1RK1 w - - 0 22, what's the position of the White King?",g1 37 | 35,"Given a chess board state in the following FEN - 2k1r3/ppp5/2r5/5p2/3P2P1/2N5/PP3P2/R2Q1RK1 w - - 0 22, what's the position of the Black King?",c8 38 | 36,"Given a chess board state in the following FEN - 8/8/r1r2b1p/1N1R1k2/2P1pp2/5R2/5PKP/8 b - - 1 36, what's the position of the White King?",g2 39 | 37,"Given a chess board state in the following FEN - 8/8/r1r2b1p/1N1R1k2/2P1pp2/5R2/5PKP/8 b - - 1 36, what's the position of the Black King?",f5 40 | 38,"Given a chess board state in the following FEN - r3k2r/pp3p1p/6p1/2pPb3/2Bn4/2N1Q2N/PP4qP/1RBK3R w kq - 0 19, what's the position of the White King?",d1 41 | 39,"Given a chess board state in the following FEN - r3k2r/pp3p1p/6p1/2pPb3/2Bn4/2N1Q2N/PP4qP/1RBK3R w kq - 0 19, what's the position of the Black Queen?",g2 42 | -------------------------------------------------------------------------------- /data/test_framework/perception/perception_20.csv: -------------------------------------------------------------------------------- 1 | ,Question,Answer 2 | 0,How many pawns do white have after the following move - e4?,8 3 | 1,How many pawns do black and white have after the following moves - e4 c5 Nf3 d6 d4 cxd4,"black 8, white 7" 4 | 2,How many pawns do black and white have after the following moves - e4 c5 Nf3 d6 d4 cxd4 Nxd4,"black 7, white 7" 5 | 3,How many pawns do white have after the following moves - d4 Nf6 Bf4 d5 Nf3 e6 c4 Bd6 Bg3 Bxg3 hxg3 h6?,8 6 | 4,How many pawns do black have after the following moves - d4 Nf6 Bf4 d5 Nf3 e6 c4 Bd6 Bg3 Bxg3 hxg3 h6?,8 7 | 5,How many pawns do white have after the following moves - e4 e6 Qe2 c5 Nf3 Nc6 g3 g6 Bg2 Bg7 O-O Nge7 c3 O-O d3 b6 Na3 a6 Re1 d6 Nc4?,8 8 | 6,"After the following moves - e4, how many chess piecess are left on the board?",32 9 | 7,"After the following moves - d4 d5 Bf4 e6 Nf3 c5 c3 Nc6 e3 Nf6 Nbd2 Bd6 Bg3 cxd4 cxd4 Qb6 Bxd6 Nb4 Bxb4 Qxb4 b3 Bd7 Be2 h6 O-O g5 Ne5 O-O-O Nxf7 g4 Nxh8, how many chess pieces are left on the board?",25 10 | 8,"After the following moves - e4 e6 Nc3 Bb4 Nge2 Ne7 a3 Bxc3, how many chess piecess are left on the board?",31 11 | 9,"After the following moves - d4 d5 Bf4 Nf6 Nf3 h6 e3 e6 Bd3 Nc6 Nbd2 a6 c3 Bd6 Bg3 Bxg3 hxg3 O-O Qc2 g6 Rxh6 Re8 Nh4 e5 Nxg6 fxg6 Bxg6, how many chess piecess are left on the board?",26 12 | 10,"After the following moves - e4 e6 Nf3 d5 exd5 exd5 d4 Bg4 Be2 Qe7 O-O Nc6 Re1 O-O-O Bb5 Qf6 Re3 Bxf3 Rxf3 Qxd4 Rd3 Qc5, how many chess piecess are left on the board?",27 13 | 11,"After the following moves - d4 d5 Bf4 e6 Nf3 c5 e3 Bd6 Bg3 Bxg3 hxg3 cxd4 exd4 a6 c3 Nf6 Bd3 Nbd7 Nbd2 b5 Ne5 Nxe5 dxe5 Nd7 f4 Bb7 Rh2 Qb6 Nf3 g6 Qd2 Rc8 Rc1 O-O f5, how many chess piecess are left on the board?",26 14 | 12,"After the following moves - d4 Nf6 Bf4 d5 Nf3 Bf5 e3 c6 Nbd2 Qb6 b3 Nbd7 h3 Be4 Nxe4 Nxe4 Bd3 Nc3 Ne5, how many chess piecess are left on the board?",30 15 | 13,What was the last chess piece that have been captured in the following game - d4 e6 Bf4 h6 Nf3 d6 e4 Qf6 Qd2 Nc6 Bb5 Bd7 Nc3 a6 Bxc6?,Black knight 16 | 14,What was the last chess piece that have been captured in the game - d4 Nf6 Bf4 d5 Nf3 Bf5 e3 c6 Nbd2 Qb6 b3 Nbd7 h3 Be4 Nxe4 Nxe4 Bd3 Nc3 Ne5?,White knight 17 | 15,What was the last chess piece that have been captured in the game - d4 Nf6 Bf4 d5 Nf3 Bf5 e3 c6 Nbd2 Qb6 b3 Nbd7 h3 Be4 Nxe4?,Black bishop 18 | 16,What was the last chess piece that have been captured in the game - e4 e6 Nc3 d5 exd5 exd5 Nf3 Nf6 Bb5+ c6 Na4 cxb5 Qe2+ Be6 Qxb5+ Qd7 Nc3 a6 Qd3 Nc6 O-O Nb4 Qe2 d4 Ne4?,Black pawn 19 | 17,What was the last chess piece that have been captured in the game - e4 e6 Nc3 d5 exd5 exd5 Nf3 Nf6 Bb5+ c6 Na4 cxb5?,Black bishop 20 | 18,What was the last chess piece that have been captured in the game - d4 d5 Bf4 c5 e3 cxd4 exd4 e6 Nf3 Nc6 c3 h6 Qa4 Bd7 Bb5?,Black pawn 21 | 19,What was the last chess piece that have been captured in the game - d4 d5 Bf4 Nf6 Nf3 c5 e3 Bg4 Nbd2 cxd4 Bb5+ Nc6 exd4 Qb6 Bxc6+ bxc6 Nb3 e6 c3 Be7 h3 Bh5?,white bishop -------------------------------------------------------------------------------- /data/test_framework/reasoning_dm_an/puzzle_data_updated.csv: -------------------------------------------------------------------------------- 1 | ,setup,FEN,next_move_number,moves,result,player,best_case,best_case_updated 2 | 0,1,1R6/p3k1p1/2p2b2/2Pn4/1BQPB3/P7/6PP/3q2K1 w - - 1 33,33,33. Qf1 Bxd4+ 34. Kh1 Qxf1,0-1,Black,2,2 3 | 1,1,2r3k1/p4p1p/4pp2/1b6/pP1P3P/P3PN2/2rN1PP1/R3K2R w KQ - 1 20,20,20. d5 Rc1+ 21. Rxc1 Rxc1,0-1,Black,2,2 4 | 2,1,4r1k1/1pR3p1/p2pn1qp/8/PPBP4/1QP1n3/3N2PP/5RK1 w - - 1 26,26,26. Rff7 Qxg2,0-1,Black,1,1 5 | 3,1,5r1k/p1p3pp/1p4p1/2n1P3/2B3P1/1P2r2P/P5K1/3R1R2 b - - 0 1,1,1... Rxf1 2. Rd8+ Rf8 3. Rxf8,1-0,White,3,2 6 | 4,1,3q3k/p2R3p/1p3bpB/8/2r3P1/5Q1P/PPP2PK1/8 b - - 0 1,1,1... Qxd7 2. Qxf6+ Kg8 3. Qf8,1-0,White,3,2 7 | 5,1,rn2k2r/1p3ppp/p2b1n2/2p1q1Nb/2P5/2NP3P/PP2BPP1/R1BQ1RK1 w kq - 0 1,1,1. Nf3 Bxf3 2. Bxf3 Qh2,0-1,Black,2,2 8 | 6,1,r4rk1/1pp2ppp/p1p2n2/8/3qP3/P1b2Q2/1P2RPPP/R1B3K1 w - - 0 1,1,1. bxc3 Qd1+ 2. Re1 Qxe1,0-1,Black,2,2 9 | 7,1,rn2k1nr/ppp2ppp/6q1/2b1p1B1/2B1P1Q1/3P4/PPP2PPP/RN3RK1 b kq - 0 8,8,8... h6 9. Qc8,1-0,White,2,1 10 | 8,1,3qkb1r/4pppp/p7/1br1NQ2/8/RP6/2P1nPPP/5R1K b k - 1 22,22,22... Nd4 23. Qxf7,1-0,White,2,1 11 | 9,1,r2qk2r/ppp3pp/3pB2B/2b1p3/4P3/3P3Q/PP3PPP/nN1K3R b kq - 0 11,11,11... gxh6 12. Qh5+ Ke7 13. Qf7,1-0,White,3,2 12 | 10,1,r1b2k1r/ppp3pp/1b1p1q2/4R3/2B5/B7/P4PPP/RN1Q2K1 w - - 1 16,16,16. Qd5 Qxf2+ 17. Kh1 Qg1,0-1,Black,2,2 13 | 11,1,1rb1k2r/p1p2ppp/8/3R4/2Q5/4q3/P1P1B1PP/2K2R2 w k - 0 1,1,1. Rd2 Qa3+ 2. Kd1 Rb1,0-1,Black,2,2 14 | 12,1,r3kb1r/pp3p1p/2n1p1p1/2p5/4N3/1B2P3/PPP3PP/3R1RK1 b kq - 1 16,16,16... a6 17. Nf6+ Ke7 18. Rd7,1-0,White,3,2 15 | 13,1,8/3K2k1/R1p2q2/1n2pp2/P3P3/1Q3P2/8/8 w - - 2 44,44,44. Ra5 Qd6+ 45. Kc8 Qc7,0-1,Black,2,2 16 | 14,1,2r4k/pp3Qpp/4pp2/8/1P1qpR1N/6PP/P1r3PK/8 b - - 0 1,1,1... Rc1 2. Ng6+ hxg6 3. Rh4,1-0,White,3,2 17 | 15,1,5R2/1R6/5p2/4n1pk/1p6/1P6/PKP2r2/8 w - - 8 43,43,43. Rb6 Nd3+ 44. Kb1 Rf1,0-1,Black,2,2 18 | 16,1,r1b1r3/pp1p1kpp/3P4/6qn/5p2/1Q6/PP1N2PP/4R2K b - - 6 21,21,21... Kf8 22. Rxe8+ Kxe8 23. Qg8,1-0,White,3,2 19 | 17,1,2k1r3/ppp5/2r5/5p2/3P2P1/2N5/PP3P2/R2Q1RK1 w - - 0 22,22,22. gxf5 Rg8+ 23. Kh1 Rh6+ 24. Qh5 Rxh5,0-1,Black,3,3 20 | 18,1,8/8/r1r2b1p/1N1R1k2/2P1pp2/5R2/5PKP/8 b - - 1 36,36,36... Kg4 37. h3+ Kh4 38. Rxf4,1-0,White,3,2 21 | 19,1,r3k2r/pp3p1p/6p1/2pPb3/2Bn4/2N1Q2N/PP4qP/1RBK3R w kq - 0 19,19,19. Re1 Qc2,0-1,Black,1,1 22 | 20,1,r4rk1/4R2p/6p1/p6n/Np1q4/3P2Q1/1PP2PPP/4R1K1 w - - 3 23,23,23. Qc7 Qxf2+ 24. Kh1 Qf1+ 25. Rxf1 Rxf1,0-1,Black,3,3 23 | 21,1,rn4rk/ppp2R1p/3p4/3P3q/2P1P3/2N5/PP3Q1P/2b4K b - - 1 28,28,28... Na6 29. Qf6+ Rg7 30. Qxg7,1-0,White,3,2 24 | 22,1,r1b1k1nr/pppp1ppp/2n2q2/2b1p3/4P1Q1/1P6/PBPP1PPP/RN2KBNR w KQkq - 3 5,5,5. Nc3 Qxf2+ 6. Kd1 Qxf1,0-1,Black,2,2 25 | 23,1,r3r1k1/2pp1p2/1p2q3/pP5p/2P3n1/4PKPR/1Q1PN3/7R w - - 0 1,1,1. Rxh5 Qe4,0-1,Black,1,1 26 | 24,1,r7/pR6/4R3/2p2r2/1kP5/7P/PK6/8 b - - 2 39,39,39... Ka5 40. Rb5+ Ka4 41. Ra6,1-0,White,3,2 27 | 25,1,4r1k1/4r1p1/7p/1p1PBp2/p4P2/P2Q1P1b/1P3q1P/R3R2K w - - 0 1,1,1. Re2 Bg2,0-1,Black,1,1 28 | 26,1,r2q1rk1/pb3pp1/8/4pQ1p/4Nn2/8/PPB2PPP/R4RK1 b - - 1 16,16,16... Qe7 17. Nf6+ gxf6 18. Qh7,1-0,White,3,2 29 | 27,1,7r/R2nk1p1/2B1p2p/2b4Q/3qP3/6P1/P2N1P1P/2B3K1 w - - 0 1,1,1. Ba3 Qxf2+ 2. Kh1 Qg1,0-1,Black,2,2 30 | 28,1,r4rk1/pp2bppp/2p5/8/3B2Q1/8/P1q2PPP/3RK2R b K - 2 19,19,19... Qxa2 20. Qxg7,1-0,White,2,1 31 | 29,1,2kr1b1r/p1pq1ppp/1p6/4P3/8/3P1N1b/PPP2PKP/RNBQ1R2 w - - 0 1,1,1. Kg1 Qg4+ 2. Kh1 Qg2,0-1,Black,2,2 32 | 30,1,1b2r1k1/1p1q3p/p1n3pB/3N4/3Pp2Q/4P1P1/PP5P/5RK1 b - - 0 1,1,1... Qxd5 2. Qf6 Qd7 3. Qf8+ Rxf8 4. Rxf8,1-0,White,4,3 33 | 31,1,2r3k1/p1Q2p2/q7/5N1p/1P2P1p1/P4pP1/5P1P/5RK1 w - - 1 31,31,31. Qe5 Qxf1+ 32. Kxf1 Rc1,0-1,Black,2,2 34 | 32,1,r1n1r2k/5pq1/p1p4p/2Q1P3/P6n/1BN4P/1PP2RP1/5R1K w - - 2 27,27,27. Rxf7 Qxg2,0-1,Black,1,1 35 | 33,1,1r1qr1k1/5p1R/p2p2p1/1ppP1bP1/5P2/2N1Q3/PPP3P1/2K4R b - - 0 1,1,1... Rxe3 2. Rh8+ Kg7 3. R1h7,1-0,White,3,2 36 | 34,1,3R1k2/pbp1r2p/8/2b2pPp/2B2P2/6KP/PP6/8 b - - 5 31,31,31... Kg7 32. Rg8,1-0,White,2,1 37 | 35,1,6k1/pp4q1/8/3b1Rb1/2p5/2P5/PP3QPP/4r1K1 w - - 0 1,1,1. Qxe1 Be3+ 2. Qxe3 Qxg2,0-1,Black,2,2 38 | 36,1,1Q6/5ppk/3p4/4r3/4q3/2P5/P5PP/R5K1 w - - 3 25,25,25. Qxd6 Qe3+ 26. Kh1 Qe1+ 27. Rxe1 Rxe1,0-1,Black,3,3 39 | 37,1,RR6/2r2pp1/4p1k1/3p4/1BrPnKPP/2P5/8/8 b - - 2 42,42,42... Nxc3 43. h5+ Kf6 44. g5,1-0,White,3,2 40 | 38,1,8/2pQ1kpp/1p2p3/p2pP3/6P1/PKP1q3/7P/8 b - - 0 1,1,1... Kg6 2. Qxe6+ Kg5 3. Qf5+ Kh4 4. Qh5,1-0,White,4,3 41 | 39,1,2k5/pp3Bp1/2pp4/4p1p1/4Pqn1/P2P1P2/1PPNQ1r1/6K1 w - - 0 31,31,31. Kxg2 Qh2+ 32. Kf1 Qh1,0-1,Black,2,2 42 | -------------------------------------------------------------------------------- /default/file_list.csv: -------------------------------------------------------------------------------- 1 | Source,Time,Comment 2 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: demo.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | import os 26 | 27 | from src.opensi_cosmic import OpenSICoSMIC 28 | 29 | # ============================================================================================================= 30 | 31 | if __name__ == "__main__": 32 | # Switch on this to avoid massive warning. 33 | os.environ["TOKENIZERS_PARALLELISM"] = "false" 34 | 35 | # Get the file's absolute path. 36 | current_dir = os.path.dirname(os.path.abspath(__file__)) 37 | root = f"{current_dir}" 38 | 39 | # Build the system for a specific LLM. 40 | config_path = os.path.join(root, "scripts/configs/config.yaml") 41 | opensi_cosmic = OpenSICoSMIC(config_path=config_path) 42 | 43 | while True: 44 | # Get a query from the terminal. 45 | query = input("[Query] ") 46 | 47 | # Exit the program. 48 | if query.lower() in ["quit", "exit"]: break 49 | 50 | # Run for each question/query, return the truncated response if applicable. 51 | answer, _, _ = opensi_cosmic(query) 52 | 53 | # Print the results. 54 | print(f"[Answer] {answer}") 55 | 56 | # Remove memory cached in the system. 57 | opensi_cosmic.quit() -------------------------------------------------------------------------------- /docker-compose.postgres.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | ollama: 3 | image: ollama/ollama:latest 4 | container_name: ollama 5 | deploy: 6 | resources: 7 | reservations: 8 | devices: 9 | - driver: nvidia 10 | count: all 11 | capabilities: [gpu] 12 | volumes: 13 | - ollama:/root/.ollama 14 | networks: 15 | - cosmic_net 16 | 17 | cosmic_db_server: 18 | image: postgres:14-alpine 19 | container_name: postgres 20 | restart: always 21 | ports: 22 | - "5432:5432" 23 | env_file: 24 | - .env 25 | environment: 26 | POSTGRES_USER: ${DATABASE_USER} 27 | POSTGRES_PASSWORD: ${DATABASE_PASSWORD} 28 | POSTGRES_DB: openwebui_db 29 | volumes: 30 | - postgres-data:/var/lib/postgresql/data 31 | networks: 32 | - cosmic_net 33 | 34 | open-webui: 35 | build: 36 | context: ./../OpenWebUI-CoSMIC 37 | dockerfile: Dockerfile 38 | args: 39 | OLLAMA_BASE_URL: '/ollama' 40 | image: opensicbr/cosmic_openwebui:latest 41 | container_name: open-webui 42 | volumes: 43 | - open-webui:/app/backend/data #used to store the vector data base by open-webui and cosmic 44 | depends_on: 45 | - cosmic_db_server 46 | - ollama 47 | - pipelines 48 | - cosmic 49 | ports: 50 | - "${OPEN_WEBUI_PORT:-8080}:8080" 51 | env_file: 52 | - .env 53 | environment: 54 | - CORS_ALLOW_ORIGIN=http://localhost:5173;http://localhost:8080 55 | - OLLAMA_BASE_URL=http://ollama:11434 56 | - WEBUI_SECRET_KEY= 57 | - OPENAI_API_KEY=0p3n-w3bu! 58 | - OPENAI_API_BASE_URL=http://pipelines:9099 59 | - OPENSI_COSMIC_API_BASE_URL=http://localhost:3000 60 | - ENABLE_OAUTH_SIGNUP=true 61 | - MICROSOFT_CLIENT_ID=${AZURE_CLIENT_ID} 62 | - MICROSOFT_CLIENT_SECRET=${AZURE_CLIENT_SECRET} 63 | - MICROSOFT_CLIENT_TENANT_ID=${AZURE_TENANT_ID} 64 | - DATABASE_URL=postgresql://${DATABASE_USER}:${DATABASE_PASSWORD}@cosmic_db_server:5432/openwebui_db 65 | extra_hosts: 66 | - host.docker.internal:host-gateway 67 | restart: unless-stopped 68 | networks: 69 | - cosmic_net 70 | 71 | pipelines: 72 | # build: 73 | # context: ./../pipelines-openwebui 74 | # dockerfile: Dockerfile 75 | image: ghcr.io/open-webui/pipelines:main 76 | pull_policy: always 77 | container_name: pipelines 78 | volumes: 79 | - pipelines:/app/pipelines 80 | depends_on: 81 | - cosmic 82 | ports: 83 | - '9099:9099' 84 | environment: 85 | - OPENSI_COSMIC_API_BASE_URL=http://cosmic:3000 86 | - MAX_QUERIES_PER_USER=5 87 | - PIPELINES_URLS=https://github.com/TheOpenSI/CoSMIC/blob/production/pipelines/cosmic_pipeline.py 88 | tty: true 89 | extra_hosts: 90 | - host.docker.internal:host-gateway 91 | restart: unless-stopped 92 | networks: 93 | - cosmic_net 94 | 95 | cosmic: 96 | build: 97 | context: . 98 | dockerfile: Dockerfile 99 | container_name: cosmic 100 | image: opensicbr/cosmic:latest 101 | volumes: 102 | - open-webui:/app/backend/data 103 | - volume_configs:/app/scripts/configs 104 | ports: 105 | - '3000:3000' 106 | - '5678:5678' # debupy 107 | depends_on: 108 | - ollama 109 | tty: true 110 | restart: unless-stopped 111 | networks: 112 | - cosmic_net 113 | 114 | 115 | pgadmin: 116 | image: dpage/pgadmin4:latest 117 | container_name: pgadmin 118 | restart: always 119 | ports: 120 | - "5050:80" 121 | env_file: 122 | - .env 123 | environment: 124 | PGADMIN_DEFAULT_EMAIL: ${PGADMIN_USER} 125 | PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_PASSWORD} 126 | volumes: 127 | - pgadmin-data:/var/lib/pgadmin 128 | depends_on: 129 | - cosmic_db_server 130 | configs: 131 | - source: servers.json 132 | target: /pgadmin4/servers.json 133 | networks: 134 | - cosmic_net 135 | 136 | configs: 137 | servers.json: 138 | content: | 139 | { 140 | "Servers": { 141 | "1": { 142 | "Name": "openwebui_db", 143 | "Group": "Servers", 144 | "Port": 5432, 145 | "Username": "${DATABASE_USER}", 146 | "Host": "cosmic_db_server", 147 | "SSLMode": "prefer", 148 | "MaintenanceDB": "postgres" 149 | } 150 | } 151 | } 152 | 153 | 154 | volumes: 155 | ollama: {} 156 | open-webui: {} 157 | pipelines: {} 158 | volume_configs: {} 159 | postgres-data: {} 160 | pgadmin-data: {} 161 | 162 | networks: 163 | cosmic_net: 164 | driver: bridge -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | ollama: 3 | image: ollama/ollama:latest 4 | container_name: ollama 5 | deploy: 6 | resources: 7 | reservations: 8 | devices: 9 | - driver: nvidia 10 | count: all 11 | capabilities: [gpu] 12 | volumes: 13 | - ollama:/root/.ollama 14 | networks: 15 | - cosmic_net 16 | 17 | open-webui: 18 | # build: 19 | # context: ./../OpenWebUI-CoSMIC 20 | # dockerfile: Dockerfile 21 | # args: 22 | # OLLAMA_BASE_URL: '/ollama' 23 | image: opensicbr/cosmic_openwebui:latest 24 | container_name: open-webui 25 | volumes: 26 | - open-webui:/app/backend/data #used to store the vector data base by open-webui and cosmic 27 | depends_on: 28 | - ollama 29 | - pipelines 30 | - cosmic 31 | - pycapsule 32 | ports: 33 | - "${OPEN_WEBUI_PORT:-8080}:8080" 34 | env_file: 35 | - .env 36 | environment: 37 | - CORS_ALLOW_ORIGIN=http://localhost:5173;http://localhost:8080 38 | - OLLAMA_BASE_URL=http://ollama:11434 39 | - WEBUI_SECRET_KEY= 40 | - OPENAI_API_KEY=0p3n-w3bu! 41 | - OPENAI_API_BASE_URL=http://pipelines:9099 42 | - OPENSI_COSMIC_API_BASE_URL=http://localhost:3000 43 | - ENABLE_OAUTH_SIGNUP=true 44 | - MICROSOFT_CLIENT_ID=${AZURE_CLIENT_ID} 45 | - MICROSOFT_CLIENT_SECRET=${AZURE_CLIENT_SECRET} 46 | - MICROSOFT_CLIENT_TENANT_ID=${AZURE_TENANT_ID} 47 | - ENABLE_WEBSOCKET_SUPPORT=false # https://github.com/open-webui/open-webui/discussions/11071 48 | extra_hosts: 49 | - host.docker.internal:host-gateway 50 | restart: unless-stopped 51 | networks: 52 | - cosmic_net 53 | 54 | pipelines: 55 | # build: 56 | # context: ./../pipelines-openwebui 57 | # dockerfile: Dockerfile 58 | image: ghcr.io/open-webui/pipelines:main 59 | pull_policy: always 60 | container_name: pipelines 61 | volumes: 62 | - pipelines:/app/pipelines 63 | depends_on: 64 | - cosmic 65 | ports: 66 | - '9099:9099' 67 | environment: 68 | - OPENSI_COSMIC_API_BASE_URL=http://cosmic:3000 69 | - MAX_QUERIES_PER_USER=5 70 | - PIPELINES_URLS=https://github.com/TheOpenSI/CoSMIC/blob/production/pipelines/cosmic_pipeline.py 71 | tty: true 72 | extra_hosts: 73 | - host.docker.internal:host-gateway 74 | restart: unless-stopped 75 | networks: 76 | - cosmic_net 77 | 78 | pycapsule: 79 | image: opensicbr/pycapsule:latest 80 | privileged: true 81 | container_name: pycapsule 82 | ports: 83 | - '8780:8780' 84 | volumes: 85 | - /var/run/docker.sock:/var/run/docker.sock 86 | - shared_mount:/app/services/Container/mount_dir/synk_mount 87 | depends_on: 88 | - ollama 89 | networks: 90 | - cosmic_net 91 | 92 | cosmic: 93 | build: 94 | context: . 95 | dockerfile: Dockerfile 96 | container_name: cosmic 97 | image: opensicbr/cosmic:latest 98 | volumes: 99 | - open-webui:/app/backend/data 100 | - volume_configs:/app/scripts/configs 101 | ports: 102 | - '3000:3000' 103 | - '5678:5678' # debupy 104 | depends_on: 105 | - ollama 106 | - pycapsule 107 | tty: true 108 | restart: unless-stopped 109 | networks: 110 | - cosmic_net 111 | 112 | volumes: 113 | ollama: {} 114 | open-webui: {} 115 | pipelines: {} 116 | volume_configs: {} 117 | shared_mount: 118 | external: true 119 | 120 | networks: 121 | cosmic_net: 122 | driver: bridge -------------------------------------------------------------------------------- /logs/test/gemma-7b-it.txt: -------------------------------------------------------------------------------- 1 | Loading checkpoint shards: 0%| | 0/2 [00:00 6 | # Muntasir Adnan 7 | # 8 | # Copyright (c) 2024 Open Source Institute 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 11 | # documentation files (the "Software"), to deal in the Software without restriction, including without 12 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 14 | # conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all copies or substantial 17 | # portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 20 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------------------------------------- 25 | 26 | import os, csv 27 | import pandas as pd 28 | 29 | from src.opensi_cosmic import OpenSICoSMIC 30 | from utils.log_tool import set_color 31 | 32 | # ============================================================================================================= 33 | 34 | if __name__ == "__main__": 35 | # Switch on this to avoid massive warning. 36 | os.environ["TOKENIZERS_PARALLELISM"] = "false" 37 | 38 | # Get the file's absolute path. 39 | current_dir = os.path.dirname(os.path.abspath(__file__)) 40 | root = f"{current_dir}" 41 | 42 | # Set a bunch of questions, can also read from .csv. 43 | df = pd.read_csv(f"{root}/data/test.csv") 44 | queries = df["Question"] 45 | answers = df["Answer"] 46 | 47 | # Build the system for a specific LLM. 48 | config_path = os.path.join(root, "scripts/configs/config.yaml") 49 | opensi_cosmic = OpenSICoSMIC(config_path=config_path) 50 | 51 | # Loop over questions to get the answers. 52 | for idx, (query, gt) in enumerate(zip(queries, answers)): 53 | # Skip marked questions. 54 | if query.find("skip") > -1: continue 55 | 56 | # Create a log file. 57 | if query.find(".csv") > -1: 58 | # Remove all namespace. 59 | query = query.replace(" ", "") 60 | 61 | # Return if file is invalid. 62 | if not os.path.exists(query): 63 | set_color("error", f"!!! Error, {query} not exist.") 64 | continue 65 | 66 | # Change the data folder to results for log file. 67 | log_file = query.replace("/data/", f"/results/{opensi_cosmic.config.llm_name}/") 68 | 69 | # Create a folder to store log file. 70 | log_file_name = log_file.split("/")[-1] 71 | log_dir = log_file.replace(log_file_name, "") 72 | os.makedirs(log_dir, exist_ok=True) 73 | log_file_pt = open(log_file, "w") 74 | log_file = csv.writer(log_file_pt) 75 | else: 76 | log_file_pt = None 77 | log_file = None 78 | 79 | # Run for each question/query, return the truncated response if applicable. 80 | answer, _, _ = opensi_cosmic(query, log_file=log_file) 81 | 82 | # Print the answer. 83 | if answer is not None and isinstance(gt, str): # compare with GT string 84 | # Assign to q variables. 85 | status = "success" if (answer.find(gt) > -1) else "fail" 86 | 87 | print(set_color(status, f"\nQuestion: '{query}' with GT: {gt}.\nAnswer: '{answer}'.")) 88 | elif answer is not None and answer != '': 89 | print(set_color("info", f"\nQuestion: '{query}'.\nAnswer: '{answer}'.")) 90 | 91 | # Close log file pointer. 92 | if log_file_pt is not None: 93 | log_file_pt.close() 94 | 95 | # Remove memory cached in the system. 96 | opensi_cosmic.quit() -------------------------------------------------------------------------------- /modules/chess/chess_genfen.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: chess_genfen.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # Muntasir Adnan 7 | # 8 | # Copyright (c) 2024 Open Source Institute 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 11 | # documentation files (the "Software"), to deal in the Software without restriction, including without 12 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 14 | # conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all copies or substantial 17 | # portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 20 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------------------------------------- 25 | 26 | import os, sys 27 | import pandas as pd 28 | import src.services.chess as chess_instances 29 | 30 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../..") 31 | 32 | from utils.log_tool import set_color 33 | from src.services.chess import ChessBase 34 | 35 | # ============================================================================================================= 36 | 37 | class FENGenerator(ChessBase): 38 | def __init__( 39 | self, 40 | **kwargs 41 | ): 42 | """Generate chess FEN with a sequence of moves. 43 | """ 44 | super().__init__(**kwargs) 45 | 46 | # Use Stockfish as chess backend. 47 | self.chess_engine = chess_instances.StockfishFENNextMove() 48 | 49 | def __call__( 50 | self, 51 | move_string: str 52 | ): 53 | """Parse the string containing moves, set the last move as to be predicted. 54 | 55 | Args: 56 | move_string (str): a string of moves. 57 | 58 | Returns: 59 | fen (str): chess FEN after all the moves except for the last move. 60 | next_move (str): last move as next move. 61 | """ 62 | # Remain the last checkmate move with the rest to generate FEN. 63 | moves = [str(v.replace(".", "")) for v in move_string.split(" ") if v != ""] 64 | 65 | # Last move as next move. 66 | next_move = moves[-1] 67 | 68 | # Reset chess board. 69 | self.chess_engine.reset_board() 70 | 71 | # Push a bunch of moves. 72 | for current_move in moves[:-1]: 73 | self.chess_engine.push_single(current_move, move_mode="algebric") 74 | 75 | # Get chess FEN. 76 | fen = self.chess_engine.get_fen() 77 | 78 | return fen, next_move 79 | 80 | def batch_process( 81 | self, 82 | query_csv: str 83 | ): 84 | """Generate chess FEN for multiple queries. 85 | 86 | Args: 87 | query_csv (str): .csv file containing multiple queries of move sequences. 88 | """ 89 | # This is to generate FEN with a sequence of moves to chess engine for model finetuning on reasoning checkmate. 90 | df = pd.read_csv(query_csv) 91 | raw_moves = df["moves"] 92 | 93 | # Write log head for printed information. 94 | if self.log_file is not None: 95 | self.log_file.writerow(["FEN", "Next Move"]) 96 | 97 | for idx, raw_move_string in enumerate(raw_moves): 98 | # Print the progress. 99 | if idx % 10 == 0 or idx == len(raw_moves) - 1: 100 | print(set_color("info", f"Generating FEN with moves for reasoning on checkmate {idx + 1}/{len(raw_moves)}...")) 101 | 102 | # Generate chess FEN for each query. 103 | fen, next_move = self.__call__(raw_move_string) 104 | 105 | # Write to .csv file 106 | if self.log_file is not None: 107 | self.log_file.writerow([fen, f"['{next_move}']"]) -------------------------------------------------------------------------------- /modules/chess/chess_qa_quality.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: chess_qa_quality.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # Muntasir Adnan 7 | # 8 | # Copyright (c) 2024 Open Source Institute 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 11 | # documentation files (the "Software"), to deal in the Software without restriction, including without 12 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 14 | # conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all copies or substantial 17 | # portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 20 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------------------------------------- 25 | 26 | import numbers 27 | import pandas as pd 28 | import numpy as np 29 | 30 | from utils.log_tool import set_color 31 | from utils.num2word import convert_number2word 32 | from src.services.qa import QABase 33 | 34 | # ============================================================================================================= 35 | 36 | class QualityEval(QABase): 37 | def __init__( 38 | self, 39 | is_rag: bool=False, 40 | **kwargs 41 | ): 42 | """Evaluate OpenSI-CoSMIC's qualities except for the reasoning which is evaluated in 43 | src/modules/chess_qa_puzzle.py. 44 | 45 | Args: 46 | is_rag (bool, optional): retrieve context from vector database or not. Defaults to False. 47 | """ 48 | super().__init__(**kwargs) 49 | 50 | # Set config. 51 | self.is_rag = is_rag 52 | 53 | def parse_quality_csv( 54 | self, 55 | csv_path: str 56 | ): 57 | """Get query information from .csv file. 58 | 59 | Args: 60 | csv_path (str): .csv file path. 61 | 62 | Returns: 63 | info (dict): a dictionary containing query information. 64 | """ 65 | # Read data. 66 | df = pd.read_csv(csv_path) 67 | 68 | # Set a dictionary. 69 | info = { 70 | "question": df["Question"], 71 | "answer": df["Answer"] 72 | } 73 | 74 | return info 75 | 76 | def batch_process( 77 | self, 78 | query_csv: str 79 | ): 80 | """Process multiple queries in a .csv file. 81 | 82 | Args: 83 | query_csv (str): .csv file path. 84 | 85 | Returns: 86 | average_score (float): average score over queries having a ground truth answer. 87 | """ 88 | # Get questions and ground truth answers. 89 | data_info = self.parse_quality_csv(query_csv) 90 | questions = data_info["question"] 91 | answers = data_info["answer"] 92 | 93 | num_questions = len(questions) 94 | score_list = [] 95 | 96 | # Write information head for log file. 97 | if self.log_file is not None: 98 | self.log_file.writerow(["Question", "Answer", "Label", "Score", "Comment", "Raw Answer"]) 99 | 100 | print(set_color("info", f"Processing {query_csv}...")) 101 | 102 | for idx, (question, gt_answer) in enumerate(zip(questions, answers)): 103 | # Print progress. 104 | if idx % 10 == 0 or idx == num_questions - 1: 105 | print(set_color("info", f"Solving {idx + 1}/{num_questions}.")) 106 | 107 | # Process each query. 108 | result, raw_result, retriever_score = super().__call__( 109 | question, 110 | is_rag=self.is_rag 111 | ) 112 | 113 | # For exit, skip, __update__store__, the result is None. 114 | if result is None: continue 115 | 116 | # Change None to "N/A" for comparison. 117 | if (gt_answer is None) or (isinstance(gt_answer, numbers.Number) and np.isnan(gt_answer)): 118 | gt_answer = "N/A" 119 | 120 | # Case insensitive and remove line change for better readability. 121 | if isinstance(gt_answer, numbers.Number) or gt_answer.isdigit(): 122 | # Convert number to word and compare both number and string format answer. 123 | gt_answer = [str(int(gt_answer)), str(convert_number2word(int(gt_answer)))] 124 | elif isinstance(gt_answer, str): 125 | # A number can be read as a string, so convert it to a number. 126 | gt_answer = gt_answer.lower().replace("\n", " ") 127 | 128 | if isinstance(result, str): 129 | result = result.lower().replace("\n", " ") 130 | raw_result = raw_result.lower().replace("\n", " ") 131 | 132 | # Check if the answer is in the analysis. 133 | if isinstance(gt_answer, list): 134 | score_per = float(len(np.nonzero([float(result.find(v) > -1) for v in gt_answer])[0]) > 0) 135 | else: 136 | score_per = float(result.find(gt_answer) > -1) 137 | 138 | # Push each question score to the list. 139 | score_list.append(score_per) 140 | 141 | # Save to log. 142 | if self.log_file is not None: 143 | # Take the first retriever score even if multiple documents are retrieved from vector database, 144 | # that is when topk>1. 145 | if isinstance(retriever_score, list): retriever_score = retriever_score[0] 146 | 147 | self.log_file.writerow([question, result, gt_answer, score_per, retriever_score, raw_result]) 148 | 149 | print(set_color( 150 | "info", 151 | f"Question: {question}, GT: {gt_answer}, Result: {result}, " \ 152 | f"Retrieve score: {retriever_score:.4f}.") 153 | ) 154 | 155 | # Calculate the average score for queries having a ground truth answer. 156 | average_score = np.mean(np.array(score_list)) 157 | 158 | return average_score -------------------------------------------------------------------------------- /modules/code_generation/code_generation.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: code_generation.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Muntasir Adnan 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | import os, sys 26 | import pandas as pd 27 | import requests 28 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../..") 29 | 30 | from typing import List 31 | from src.services.base import ServiceBase 32 | from utils.log_tool import set_color 33 | 34 | class CodeGenerator(ServiceBase): 35 | def __init__( 36 | self, 37 | service_container_name: str = "pycapsule", 38 | model_name: str = "qwen2.5-coder", 39 | **kwargs 40 | ) -> None: 41 | """ 42 | Code generation module. 43 | Sends http requests at port 8780 to the PyCapsule service. 44 | 45 | Args: 46 | service_container_name (str): Name of the container, set to localhost for development. 47 | Set this to the container name for docker network. 48 | model_name (str): Model name. 49 | """ 50 | super().__init__(**kwargs) 51 | self.model_name = model_name 52 | self.PORT = 8780 # PyCapsule service default port 53 | self.service_url = f"http://{service_container_name}:{self.PORT}" 54 | 55 | def _check_service_status(self): 56 | """ 57 | Check if the PyCapsule service is running. 58 | """ 59 | try: 60 | # Send a health check request to the service 61 | response: requests.Response = requests.post(f"{self.service_url}/health") 62 | if response.status_code != 200: 63 | raise Exception(f"PyCapsule service is not running. Status code: {response.status_code}") 64 | except requests.exceptions.RequestException as e: 65 | raise Exception(f"Failed to connect to PyCapsule service: {str(e)}") 66 | 67 | def __call__( 68 | self, 69 | query:str, 70 | timeout: int = 60 71 | ) -> tuple[str, str]: 72 | """ 73 | Send the user query to the PyCapsule service. 74 | 75 | Args: 76 | query (str): User query. 77 | timeout (int): Timeout for the request. Defaults to 30 seconds. 78 | """ 79 | try: 80 | # Check service availability 81 | self._check_service_status() 82 | 83 | # Send the user query to the PyCapsule service 84 | pycaspsule_response: requests.Response = requests.post( 85 | f"{self.service_url}/query", 86 | json={"query": query}, 87 | timeout=timeout 88 | ) 89 | 90 | if pycaspsule_response.status_code != 200: 91 | raise Exception( 92 | (f"PyCapsule service returned error. " 93 | f"Status code: {pycaspsule_response.status_code}") 94 | ) 95 | 96 | # Extract respone, error, code and status from the response 97 | response: str = pycaspsule_response.json()[0].get("code", "") 98 | raw_response: str = pycaspsule_response.json()[0].get("response", "") + "\n\n" + response 99 | 100 | except Exception as e: 101 | raw_response = response = "PyCapsule service encountered an error." 102 | print(str(e)) 103 | 104 | return response, raw_response # Order changed -------------------------------------------------------------------------------- /modules/docker/command.sh: -------------------------------------------------------------------------------- 1 | # Copy the command below on demand and run on terminal. 2 | 3 | # Delete docker containers with image name as opensi_docker. 4 | docker rm $(docker ps -aq --filter ancestor=opensi_docker) 5 | 6 | # Delete docker images. 7 | docker rmi -f $(docker images -aq) 8 | 9 | # Build a docker image. 10 | docker build -t opensi_docker . 11 | 12 | # Run the image within a container, static. 13 | docker run --gpus all -e query="Who are you?" opensi_docker 14 | 15 | # Run without copy, but mount, dynamic. 16 | docker run -v ${PWD}:/app -v ~/.cache/huggingface:/root/.cache/huggingface --gpus all -e query="What can you provide?" opensi_docker 17 | 18 | # Run within interaction. 19 | docker run -it -v ${PWD}:/app -v ~/.cache/huggingface:/root/.cache/huggingface --gpus all -e query="Who are you?" opensi_docker /bin/bash 20 | 21 | # Check size. 22 | docker ps --size -------------------------------------------------------------------------------- /modules/docker/main_docker.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: main_docker.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | import os, sys 26 | 27 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../..") 28 | 29 | from src.opensi_cosmic import OpenSICoSMIC 30 | 31 | # ============================================================================================================= 32 | 33 | if __name__ == "__main__": 34 | # Switch on this to avoid massive warning. 35 | os.environ["TOKENIZERS_PARALLELISM"] = "false" 36 | 37 | # # # Build the system for a specific LLM. 38 | opensi_cosmic = OpenSICoSMIC() 39 | 40 | # # Get query from arguments. 41 | query = os.getenv("query") 42 | 43 | # Run for each question/query, return the truncated response if applicable. 44 | answer, _, _ = opensi_cosmic(query) 45 | 46 | # Print the answer. 47 | print(f"Query: {query}\nAnswer: {answer}") 48 | 49 | # Remove memory cached in the system. 50 | opensi_cosmic.quit() -------------------------------------------------------------------------------- /modules/query_analyser/test_query_analyser.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: test_query_analyser.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | import pandas as pd 25 | import os, sys 26 | import numpy as np 27 | 28 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../..") 29 | 30 | from src.opensi_cosmic import OpenSICoSMIC 31 | from src.services.qa import QABase 32 | from utils.log_tool import set_color 33 | 34 | # ============================================================================================================= 35 | 36 | class QABaseTest(QABase): 37 | def __init__(self, *args, **kwargs): 38 | """Base class for QA test. 39 | """ 40 | super().__init__(*args, **kwargs) 41 | 42 | def __call__( 43 | self, 44 | query: str, 45 | context: str="", 46 | is_rag: bool=False, 47 | verbose: bool=False 48 | ): 49 | """Process each QA. 50 | 51 | Args: 52 | query (str): a question. 53 | context (str|dict, optional): contex associated with the question. Defaults to "". 54 | is_rag (bool, optional): if retrieve context for the question. Defaults to False. 55 | verbose (bool, optional): debug mode. Default to False. 56 | 57 | Returns: 58 | response (str): service number. 59 | empty (str): None. Just align the number of outputs. 60 | empty: None. Just align the number of outputs. 61 | """ 62 | # Get service option through query analyser. 63 | service_option, _ = self.query_analyser(query) 64 | 65 | return service_option, None, None 66 | 67 | # ============================================================================================================= 68 | 69 | class OpenSICoSMICTest(OpenSICoSMIC): 70 | def __init__(self, *args, **kwargs): 71 | """ Construct OpenSICoSMIC test instance. It contains LLM and services including vector database 72 | and RAG, where RAG includes context retriever and vector database update. 73 | Chess services are induced in PuzzleAnalyse and QualityEval, called on demand, not as global instance. 74 | """ 75 | super().__init__(*args, **kwargs) 76 | 77 | # Release unused LLM and database. 78 | self.llm.quit() 79 | self.rag.vector_database.quit() 80 | 81 | # Use QA test version. 82 | self.qa = QABaseTest(self.query_analyser, None, None) 83 | 84 | # ============================================================================================================= 85 | 86 | if __name__ == "__main__": 87 | # Get the file's absolute path. 88 | current_dir = os.path.dirname(os.path.abspath(__file__)) 89 | root = f"{current_dir}" 90 | 91 | # Load test dataset. 92 | df = pd.read_csv(f"{root}/../../data/test.csv") 93 | queries = df["Question"] 94 | answers = df["Label"].astype('str') 95 | 96 | # Build CoSMIC test version. 97 | opensi_cosmic = OpenSICoSMICTest() 98 | 99 | # Initialize statistics. 100 | fail_list = [] 101 | statistics_dict = {} 102 | label_list = ["0.0", "0.1", "1", "2", "3"] 103 | 104 | # Update to remove no answers. 105 | valid_indices = [idx for idx, v in enumerate(answers) if v != "nan"] 106 | queries = queries[valid_indices] 107 | answers = answers[valid_indices] 108 | 109 | for label in label_list: 110 | statistics_dict.update({label: {"success": 0, "fail": 0, "success_rate": -1}}) 111 | 112 | # Run over each sample and compare with the ground truth service number. 113 | for idx, (query, gt) in enumerate(zip(queries, answers)): 114 | # Align gt. 115 | if gt in ["1.0", "2.0", "3.0"]: 116 | gt = gt.replace(".0", "") 117 | 118 | # Print the progress. 119 | if idx % 50 == 0 or idx == len(queries) - 1: 120 | print(f"{idx + 1}/{len(queries)}, fail list: {fail_list}.") 121 | 122 | # Get service option. 123 | predicted_service, _, _ = opensi_cosmic(query) 124 | 125 | # Statistics for success and fail samples. 126 | if predicted_service == gt: 127 | statistics_dict[gt]["success"] += 1 128 | else: 129 | statistics_dict[gt]["fail"] += 1 130 | fail_list.append(idx) 131 | 132 | # Calculate the success rate. 133 | average_success_rate = [] 134 | 135 | for label in label_list: 136 | total_num = statistics_dict[label]["success"] + statistics_dict[label]["fail"] 137 | 138 | if total_num == 0: 139 | success_rate = 0 140 | else: 141 | success_rate = 100 * statistics_dict[label]["success"] / total_num 142 | average_success_rate.append(success_rate) 143 | 144 | statistics_dict[label]["success_rate"] = success_rate 145 | 146 | # Print the statistics. 147 | print(set_color( 148 | "info", 149 | f"{statistics_dict}.\n" \ 150 | f"Average success rate: {np.mean(average_success_rate)}.\n" \ 151 | f"Error list: {fail_list}.") 152 | ) -------------------------------------------------------------------------------- /pipelines/cosmic_pipeline.py: -------------------------------------------------------------------------------- 1 | import os 2 | import requests 3 | from pydantic import BaseModel, Field 4 | from typing import List 5 | from main import reload 6 | 7 | baseUrl = os.environ.get("OPENSI_COSMIC_API_BASE_URL", "http://cosmic:3000") 8 | 9 | class Pipeline: 10 | class Valves(BaseModel): 11 | pass 12 | # WORD_LIMIT: int = Field(title="Word Limit", default=300, description="Word limit when getting page summary") 13 | # WIKI_ROOT: str = Field(title="Wiki", default="https://en.wikipedia.org/wiki", description="Wikipedia root URL") 14 | # SOURCE_TYPE: str = Field(title="Source Type", default="Wikipedia", description="Source type for the pipeline", enum=["Wikipedia", "Google", "Custom"]) 15 | # A class-level dictionary to keep track of user queries. 16 | # Key: user_id, Value: number of queries asked. 17 | user_queries_count = {} 18 | 19 | def __init__(self): 20 | self.id = "cosmic_pipeline" 21 | self.name = "OpenSI-CoSMIC" 22 | 23 | # self.valves = self.Valves( 24 | # **{k: os.getenv(k, v.default) for k, v in self.Valves.model_fields.items()} 25 | # ) 26 | 27 | # print("TEST", self.valves.RATE_LIMIT) 28 | 29 | self.MAX_QUERIES_PER_USER = int(os.environ.get("MAX_QUERIES_PER_USER", "5")) 30 | 31 | # async def on_valves_updated(self): 32 | # pass 33 | 34 | 35 | def quit_cosmic(self): 36 | try: 37 | response = requests.get(f"{baseUrl}/quit") 38 | if response.status_code != 200: 39 | raise Exception(f"Error during /quit API call: {response.text}") 40 | print(response.json()["message"]) 41 | except requests.exceptions.RequestException as e: 42 | raise Exception(f"Error during /quit API call: {e}") 43 | 44 | async def on_startup(self): 45 | print(f"on_startup:{__name__}") 46 | 47 | async def on_shutdown(self): 48 | print(f"on_shutdown:{__name__}") 49 | self.quit_cosmic() 50 | 51 | def post_to_cosmic(self, user_message: str, body: dict) -> str: 52 | try: 53 | response = requests.post( 54 | f"{baseUrl}/cosmic", 55 | json={"user_message": user_message, "body": body} 56 | ) 57 | if response.status_code == 200: 58 | return response.json().get("result", "Something went wrong.") 59 | 60 | raise Exception(f"Error: {response.status_code}, {response.text}") 61 | except requests.exceptions.RequestException as e: 62 | raise Exception(f"Error during /cosmic API call: {e}") 63 | 64 | def pipe( 65 | self, 66 | user_message: str, 67 | model_id: str, 68 | messages: List[dict], 69 | body: dict 70 | ): 71 | # Some will run twice for history, just ignore. 72 | if user_message[:3] == "###": return "" 73 | 74 | # # Extract user_id from body. Adjust if user_id is available elsewhere. 75 | user_id = body["user"]["id"] 76 | user_role = body["user"]["role"] 77 | 78 | current_count = self.user_queries_count.get(user_id, 0) 79 | 80 | if (user_role != "admin") and (current_count >= self.MAX_QUERIES_PER_USER): 81 | # Return a message indicating the limit has been reached 82 | return "You have reached the maximum number of queries allowed." 83 | 84 | # Increment the count for this user 85 | self.user_queries_count[user_id] = current_count + 1 86 | 87 | answer = self.post_to_cosmic(user_message, body) 88 | if answer is None: answer = 'Successfully!' 89 | 90 | return answer 91 | 92 | # pipeline = Pipeline() 93 | 94 | # body = { 95 | # "user": { 96 | # "id": 1, 97 | # "role": "admin", 98 | # "email": "opensi@canberra.edu.au" 99 | # } 100 | # } 101 | 102 | # user_message = "Do you know what was my first question?" 103 | 104 | # print(pipeline.pipe(user_message=user_message, model_id="model_id", messages=[], body=body)) -------------------------------------------------------------------------------- /postgress_setup.txt: -------------------------------------------------------------------------------- 1 | ====================================================================== 2 | PostgreSQL + pgAdmin Setup on Ubuntu VM (Manual Installation) 3 | ====================================================================== 4 | 5 | ====================================================================== 6 | STEP 0: Connect to the Linux VM from Your Local Machine 7 | ====================================================================== 8 | 9 | If you're using Azure, AWS, or GCP, connect using SSH: 10 | 11 | ssh @ 12 | 13 | Example: 14 | 15 | ssh opensi@20.50.120.100 16 | 17 | If you're using a private key: 18 | 19 | ssh -i path/to/key.pem opensi@ 20 | 21 | You are now inside the VM terminal. 22 | 23 | ====================================================================== 24 | STEP 1: Install PostgreSQL 25 | ====================================================================== 26 | 27 | sudo apt update 28 | sudo apt install postgresql postgresql-contrib 29 | 30 | ====================================================================== 31 | STEP 2: Add 'postgres' User to SUDO Group 32 | ====================================================================== 33 | 34 | sudo usermod -aG sudo postgres 35 | 36 | ====================================================================== 37 | STEP 3: Set a Linux Password for the 'postgres' User 38 | ====================================================================== 39 | 40 | sudo passwd postgres 41 | 42 | ====================================================================== 43 | STEP 4: Set a PostgreSQL Account Password 44 | ====================================================================== 45 | 46 | sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'YourSecurePassword';" 47 | 48 | ====================================================================== 49 | STEP 5: Access PostgreSQL Shell 50 | ====================================================================== 51 | 52 | sudo su -l postgres 53 | psql 54 | 55 | ====================================================================== 56 | STEP 6: Create a Test Database and User 57 | ====================================================================== 58 | 59 | Inside the psql shell: 60 | 61 | CREATE DATABASE mytestdb; 62 | CREATE USER mytestuser WITH ENCRYPTED PASSWORD 'MyStr0ngP@SS'; 63 | GRANT ALL PRIVILEGES ON DATABASE mytestdb TO mytestuser; 64 | 65 | List databases: 66 | 67 | \l 68 | 69 | Connect to your new DB: 70 | 71 | \c mytestdb 72 | 73 | ====================================================================== 74 | STEP 7: Enable Remote Connections 75 | ====================================================================== 76 | 77 | 1. Edit postgresql.conf: 78 | 79 | sudo nano /etc/postgresql//main/postgresql.conf 80 | 81 | Uncomment and update this line: 82 | 83 | listen_addresses = '*' 84 | 85 | 2. Edit pg_hba.conf: 86 | 87 | sudo nano /etc/postgresql//main/pg_hba.conf 88 | 89 | Add: 90 | 91 | host all all 0.0.0.0/0 md5 92 | 93 | (Replace with subnet CIDR for production) 94 | 95 | ====================================================================== 96 | STEP 8: Restart PostgreSQL 97 | ====================================================================== 98 | 99 | sudo systemctl restart postgresql 100 | 101 | ====================================================================== 102 | STEP 9: Install and Configure pgAdmin Web 103 | ====================================================================== 104 | 105 | sudo apt install pgadmin4-web 106 | sudo /usr/pgadmin4/bin/setup-web.sh 107 | 108 | Enter admin email and password. 109 | 110 | ====================================================================== 111 | STEP 10: Allow Web Access from Local Machine 112 | ====================================================================== 113 | On the local machine terminal: 114 | 115 | ssh -L :localhost: @ 116 | 117 | ====================================================================== 118 | Step 11: Create Simple Docker that Access to Postgres 119 | ====================================================================== 120 | docker run -d -p 8080:8080 \ 121 | -e OPENAI_API_KEY=your_key \ 122 | -e WEBUI_SECRET_KEY=your_secret \ 123 | -e DATABASE_URL=postgresql://opeuser:data101@10.0.0.4:5432/opeweb \ 124 | --name openwebui \ 125 | 126 | Access the openweb from port 8080 127 | 128 | Access the pgadmin from http://127.0.0.1:5050/pgadmin4/ -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | huggingface_hub==0.24.0 2 | setuptools==75.1.0 3 | chess==1.10.0 4 | stockfish==3.28.0 5 | bitsandbytes==0.43.1 6 | faiss-cpu==1.8.0 7 | imageio==2.34.2 8 | llama_index==0.11.1 9 | matplotlib==3.7.5 10 | numpy==1.24.3 11 | openai==1.42.0 12 | pandas==2.0.3 13 | peft==0.11.1 14 | Pillow==10.4.0 15 | python-dotenv==1.0.1 16 | pytz==2024.1 17 | torch==2.3.0 18 | transformers==4.42.4 19 | python-box==7.2.0 20 | PyYAML==6.0.2 21 | regex==2024.5.15 22 | langchain==0.2.14 23 | langchain_community==0.2.12 24 | langchain_huggingface==0.0.3 25 | ollama==0.4.7 26 | httpx==0.27.2 27 | uvicorn==0.33.0 28 | fastapi==0.115.7 29 | passlib==1.7.4 30 | jwt==1.3.1 31 | python-multipart==0.0.20 32 | debugpy==1.8.14 -------------------------------------------------------------------------------- /scripts/chatbot/cosmic.sh: -------------------------------------------------------------------------------- 1 | echo "Starting Cosmic Chatbot" 2 | echo "========================" 3 | echo "Starting Ollama" 4 | ollama serve > ollama.log 2>&1 & 5 | # echo "Starting Chatbot" 6 | # bash /app/scripts/chatbot/run_chatbot_docker.sh 7 | 8 | # https://www.uvicorn.org/settings/#configuration-methods 9 | uvicorn api:app --host 0.0.0.0 --port 3000 -------------------------------------------------------------------------------- /scripts/chatbot/run_chatbot_docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" 4 | ROOT="${SCRIPT_DIR}/../.." 5 | 6 | image_name="open-webui" 7 | container_name="open-webui" 8 | host_port=3000 9 | container_port=8080 10 | 11 | # Dynamically get the host IP address 12 | HOST_IP=$(hostname -i | awk '{print $1}') 13 | echo "[INFO] Using host IP: $HOST_IP" 14 | 15 | # Create a shared volume for the container 16 | docker volume create volume_configs 17 | docker volume create volume_uploads 18 | 19 | ENV_CONTENT="" 20 | if [[ -e ${ROOT}/.env ]]; then 21 | ENV_CONTENT=$(cat ${ROOT}/.env) 22 | echo "Read .env file content" 23 | fi 24 | 25 | # Build the image 26 | docker build -t "$image_name" ${ROOT}/modules/chatbot 27 | docker rm "$container_name" &>/dev/null || true 28 | 29 | echo "[WARNING] For development purposes, the container is directly using the host network." 30 | echo "[WARNING] This is not recommended for production deployments." 31 | 32 | # Run the container 33 | docker run -d \ 34 | --network=host \ 35 | --add-host=host.docker.internal:$HOST_IP \ 36 | --name "$container_name" \ 37 | --restart always \ 38 | -v volume_configs:/app/backend/configs \ 39 | -v volume_uploads:/app/backend/data/uploads \ 40 | -e OPENAI_API_BASE_URL=http://host.docker.internal:9099 \ 41 | -e OPENAI_API_KEY=0p3n-w3bu! \ 42 | "$image_name" 43 | 44 | docker image prune -f 45 | 46 | # Run the pipeline script 47 | cd ${ROOT}/modules/chatbot/pipelines 48 | bash start_docker.sh 49 | cd ${ROOT} -------------------------------------------------------------------------------- /scripts/code_generation/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # check if requirements.txt exists 4 | if [ -f /usr/src/app/requirements.txt ]; then 5 | echo "Installing requirements..." 6 | pip3 install -r /usr/src/app/requirements.txt 7 | fi 8 | 9 | # check if main.py exists 10 | if [ -f /usr/src/app/main.py ]; then 11 | echo "Executing main.py..." 12 | python3 /usr/src/app/main.py 13 | else 14 | echo "Nothing to execute, shutting down." 15 | fi -------------------------------------------------------------------------------- /scripts/configs/config.yaml: -------------------------------------------------------------------------------- 1 | # Supported base LLMs: 2 | # mistral-7b-v0.1, mistral-7b-instruct-v0.1, mistral-7b-finetuned, 3 | # gemma-7b, gemma-7b-it, 4 | # gpt-3.5-turbo, gpt-4o, 5 | # ollama:[ollama model] from https://ollama.com/library. 6 | 7 | llm_name: "ollama:qwen2.5:7b" 8 | is_quantized: False 9 | seed: 0 # seed of response generation by base LLM. 10 | doc_directory: "" # directory containing .pdf documents to build the system's vector database. 11 | document_path: [] # a string or a list of .pdf to add context to the vector database. 12 | service: -1 # service selection: -1 [auto], 0 [chess], 1 [update vector database], 2 [code generation], 3 [general QA] 13 | 14 | query_analyser: 15 | llm_name: "ollama:llama3.1:8b" 16 | is_quantized: False 17 | 18 | chess: 19 | stockfish_path: "" # if empty, default to "third_party/stockfish/stockfish-ubuntu-x86-64-avx2" 20 | 21 | rag: # RAG-related config. 22 | topk: 10 # retrieve topk documents. 23 | retrieve_score_threshold: 0.7 # similarity score under this threshold will not be used in prompt. 24 | vector_db_path: "" # vector database path, if not exist, use default database/vector_database. 25 | -------------------------------------------------------------------------------- /scripts/demo/run_demo.sh: -------------------------------------------------------------------------------- 1 | ollama serve > ollama_serve.log 2>&1 & 2 | python demo.py -------------------------------------------------------------------------------- /src/maps.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: maps.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | # ============================================================================================================= 26 | 27 | LLM_MODEL_DICT = { 28 | "mistral-7b-v0.1": "mistralai/Mistral-7B-v0.1", 29 | "mistral-7b-instruct-v0.1": "mistralai/Mistral-7B-Instruct-v0.1", 30 | "gemma-7b": "google/gemma-7b", 31 | "gemma-7b-it": "google/gemma-7b-it", 32 | "mistral-7b-finetuned": "OpenSI/cognitive_AI_chess" 33 | } 34 | 35 | # ============================================================================================================= 36 | 37 | LLM_INSTANCE_DICT = { 38 | "mistral-7b-v0.1": "Mistral7bv01", 39 | "mistral-7b-instruct-v0.1": "Mistral7bInstructv01", 40 | "gemma-7b": "Gemma7b", 41 | "gemma-7b-it": "Gemma7bIt", 42 | "mistral-7b-finetuned": "MistralFinetuned", 43 | "gpt": "GPT", 44 | "ollama": "GPT" 45 | } -------------------------------------------------------------------------------- /src/query_analyser/user_prompt.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: user_prompt.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | import os, sys 26 | 27 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../..") 28 | 29 | from src.services.llms.prompts.user_prompt import UserPromptBase 30 | 31 | # ============================================================================================================= 32 | 33 | class QueryAnalyserService(UserPromptBase): 34 | def __init__( 35 | self, 36 | services: dict, 37 | **kwargs 38 | ): 39 | """Initialize the instance. 40 | 41 | Args: 42 | services (dict): a dictionary of services. 43 | """ 44 | super().__init__(**kwargs) 45 | 46 | # Set services. 47 | self.services = services 48 | self.num_services = len(self.services) 49 | 50 | # Get the service string and option string for user prompt. 51 | service_string = "" 52 | option_string = "" 53 | 54 | # Get strings for user prompt. 55 | for idx, service_tag in enumerate(self.services): 56 | service = self.services[service_tag] 57 | service_string += f"service {service_tag}: {service}" 58 | option_string += f"service {service_tag}" 59 | 60 | if idx < self.num_services - 1: 61 | service_string += ", " 62 | option_string += " or " 63 | 64 | # Set as global variables. 65 | self.service_string = service_string 66 | self.option_string = option_string 67 | 68 | def __call__( 69 | self, 70 | question: str, 71 | context: dict={} 72 | ): 73 | """Build user prompt to analyse the question. 74 | 75 | Args: 76 | question (str): the question. 77 | context (dict): context, not used but reserve for interface uniform. Default to "". 78 | 79 | Returns: 80 | user_prompt (str): question with instruction. 81 | """ 82 | user_prompt = f"Given {self.num_services} services: '{self.service_string}'," \ 83 | f" which service can answer the following query? The query is '{question}'." \ 84 | f" For instance, if the query is to predict the next chess move, then select service 0;"\ 85 | f" otherwise, if the query is to generate or modify a code, then select service 2." \ 86 | f" Just return which service without any explainations." 87 | 88 | return user_prompt 89 | 90 | # ============================================================================================================= 91 | 92 | class QueryAnalyserSystemInfo(QueryAnalyserService): 93 | def __init__( 94 | self, 95 | *args, 96 | **kwargs 97 | ): 98 | """Initialize the instance. 99 | """ 100 | super().__init__(*args, **kwargs) 101 | 102 | # Get the service string and option string for user prompt. 103 | service_string = "" 104 | 105 | # Get a string of services for user prompt. 106 | for idx, service_tag in enumerate(self.services): 107 | service = self.services[service_tag] 108 | service_string += f"{service}" 109 | 110 | if idx < self.num_services - 1: 111 | service_string += ", " 112 | 113 | # Replace self.service_string. 114 | self.service_string = service_string 115 | 116 | # Get system information. 117 | self.system_information = self.get_system_information() 118 | 119 | def get_system_information(self): 120 | """Get system information. 121 | 122 | Returns: 123 | system_information (str): system information. 124 | """ 125 | system_information = \ 126 | f"My name is OpenSI-CoSMIC." \ 127 | f" I am an AI system." \ 128 | f" OpenSI-CoSMIC stands for the Open Source" \ 129 | f" Institute-Cognitive System of Machine Intelligent Computing." \ 130 | f" I am created, developed, and maintained by OpenSI," \ 131 | f" which is an institute at the University of Canberra." \ 132 | f" At the moment, I can provide {len(self.services)} services," \ 133 | f" including {self.service_string}." \ 134 | f" I can design and provide more services under an agreement." \ 135 | f" To request more services, please find the contact information in my profile." \ 136 | f" My profile and project repository can be found at" \ 137 | f" ." \ 138 | f" You take my role." 139 | 140 | return system_information 141 | 142 | def __call__( 143 | self, 144 | question: str, 145 | context: dict={} 146 | ): 147 | """Build user prompt to analyse the question. 148 | 149 | Args: 150 | question (str): the question. 151 | context (dict): context, not used but reserve for interface uniform. Default to "". 152 | 153 | Returns: 154 | user_prompt (str): question with instruction. 155 | """ 156 | # user_prompt = f"Given that '{self.system_information}'," \ 157 | # f" is the question '{question}' a general question related to the system" \ 158 | # f" information or OpenSI-CoSMIC?" \ 159 | # f" Just answer yes or no without any explainations." 160 | 161 | user_prompt = f"A user has asked the following question - '{question}', " \ 162 | f"is the user asking information about you (the AI assistant called OpenSI-CoSMIC) or " \ 163 | f"requesting information about how you work/what you can do? " \ 164 | f"Answer only 'YES' or 'NO' without any explanations." 165 | 166 | return user_prompt -------------------------------------------------------------------------------- /src/services/base.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: base.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # Muntasir Adnan 7 | # 8 | # Copyright (c) 2024 Open Source Institute 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 11 | # documentation files (the "Software"), to deal in the Software without restriction, including without 12 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 14 | # conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all copies or substantial 17 | # portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 20 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------------------------------------- 25 | 26 | import os 27 | 28 | # ============================================================================================================= 29 | 30 | class ServiceBase: 31 | def __init__( 32 | self, 33 | log_file: str=None, 34 | ): 35 | """Base class for the services in OpenSI-CoSMIC. 36 | 37 | Args: 38 | log_file (str, optional): (relative) log file path for storing printed information. 39 | Defaults to None. 40 | """ 41 | # Set log file path. 42 | self.log_file = log_file 43 | 44 | # Get the root of the current file to set log file path as absolute path if it is a relative path. 45 | current_dir = os.path.dirname(os.path.abspath(__file__)) 46 | self.root = f"{current_dir}/../.." 47 | 48 | def set_log_file( 49 | self, 50 | log_file: str 51 | ): 52 | """Set log file externally. 53 | 54 | Args: 55 | log_file (str): (relative) log file path. 56 | """ 57 | self.log_file = log_file -------------------------------------------------------------------------------- /src/services/llms/Ollama.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: OllamaPullManager.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Muntasir Adnan 6 | # 7 | # Copyright (c) 2025 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | import os, sys 25 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../../..") 26 | 27 | import ollama 28 | 29 | from typing import List, Dict, Any, Union 30 | from ollama import Client 31 | 32 | from src.services.llms.llm import LLMBase 33 | from src.services.llms.OllamaPullManager import OllamaPullManager 34 | 35 | class Ollama(LLMBase): 36 | def __init__(self, 37 | llm_name: str = "llama3.2", 38 | container_name: str = "ollama", 39 | local_port: int = 11434, 40 | **kwargs) -> None: 41 | """ 42 | LLMs using the official Ollama container. 43 | 44 | Args: 45 | llm_name (str, optional): Ollama supported LLMs available at https://ollama.com/library. 46 | container_name (str, optional): Name of the Ollama container. Defaults to "ollama". 47 | local_port (int, optional): Local port for the ollama container. Defaults to 11434. 48 | """ 49 | model_name = llm_name.replace("ollama:", "") 50 | super().__init__(llm_name=model_name, **kwargs) 51 | self._tag_model() # adds :latest if not present 52 | self.ollama_client = self._set_local_client(container_name, local_port) # local client instance 53 | self.ollama_pull_manager = OllamaPullManager( 54 | model_name = self.llm_name, 55 | mode = "stochastic", 56 | interventions = [85, 95], 57 | max_retries = 3, 58 | fall_back_interval= 60, 59 | ollama_client = self.ollama_client 60 | ) 61 | self._check_availability() 62 | 63 | 64 | def _tag_model(self) -> None: 65 | if ":" not in self.llm_name: 66 | self.llm_name = f"{self.llm_name}:latest" 67 | 68 | 69 | def _set_local_client(self, 70 | container_name: str, 71 | port: int) -> Client: 72 | """ 73 | Set the local client for the Ollama container. 74 | 75 | Args: 76 | container_name (str): Name of the Ollama container. 77 | """ 78 | client = ollama.Client( 79 | host = f"http://{container_name}:{port}", 80 | headers = {"Content-Type": "application/json"} 81 | ) 82 | return client 83 | 84 | 85 | def _check_availability(self) -> None: 86 | """ 87 | Check if the Ollama container is available and the specified model is available. 88 | Raises an exception if the container or model is not available. 89 | """ 90 | self.ollama_pull_manager.pull_model() 91 | 92 | 93 | def __call__(self, 94 | question: str, 95 | context: Union[str, Dict[str, Any]] = {}) -> tuple[str, str]: 96 | """ 97 | Process the question and generate a response using Ollama. 98 | 99 | Args: 100 | question (str): User question in string. 101 | context (Union[str, Dict[str, Any]], optional): Context for the question. Defaults to {}. 102 | 103 | Returns: 104 | Tuple of (response, raw_response) 105 | """ 106 | # Generate user prompt with question and context 107 | user_prompt: str = self.user_prompter(question, context=context) 108 | 109 | # Combine system prompt with user prompt 110 | combined_prompt: list[dict] = self.system_prompter(user_prompt, context=context) 111 | 112 | # Chat 113 | chat_response = self.ollama_client.chat( 114 | model = self.llm_name, 115 | messages = combined_prompt, 116 | ) 117 | raw_response = chat_response["message"]["content"] 118 | 119 | # Apply truncation if enabled 120 | response = self.truncate_response(raw_response) \ 121 | if self.is_truncate_response \ 122 | else raw_response 123 | 124 | return response, raw_response 125 | 126 | 127 | def quit(self) -> None: 128 | """ 129 | Clean up any resources. No specific cleanup needed for API-based implementation. 130 | """ 131 | pass # No resources to clean up for REST API implementation 132 | 133 | # if __name__ == "__main__": 134 | # ollama_instance = OllamaContainer(container_name = "localhost") 135 | # response, raw_respose = ollama_instance.__call__("what is the capital of greece?") 136 | # print("Response:", response) 137 | # print("Raw Response:", raw_respose) -------------------------------------------------------------------------------- /src/services/llms/login.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: login.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | import torch, os, sys 26 | 27 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../../..") 28 | 29 | from huggingface_hub import login 30 | from src.maps import LLM_MODEL_DICT 31 | from dotenv import load_dotenv 32 | 33 | # ============================================================================================================= 34 | 35 | class LLMLogin: 36 | def __init__( 37 | self, 38 | llm_name 39 | ): 40 | """Login LLM. 41 | 42 | Args: 43 | model (str, optional): model name. Defaults to "base". 44 | """ 45 | # Set config. 46 | current_dir = os.path.dirname(os.path.abspath(__file__)) 47 | self.root = f"{current_dir}/../../.." 48 | self.llm_name = llm_name 49 | 50 | def login(self): 51 | """Login huggingface if no local model found. 52 | """ 53 | cache_model_name = "models--" + LLM_MODEL_DICT[self.llm_name].replace("/", "--") 54 | cache_model_directory = os.path.join(os.path.expanduser("~"), ".cache/huggingface/hub") 55 | cache_model_path = os.path.join(cache_model_directory, cache_model_name) 56 | 57 | if not os.path.exists(cache_model_path): 58 | # Set the token stored file. 59 | load_dotenv(f"{self.root}/.env") 60 | 61 | # Required token for huggingface login. 62 | if self.llm_name.find("finetune") > -1: 63 | login(os.getenv("hf_token_finetune"), add_to_git_credential=True) 64 | else: 65 | login(os.getenv("hf_token"), add_to_git_credential=True) -------------------------------------------------------------------------------- /src/services/rag.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: rag.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # Muntasir Adnan 7 | # 8 | # Copyright (c) 2024 Open Source Institute 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 11 | # documentation files (the "Software"), to deal in the Software without restriction, including without 12 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 14 | # conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all copies or substantial 17 | # portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 20 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------------------------------------- 25 | 26 | import os, sys 27 | 28 | sys.path.append(f"{os.path.dirname(os.path.abspath(__file__))}/../..") 29 | 30 | from src.services.base import ServiceBase 31 | from src.services.vector_database import VectorDatabase 32 | 33 | # ============================================================================================================= 34 | 35 | class RAGBase(ServiceBase): 36 | def __init__( 37 | self, 38 | vector_database: VectorDatabase, 39 | retrieve_score_threshold: float=0.7, 40 | topk: int=5, 41 | **kwargs 42 | ): 43 | """Context retriever service. 44 | 45 | Args: 46 | vector_database (VectorDatabase): vector database. 47 | retrieve_score_threshold (float, optional): retrieve score threshold to filter out retrieved 48 | context with similarity under this threshold. Defaults to 0.7. 49 | topk (int, optional): up to topk retrieved context returned. Defaults to 5. 50 | """ 51 | super().__init__(**kwargs) 52 | 53 | # Set config. 54 | self.retrieve_score_threshold = retrieve_score_threshold 55 | self.topk = topk 56 | self.vector_database = vector_database 57 | 58 | def set_vector_database( 59 | self, 60 | vector_database: VectorDatabase 61 | ): 62 | """Set the vector database externally on demand. 63 | 64 | Args: 65 | vector_database (VectorDatabase): an external vector database. 66 | """ 67 | self.vector_database = vector_database 68 | 69 | def set_retrieve_score_threshold( 70 | self, 71 | retrieve_score_threshold: float 72 | ): 73 | """Change the retrieve score externally on demand. 74 | 75 | Args: 76 | retrieve_score_threshold (float): an external threshold. 77 | """ 78 | self.retrieve_score_threshold = retrieve_score_threshold 79 | 80 | def set_topk( 81 | self, 82 | topk: int 83 | ): 84 | """Change the topk externally on demand. 85 | 86 | Args: 87 | topk (int): topk documents to be retrieved. 88 | """ 89 | self.topk = topk 90 | 91 | def __call__( 92 | self, 93 | user_prompt: str 94 | ): 95 | """Retrieve context for a given user prompt. 96 | 97 | Args: 98 | user_prompt (str): a question from the user. 99 | 100 | Returns: 101 | context (str): retrieved context from the vector database. 102 | retrieved_doc_score: score of the retrieved context. 103 | """ 104 | # Find the topk relevant tokens. 105 | retrieved_contents = self.vector_database.similarity_search_with_relevance_scores( 106 | query=user_prompt, 107 | k=self.topk 108 | ) 109 | 110 | # Store the retrieved page contents and page scores. 111 | retrieved_context = [] 112 | retrieved_context_score = [] 113 | 114 | for doc, score in retrieved_contents: 115 | # Filter out low confidence context. 116 | if score >= self.retrieve_score_threshold: 117 | retrieved_context.append(doc.page_content) 118 | else: 119 | retrieved_context.append(None) 120 | 121 | # Store all the scores. 122 | retrieved_context_score.append(score) 123 | 124 | if len(retrieved_context) == 0: 125 | context = "" 126 | else: 127 | # Change the linechange to avoid messing up the print and log file. 128 | context = "".join([ 129 | f"Document {str(i)}: " + doc.replace("\n", " ") + ". " \ 130 | for i, doc in enumerate(retrieved_context) if (doc is not None) 131 | ]) 132 | 133 | return context, retrieved_context_score -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | DOCKER_BUILD=false 5 | 6 | show_usage(){ 7 | echo "Usage: $0 [OPTIONS]" 8 | echo "" 9 | echo "Options:" 10 | echo " --help Show this help message" 11 | echo " --docker_build Build the Docker image before starting the services" 12 | echo "" 13 | echo "Examples:" 14 | echo " $0 # Default" 15 | echo " $0 --docker_build # Build Docker image first" 16 | } 17 | 18 | while [[ $# -gt 0 ]]; do 19 | case $1 in 20 | --help|-h) 21 | show_usage 22 | exit 0 23 | ;; 24 | --docker_build) 25 | DOCKER_BUILD=true 26 | shift 27 | ;; 28 | *) echo "Error: Unknown option $1" 29 | show_usage 30 | exit 1 31 | ;; 32 | esac 33 | done 34 | 35 | echo "Configuration:" 36 | echo " Docker build: $DOCKER_BUILD" 37 | echo "" 38 | 39 | # Create volume 40 | echo "Creating Docker volume for PyCapsule..." 41 | docker volume create shared_mount 42 | 43 | # Docker Compose 44 | echo "Starting Docker Compose services..." 45 | if [[ "$DOCKER_BUILD" == true ]]; then 46 | docker compose up --build 47 | else 48 | docker compose up 49 | fi 50 | 51 | exit 0 -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 | # About 8 | 9 | fentoboardimage takes a Fen string representing a Chess position, and renders a PIL image of the resulting position. 10 | 11 | # Examples 12 | 13 | Examples can be found under the `examples` folder in this repository. 14 | Further examples can be found within `tests/test.py` 15 | 16 | ### You can customize: 17 | - the size and color of the board 18 | - piece sprites 19 | - black or white perspective 20 | - Board highlighting for last move 21 | - Arrows 22 | 23 | # Installation 24 | 25 | Install the package using pip 26 | ``` 27 | $ pip install fentoboardimage 28 | ``` 29 | 30 | Then import the fenToImage and loadPiecesFolder functions and use them as follows: 31 | ``` 32 | from fentoboardimage import fenToImage, loadPiecesFolder 33 | 34 | boardImage = fenToImage( 35 | fen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", 36 | squarelength=100, 37 | pieceSet=loadPiecesFolder("./pieces"), 38 | darkColor="#D18B47", 39 | lightColor="#FFCE9E" 40 | ) 41 | ``` 42 | 43 | In order to load a piece set, the pieces must follow this file structure, and must be a .png: 44 | ``` 45 | -piece_set_name 46 | -white 47 | - Knight.png 48 | - Rook.png 49 | - Pawn.png 50 | - Bishop.png 51 | - Queen.png 52 | - King.png 53 | -black 54 | - Knight.png 55 | - Rook.png 56 | - Pawn.png 57 | - Bishop.png 58 | - Queen.png 59 | - King.png 60 | ``` 61 | 62 | 63 | In order to load an arrow set, the images must follow this file structure, and must be a .png: 64 | ``` 65 | - arrow_set_name 66 | - Knight.png 67 | - Up.png 68 | ``` 69 | 70 | - `Knight.png` is a 3:2 aspect ratio .png image containing an arrow pointing from the bottom right square to the top left square in the image. This image is internally rotated to correctly point at the target square from the origin 71 | - `Up.png` is a 1:3 aspect ratio image depicting an upward facing arrow point from the bottom most square to the top most square. This image is internally segmented and used to construct arrows in the ordinate and diagonal direction. 72 | 73 | # Usage 74 | 75 | The `fenToImage` function has these parameters: 76 | 77 | - fen: `str` 78 | 79 | Fen string representing a position 80 | 81 | - squarelength: `int` 82 | 83 | The length of one square on the board. Resulting board will be 8 * squarelength long 84 | 85 | - pieceSet: `loadPiecesFolder` 86 | 87 | the piece set, loaded using the `loadPiecesFolder` function 88 | 89 | - The loadPiecesFolder function has two parameters: 90 | 91 | path: `str` 92 | 93 | Loads piece set located at the path provided. 94 | 95 | cache: `boolean` 96 | 97 | Whether to internally cache the piece pngs to avoid reloading 98 | 99 | - darkColor: `str` 100 | 101 | dark square color on the board 102 | 103 | - lightColor: `str` 104 | 105 | light square color on the board 106 | 107 | - flipped: `boolean` default = False 108 | 109 | Whether to flip to board, and render it from black's perspective 110 | 111 | - ArrowSet: `loadArrowsFolder()` 112 | 113 | the arrow set, loaded using the `loadArrowsFolder` function 114 | 115 | - The loadArrowsFolder function has two parameters: 116 | 117 | - path: `str` 118 | 119 | Loads arrow set located at the path provided. 120 | 121 | - cache: `boolean` 122 | 123 | Whether to internally cache the arrow pngs to avoid reloading 124 | 125 | - Arrows: `list[(str,str)]` 126 | 127 | A list of tuples containing coordinates to place arrows. In the format 128 | of (start, end) using standard chess notation for the squares. 129 | - lastMove: `dict` 130 | 131 | A dictionary containing the fields `before`, `after`, `darkColor` and `lightColor`. 132 | `before` and `after` using standard chess notation for the squares, and `darkColor` 133 | and `lightColor` should be hex strings. 134 | 135 | - coordinates: `dict` 136 | 137 | A dictionary containing the fields "font", "size", "darkColor", "lightColor", "positionFn", 138 | "padding", and "outsideBoardColor" 139 | 140 | - font: `loadFontFile()` 141 | 142 | The font file to use for coordinates, load using the loadFontFile function, with the 143 | file path to the ttf file or bitmap font file as its sole argument. 144 | - size: int 145 | 146 | The font size for the coordinate 147 | - darkColor: `str` 148 | 149 | The color of the coordinate for dark squares 150 | - lightColor: `str` 151 | 152 | The color of the coordinate for light squares 153 | - posititionFn: `CoordinatePositionFn["outBorder"]` | `CoordinatePositionFn["innerBorder"]` | `CoordinatePositionFn["everySquare"]` | `function` 154 | 155 | The function used to determine what characters to draw and where for each square 156 | on the board. Can either be one of the three predefined functions from the 157 | CoordinatePositionFn dict, or a custom function. See the definitions for the 158 | builtin functions in "fentoboardimage/Coordinates.py" for examples to follow when 159 | writing a custom position fn. 160 | - padding: `int` 161 | 162 | The padding between the square's edge and the resulting placement 163 | of the coordinate character 164 | - outsideBorderColor: `str` optional 165 | 166 | What color to paint the background if the coordinates end up outside the board 167 | 168 | 169 | - highlighting: `dict` 170 | 171 | A dictionary of highlighting color => squares to highlight. The keys of this object have 172 | are either a hex color, or a tuple of (light_square_color, dark_square_color). The values 173 | of the dictionary must be a list of square coordinates. A hex color key will apply the same 174 | color to every listed square, while a tuple key will conditionally apply either light_square_color 175 | or dark_square_color depending on if the coordinate is a light or dark square. 176 | 177 | Example: 178 | 179 | highlighting={ 180 | ("#ff0000", "#702963"): ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8"], 181 | ("#00ff00", "#2e7d32"): ["b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8"], 182 | "#0000ff": ["c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"] 183 | } 184 | 185 | 186 | 187 | 188 | # Dependencies 189 | - [Pillow](https://pypi.org/project/Pillow/) 190 | 191 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/documentation/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/documentation/logo.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/arrows/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/arrows/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/arrows/Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/arrows/Up.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/black/Bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/black/Bishop.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/black/King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/black/King.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/black/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/black/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/black/Pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/black/Pawn.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/black/Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/black/Queen.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/black/Rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/black/Rook.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/white/Bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/white/Bishop.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/white/King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/white/King.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/white/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/white/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/white/Pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/white/Pawn.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/white/Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/white/Queen.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/pieces/white/Rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/examples/pieces/white/Rook.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/render_board.py: -------------------------------------------------------------------------------- 1 | from fentoboardimage import fenToImage, loadPiecesFolder 2 | 3 | board = fenToImage( 4 | fen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", 5 | squarelength=200, 6 | pieceSet=loadPiecesFolder("pieces"), 7 | darkColor="#79a65d", 8 | lightColor="#daf2cb" 9 | ) 10 | 11 | board.show() 12 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/render_board_arrows.py: -------------------------------------------------------------------------------- 1 | from fentoboardimage import fenToImage, loadPiecesFolder, loadArrowsFolder 2 | 3 | board = fenToImage( 4 | fen="rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", 5 | squarelength=200, 6 | pieceSet=loadPiecesFolder("pieces"), 7 | ArrowSet=loadArrowsFolder("arrows"), 8 | darkColor="#79a65d", 9 | lightColor="#daf2cb", 10 | Arrows=[ 11 | ["a1", "a8"], 12 | ["b1", "d2"] 13 | ] 14 | ) 15 | 16 | board.show() 17 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/render_board_coordinates.py: -------------------------------------------------------------------------------- 1 | from fentoboardimage import fenToImage, loadPiecesFolder, loadFontFile, CoordinatePositionFn 2 | 3 | image1 = fenToImage( 4 | fen="8/5N2/4p2p/5p1k/1p4rP/1P2Q1P1/P4P1K/5q2 w - - 15 44", 5 | squarelength=125, 6 | pieceSet=loadPiecesFolder( 7 | "./pieces"), 8 | darkColor="#79a65d", 9 | lightColor="#daf2cb", 10 | coordinates={ 11 | "font": loadFontFile("./fonts/Roboto-Bold.ttf"), 12 | "size": 28, 13 | "darkColor": "#daf2cb", 14 | "lightColor": "#79a65d", 15 | "positionFn": CoordinatePositionFn["outerBorder"], 16 | "padding": 15, 17 | "outsideBoardColor": "#000000" 18 | } 19 | ) 20 | 21 | image1.show() 22 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/examples/requirements.txt: -------------------------------------------------------------------------------- 1 | fentoboardimage==1.2.0 2 | Pillow==9.5.0 3 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/fentoboardimage/Arrows.py: -------------------------------------------------------------------------------- 1 | import math 2 | from PIL import Image 3 | 4 | 5 | def _generateArrow(arrow, length, pieceSize): 6 | image = arrow 7 | resized = Image.new("RGBA", (pieceSize, int(pieceSize*length))) 8 | head = image.crop((0, 0, pieceSize, pieceSize)).convert("RGBA") 9 | tail = image.crop((0, pieceSize*2, pieceSize, 10 | pieceSize*3)).convert("RGBA") 11 | 12 | body = image.crop( 13 | (0, pieceSize, pieceSize, pieceSize*2)).convert("RGBA") 14 | resized.paste(head) 15 | resized.paste(tail, (0, int(pieceSize * (length - 1)))) 16 | if length > 2: 17 | body = body.resize((pieceSize, int(pieceSize * (length - 2)))) 18 | resized.paste(body, (0, pieceSize)) 19 | return resized 20 | 21 | # TODO Separate the different arrow types into their own functions 22 | 23 | 24 | def paintAllArrows(board, arrowConfiguration, arrowSet): 25 | height, width = board.size 26 | pieceSize = int(width/8) 27 | def position(val): return int(val * pieceSize) 28 | for arrow in arrowConfiguration: 29 | start = arrow[0] 30 | end = arrow[1] 31 | delta = (end[0] - start[0], end[1] - start[1]) 32 | start_x = position(start[0]) 33 | start_y = position(start[1]) 34 | target_x = position(end[0]) 35 | target_y = position(end[1]) 36 | if delta == (-2, 1): 37 | image = arrowSet["one"].transpose(Image.FLIP_TOP_BOTTOM) 38 | Image.Image.alpha_composite(board, image, (target_x, start_y)) 39 | elif delta == (-1, 2): 40 | image = arrowSet["one"].transpose(Image.ROTATE_270).transpose( 41 | Image.FLIP_LEFT_RIGHT).transpose(Image.FLIP_TOP_BOTTOM) 42 | Image.Image.alpha_composite(board, image, (target_x, start_y)) 43 | elif delta == (1, 2): 44 | image = arrowSet["one"].transpose(Image.ROTATE_270).transpose( 45 | Image.FLIP_LEFT_RIGHT).transpose(Image.ROTATE_180) 46 | Image.Image.alpha_composite(board, image, (start_x, start_y)) 47 | elif delta == (2, 1): 48 | image = arrowSet["one"].transpose(Image.ROTATE_180) 49 | Image.Image.alpha_composite(board, image, (start_x, start_y)) 50 | elif delta == (2, -1): 51 | image = arrowSet["one"].transpose(Image.FLIP_LEFT_RIGHT) 52 | Image.Image.alpha_composite(board, image, (start_x, target_y)) 53 | elif delta == (1, -2): 54 | image = arrowSet["one"].transpose(Image.ROTATE_270).transpose( 55 | Image.FLIP_LEFT_RIGHT).transpose(Image.FLIP_LEFT_RIGHT) 56 | Image.Image.alpha_composite(board, image, (start_x, target_y)) 57 | elif delta == (-1, -2): 58 | image = arrowSet["one"].transpose( 59 | Image.ROTATE_270).transpose(Image.FLIP_LEFT_RIGHT) 60 | Image.Image.alpha_composite(board, image, (target_x, target_y)) 61 | elif delta == (-2, -1): 62 | image = arrowSet["one"] 63 | Image.Image.alpha_composite(board, image, (target_x, target_y)) 64 | elif delta[0] == 0: 65 | image = _generateArrow( 66 | arrowSet["up"], abs(delta[1]) + 1, pieceSize) 67 | if delta[1] > 0: 68 | image = image.transpose(Image.ROTATE_180) 69 | Image.Image.alpha_composite(board, image, (start_x, start_y)) 70 | else: 71 | Image.Image.alpha_composite(board, image, (target_x, target_y)) 72 | elif delta[1] == 0: 73 | image = _generateArrow(arrowSet["up"], abs( 74 | delta[0]) + 1, pieceSize).transpose(Image.ROTATE_270) 75 | if delta[0] < 0: 76 | image = image.transpose(Image.ROTATE_180) 77 | Image.Image.alpha_composite(board, image, (target_x, target_y)) 78 | else: 79 | Image.Image.alpha_composite(board, image, (start_x, start_y)) 80 | elif abs(delta[0]) == abs(delta[1]): 81 | arrow = _generateArrow(arrowSet["up"], (math.sqrt( 82 | (abs(delta[0]) + 0.5)**2 + (abs(delta[1]) + 0.5)**2)), pieceSize).rotate(45, expand=True) 83 | if delta[0] > 0 and delta[1] > 0: 84 | arrow = arrow.transpose(Image.ROTATE_180) 85 | Image.Image.alpha_composite(board, arrow, (start_x, start_y)) 86 | elif delta[0] > 0 and delta[1] < 0: 87 | arrow = arrow.transpose(Image.ROTATE_270) 88 | Image.Image.alpha_composite(board, arrow, (start_x, target_y)) 89 | elif delta[0] < 0 and delta[1] > 0: 90 | arrow = arrow.transpose(Image.ROTATE_90) 91 | Image.Image.alpha_composite(board, arrow, (target_x, start_y)) 92 | elif delta[0] < 0 and delta[1] < 0: 93 | Image.Image.alpha_composite(board, arrow, (target_x, target_y)) 94 | 95 | else: 96 | raise ValueError("Invalid arrow target: start(" + 97 | str(start) + ") end(" + str(end) + ")") 98 | return board 99 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/fentoboardimage/Checkerboard.py: -------------------------------------------------------------------------------- 1 | from PIL import ImageDraw 2 | 3 | 4 | def paintCheckerBoard(board, darkColor, lastMove=None, highlighting=None): 5 | height, width = board.size 6 | draw = ImageDraw.Draw(board) 7 | if height != width: 8 | # Require a square board, any stretching / transformations 9 | # should be handled afterwards through PIL 10 | raise Exception("Height unequal to width") 11 | 12 | def getRectanglePositionTuples(tup): 13 | return (((tup[0] + startSquareOffset) * squareSize, tup[1] * squareSize), 14 | ((tup[0] + startSquareOffset) * squareSize + squareSize - 1, tup[1] * squareSize + squareSize - 1)) 15 | 16 | def isLightSquare(tup): 17 | if tup[0] % 2 == 0: 18 | if tup[1] % 2 == 0: 19 | return True 20 | return False 21 | else: 22 | if tup[1] % 2 == 0: 23 | return False 24 | return True 25 | for y in range(0, 8): 26 | for x in range(0, 8, 2): 27 | # Four pairs of dark then light must be painted per row 28 | 29 | squareSize: int = width/8 30 | 31 | firstIsColored = y % 2 == 0 32 | # If the first square is colored, offset 33 | # the pattern of dark then light by one 34 | startSquareOffset = 1 if firstIsColored else 0 35 | draw.rectangle(getRectanglePositionTuples((x, y)), darkColor) 36 | if lastMove != None: 37 | beforeColor: str = lastMove["darkColor"] 38 | afterColor: str = lastMove["darkColor"] 39 | if isLightSquare(lastMove["before"]): 40 | beforeColor = lastMove["lightColor"] 41 | if isLightSquare(lastMove["after"]): 42 | afterColor = lastMove["lightColor"] 43 | draw.rectangle(getRectanglePositionTuples( 44 | lastMove["before"]), beforeColor) 45 | draw.rectangle(getRectanglePositionTuples( 46 | lastMove["after"]), afterColor) 47 | if highlighting != None: 48 | for color_pair_or_color in highlighting: 49 | color_pair = color_pair_or_color 50 | if type(color_pair_or_color) == str: 51 | color_pair = (color_pair_or_color, color_pair_or_color) 52 | squares = highlighting[color_pair_or_color] 53 | for square in squares: 54 | draw.rectangle(getRectanglePositionTuples( 55 | square),color_pair[0] if isLightSquare(square) else color_pair[1]) 56 | return board 57 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/fentoboardimage/Coordinates.py: -------------------------------------------------------------------------------- 1 | from PIL import ImageDraw 2 | from PIL import Image 3 | import math 4 | from .Utils import flippedCheck, indicesToSquare 5 | 6 | 7 | def get_size(font, s): 8 | left, top, right, bottom = font.getbbox(s) 9 | width, height = right - left, bottom 10 | return width, height 11 | 12 | 13 | def OuterBorderFn(coordinate, squareOrigin, squarelength, font, flipped, padding): 14 | collection = [] 15 | padding = padding if padding != None else 0 16 | 17 | if flippedCheck(flipped, coordinate[0], "a", "h"): 18 | width, height = get_size(font, coordinate[1]) 19 | collection.append({ 20 | "coordinate": (squareOrigin[0] - padding - width, squareOrigin[1] + squarelength/2 - height/2), 21 | "text": coordinate[1] 22 | }) 23 | if flippedCheck(flipped, coordinate[0], "h", "a"): 24 | width, height = get_size(font, coordinate[1]) 25 | collection.append({ 26 | "coordinate": (squareOrigin[0] + padding + squarelength, squareOrigin[1] + squarelength/2 - height/2), 27 | "text": coordinate[1]}) 28 | if flippedCheck(flipped, coordinate[1], "1", "8"): 29 | width, height = get_size(font, coordinate[0]) 30 | collection.append({ 31 | "coordinate": (squareOrigin[0] + squarelength/2 - width/2, squareOrigin[1] + squarelength + padding), 32 | "text": coordinate[0] 33 | }) 34 | if flippedCheck(flipped, coordinate[1], "8", "1"): 35 | width, height = get_size(font, coordinate[0]) 36 | collection.append({ 37 | "coordinate": (squareOrigin[0] + squarelength/2 - width/2, squareOrigin[1] - height - padding), 38 | "text": coordinate[0] 39 | }) 40 | return collection 41 | 42 | 43 | def InnerBorderFn(coordinate, squareOrigin, squarelength, font, flipped, padding): 44 | collection = [] 45 | padding = padding if padding != None else squarelength/20 46 | if flippedCheck(flipped, coordinate[0], "a", "h"): 47 | collection.append({ 48 | "coordinate": (squareOrigin[0] + padding, squareOrigin[1] + padding), 49 | "text": coordinate[1] 50 | }) 51 | if flippedCheck(flipped, coordinate[1], "1", "8"): 52 | width, height = get_size(font, coordinate[0]) 53 | collection.append({ 54 | "coordinate": (squareOrigin[0] + squarelength - width - padding, squareOrigin[1] + squarelength - height - padding), 55 | "text": coordinate[0] 56 | }) 57 | return collection 58 | 59 | 60 | def EverySquare(coordinate, squareOrigin, squarelength, font, flipped, padding): 61 | width, height = get_size(font, coordinate[0]) 62 | padding = padding if padding != None else squarelength/20 63 | collection = [] 64 | collection.append({ 65 | "coordinate": (squareOrigin[0] + padding, squareOrigin[1] + padding), 66 | "text": coordinate[1] 67 | }) 68 | collection.append({ 69 | "coordinate": (squareOrigin[0] + squarelength - width - padding, squareOrigin[1] + squarelength - height - padding), 70 | "text": coordinate[0] 71 | }) 72 | return collection 73 | 74 | 75 | CoordinatePositionFn = { 76 | "outerBorder": OuterBorderFn, 77 | "innerBorder": InnerBorderFn, 78 | "everySquare": EverySquare 79 | } 80 | 81 | 82 | def paintCoordinateOverlay(board, coordinates, squarelength, flipped): 83 | draw = ImageDraw.Draw(board) 84 | size = 1 if coordinates["size"] == None else coordinates["size"] 85 | font = coordinates["font"](size) 86 | padding = coordinates["padding"] 87 | dark = True 88 | offset = ( 89 | 0, 0) if "offset" not in coordinates else coordinates["offset"] 90 | textObjects = [] 91 | maxX, minX, maxY, minY = squarelength * 8, 0, squarelength * 8, 0 92 | for x in range(0, 8): 93 | for y in range(0, 8): 94 | coordStr = indicesToSquare((x, y), flipped) 95 | locations = coordinates["positionFn"]( 96 | coordStr, (x * squarelength + offset[0], y * squarelength + offset[1]), squarelength, font, flipped, padding) 97 | dark = not dark 98 | if locations != None: 99 | for text in locations: 100 | textObjects.append({ 101 | "position": text["coordinate"], 102 | "text": text["text"], 103 | "fill": coordinates["darkColor" if dark else "lightColor"] 104 | }) 105 | width, height = get_size(font, text["text"]) 106 | maxX = max(maxX, text["coordinate"][0] + width) 107 | minX = min(minX, text["coordinate"][0]) 108 | maxY = max(maxY, text["coordinate"][1] + height) 109 | minY = min(minY, text["coordinate"][1]) 110 | dark = not dark 111 | paintOffset = (math.ceil(abs(minX)), math.ceil(abs(minY))) 112 | coordOverlayWidth, coordOverlayHeight = ( 113 | math.ceil(maxX + paintOffset[0]), math.ceil(maxY + paintOffset[1])) 114 | coordOverlay = None 115 | if "outsideBoardColor" in coordinates: 116 | coordOverlay = Image.new( 117 | "RGBA", (coordOverlayWidth, coordOverlayHeight), coordinates["outsideBoardColor"]) 118 | else: 119 | coordOverlay = Image.new( 120 | "RGBA", (coordOverlayWidth, coordOverlayHeight)) 121 | coordOverlay.paste(board, paintOffset) 122 | draw = ImageDraw.Draw(coordOverlay) 123 | 124 | for text in textObjects: 125 | draw.text((text["position"][0] + paintOffset[0], text["position"][1] + paintOffset[1]), 126 | text["text"], font=font, fill=text["fill"]) 127 | return coordOverlay, paintOffset 128 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/fentoboardimage/FenParser.py: -------------------------------------------------------------------------------- 1 | # https://github.com/tlehman/fenparser 2 | from unittest import TestCase 3 | from itertools import chain 4 | import re 5 | 6 | 7 | class FenParser(): 8 | def __init__(self, fen_str): 9 | self.fen_str: str = fen_str 10 | 11 | def parse(self): 12 | ranks = self.fen_str.split(" ")[0].split("/") 13 | pieces_on_all_ranks = [self.parse_rank(rank) for rank in ranks] 14 | return pieces_on_all_ranks 15 | 16 | def parse_rank(self, rank): 17 | rank_re = re.compile("(\d|[kqbnrpKQBNRP])") 18 | piece_tokens = rank_re.findall(rank) 19 | pieces = self.flatten(map(self.expand_or_noop, piece_tokens)) 20 | return pieces 21 | 22 | def flatten(self, lst): 23 | return list(chain(*lst)) 24 | 25 | def expand_or_noop(self, piece_str): 26 | piece_re = re.compile("([kqbnrpKQBNRP])") 27 | retval = "" 28 | if piece_re.match(piece_str): 29 | retval = piece_str 30 | else: 31 | retval = self.expand(piece_str) 32 | return retval 33 | 34 | def expand(self, num_str): 35 | return int(num_str)*" " 36 | 37 | 38 | class FenParserTest(TestCase): 39 | def test_parse_rank(self): 40 | start_pos = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" 41 | rank8 = "rnbqkbnr" 42 | rank7 = "pppppppp" 43 | rank6 = "8" 44 | fp = FenParser(start_pos) 45 | assert fp.parse_rank(rank8) == ["r", "n", "b", "q", "k", "b", "n", "r"] 46 | assert fp.parse_rank(rank7) == ["p", "p", "p", "p", "p", "p", "p", "p"] 47 | assert fp.parse_rank(rank6) == [" ", " ", " ", " ", " ", " ", " ", " "] 48 | 49 | def test_parse_starting_position(self): 50 | start_pos = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" 51 | fp = FenParser(start_pos) 52 | print(fp.parse()) 53 | assert len(fp.parse()) == 8 54 | assert fp.parse() == [["r", "n", "b", "q", "k", "b", "n", "r"], 55 | ["p", "p", "p", "p", "p", "p", "p", "p"], 56 | [" ", " ", " ", " ", " ", " ", " ", " "], 57 | [" ", " ", " ", " ", " ", " ", " ", " "], 58 | [" ", " ", " ", " ", " ", " ", " ", " "], 59 | [" ", " ", " ", " ", " ", " ", " ", " "], 60 | ["P", "P", "P", "P", "P", "P", "P", "P"], 61 | ["R", "N", "B", "Q", "K", "B", "N", "R"]] 62 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/fentoboardimage/Pieces.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | 3 | 4 | def paintPiece(board, cord, image): 5 | height, width = board.size 6 | pieceSize = int(width/8) 7 | x = cord[0] 8 | y = cord[1] 9 | def position(val): return int(val * pieceSize) 10 | box = (position(x), position(y)) 11 | 12 | # Extract the alpha layer to use as a mask 13 | # when pasting, to not overwrite the board 14 | _, _, _, alpha = image.split() 15 | Image.Image.alpha_composite(board, image, box) 16 | 17 | return board 18 | 19 | 20 | def paintAllPieces(board, parsed, pieceImages): 21 | for y in range(0, len(parsed)): 22 | for x in range(0, len(parsed[y])): 23 | piece = parsed[y][x] 24 | if piece != " ": 25 | board = paintPiece( 26 | board, (x, y), pieceImages[piece]) 27 | return board 28 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/fentoboardimage/Utils.py: -------------------------------------------------------------------------------- 1 | def indicesToSquare(indices, flipped=False): 2 | if flipped: 3 | return f"{chr((7 - indices[0]) + 97)}{ indices[1] + 1}" 4 | return f"{chr(indices[0] + 97)}{ 7 - indices[1] + 1}" 5 | 6 | 7 | def squareToIndices(square): 8 | """ 9 | Converts a square string to a tuple of indices 10 | """ 11 | return (ord(square[0]) - 97, 8 - int(square[1])) 12 | 13 | 14 | def flipCoordTuple(coord): 15 | """ 16 | Flips a tuple of coordinates 17 | """ 18 | return (7 - coord[0], 7 - coord[1]) 19 | 20 | 21 | def flippedCheck(flipped, checkChar, c1, c2): 22 | if not flipped and checkChar == c1: 23 | return True 24 | if flipped and checkChar == c2: 25 | return True 26 | return False 27 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/fentoboardimage/__init__.py: -------------------------------------------------------------------------------- 1 | from .main import * 2 | from . import main -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "pillow" 3 | version = "9.0.1" 4 | description = "Python Imaging Library (Fork)" 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.7" 8 | 9 | [metadata] 10 | lock-version = "1.1" 11 | python-versions = "^3.7" 12 | content-hash = "119f8058c6f87ab04b5c5f5b6403a91509c7dc8ade0d6d33b8534ab321cbf267" 13 | 14 | [metadata.files] 15 | pillow = [ 16 | {file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"}, 17 | {file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"}, 18 | {file = "Pillow-9.0.1-1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9618823bd237c0d2575283f2939655f54d51b4527ec3972907a927acbcc5bfc"}, 19 | {file = "Pillow-9.0.1-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:9bfdb82cdfeccec50aad441afc332faf8606dfa5e8efd18a6692b5d6e79f00fd"}, 20 | {file = "Pillow-9.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5100b45a4638e3c00e4d2320d3193bdabb2d75e79793af7c3eb139e4f569f16f"}, 21 | {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:528a2a692c65dd5cafc130de286030af251d2ee0483a5bf50c9348aefe834e8a"}, 22 | {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0f29d831e2151e0b7b39981756d201f7108d3d215896212ffe2e992d06bfe049"}, 23 | {file = "Pillow-9.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:855c583f268edde09474b081e3ddcd5cf3b20c12f26e0d434e1386cc5d318e7a"}, 24 | {file = "Pillow-9.0.1-cp310-cp310-win32.whl", hash = "sha256:d9d7942b624b04b895cb95af03a23407f17646815495ce4547f0e60e0b06f58e"}, 25 | {file = "Pillow-9.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:81c4b81611e3a3cb30e59b0cf05b888c675f97e3adb2c8672c3154047980726b"}, 26 | {file = "Pillow-9.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:413ce0bbf9fc6278b2d63309dfeefe452835e1c78398efb431bab0672fe9274e"}, 27 | {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80fe64a6deb6fcfdf7b8386f2cf216d329be6f2781f7d90304351811fb591360"}, 28 | {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cef9c85ccbe9bee00909758936ea841ef12035296c748aaceee535969e27d31b"}, 29 | {file = "Pillow-9.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d19397351f73a88904ad1aee421e800fe4bbcd1aeee6435fb62d0a05ccd1030"}, 30 | {file = "Pillow-9.0.1-cp37-cp37m-win32.whl", hash = "sha256:d21237d0cd37acded35154e29aec853e945950321dd2ffd1a7d86fe686814669"}, 31 | {file = "Pillow-9.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ede5af4a2702444a832a800b8eb7f0a7a1c0eed55b644642e049c98d589e5092"}, 32 | {file = "Pillow-9.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:b5b3f092fe345c03bca1e0b687dfbb39364b21ebb8ba90e3fa707374b7915204"}, 33 | {file = "Pillow-9.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:335ace1a22325395c4ea88e00ba3dc89ca029bd66bd5a3c382d53e44f0ccd77e"}, 34 | {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db6d9fac65bd08cea7f3540b899977c6dee9edad959fa4eaf305940d9cbd861c"}, 35 | {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f154d173286a5d1863637a7dcd8c3437bb557520b01bddb0be0258dcb72696b5"}, 36 | {file = "Pillow-9.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d4b1341ac07ae07eb2cc682f459bec932a380c3b122f5540432d8977e64eae"}, 37 | {file = "Pillow-9.0.1-cp38-cp38-win32.whl", hash = "sha256:effb7749713d5317478bb3acb3f81d9d7c7f86726d41c1facca068a04cf5bb4c"}, 38 | {file = "Pillow-9.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:7f7609a718b177bf171ac93cea9fd2ddc0e03e84d8fa4e887bdfc39671d46b00"}, 39 | {file = "Pillow-9.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:80ca33961ced9c63358056bd08403ff866512038883e74f3a4bf88ad3eb66838"}, 40 | {file = "Pillow-9.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c3c33ac69cf059bbb9d1a71eeaba76781b450bc307e2291f8a4764d779a6b28"}, 41 | {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12875d118f21cf35604176872447cdb57b07126750a33748bac15e77f90f1f9c"}, 42 | {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:514ceac913076feefbeaf89771fd6febde78b0c4c1b23aaeab082c41c694e81b"}, 43 | {file = "Pillow-9.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3c5c79ab7dfce6d88f1ba639b77e77a17ea33a01b07b99840d6ed08031cb2a7"}, 44 | {file = "Pillow-9.0.1-cp39-cp39-win32.whl", hash = "sha256:718856856ba31f14f13ba885ff13874be7fefc53984d2832458f12c38205f7f7"}, 45 | {file = "Pillow-9.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:f25ed6e28ddf50de7e7ea99d7a976d6a9c415f03adcaac9c41ff6ff41b6d86ac"}, 46 | {file = "Pillow-9.0.1-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:011233e0c42a4a7836498e98c1acf5e744c96a67dd5032a6f666cc1fb97eab97"}, 47 | {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:253e8a302a96df6927310a9d44e6103055e8fb96a6822f8b7f514bb7ef77de56"}, 48 | {file = "Pillow-9.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6295f6763749b89c994fcb6d8a7f7ce03c3992e695f89f00b741b4580b199b7e"}, 49 | {file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"}, 50 | {file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"}, 51 | ] 52 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "fenToBoardImage" 3 | version = "1.3.0" 4 | description = "FenToBoardImage takes a Fen string representing a Chess position, and renders a Pillow image of the resulting position." 5 | authors = ["Reed Krawiec "] 6 | license = "GPL3" 7 | readme = "README.md" 8 | [tool.poetry.dependencies] 9 | python = "^3.7" 10 | Pillow = "^9.0.0" 11 | 12 | [tool.poetry.dev-dependencies] 13 | Pillow = "^9.0.0" 14 | 15 | [build-system] 16 | requires = ["poetry-core>=1.0.0"] 17 | build-backend = "poetry.core.masonry.api" 18 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/__init__.py -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/arrows1/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/arrows1/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/arrows1/Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/arrows1/Up.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board1.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board10.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board11.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board12.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board13.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board14.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board15.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board16.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board17.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board18.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board19.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board2.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board20.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board21.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board22.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board23.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board3.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board4.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board5.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board6.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board7.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board8.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/boards/board9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/boards/board9.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/black/Bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/black/Bishop.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/black/King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/black/King.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/black/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/black/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/black/Pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/black/Pawn.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/black/Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/black/Queen.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/black/Rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/black/Rook.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/white/Bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/white/Bishop.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/white/King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/white/King.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/white/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/white/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/white/Pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/white/Pawn.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/white/Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/white/Queen.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces/white/Rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces/white/Rook.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/black/Bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/black/Bishop.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/black/King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/black/King.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/black/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/black/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/black/Pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/black/Pawn.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/black/Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/black/Queen.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/black/Rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/black/Rook.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/white/Bishop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/white/Bishop.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/white/King.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/white/King.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/white/Knight.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/white/Knight.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/white/Pawn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/white/Pawn.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/white/Queen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/white/Queen.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pieces2/white/Rook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/Fen-To-Board-Image/test/pieces2/white/Rook.png -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/poetry.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. 2 | 3 | [[package]] 4 | name = "fentoboardimage" 5 | version = "1.3.0" 6 | description = "FenToBoardImage takes a Fen string representing a Chess position, and renders a Pillow image of the resulting position." 7 | optional = false 8 | python-versions = "^3.7" 9 | files = [] 10 | develop = false 11 | 12 | [package.dependencies] 13 | Pillow = "^9.0.0" 14 | 15 | [package.source] 16 | type = "directory" 17 | url = ".." 18 | 19 | [[package]] 20 | name = "pillow" 21 | version = "9.0.0" 22 | description = "Python Imaging Library (Fork)" 23 | optional = false 24 | python-versions = ">=3.7" 25 | files = [ 26 | {file = "Pillow-9.0.0-cp310-cp310-macosx_10_10_universal2.whl", hash = "sha256:113723312215b25c22df1fdf0e2da7a3b9c357a7d24a93ebbe80bfda4f37a8d4"}, 27 | {file = "Pillow-9.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:bb47a548cea95b86494a26c89d153fd31122ed65255db5dcbc421a2d28eb3379"}, 28 | {file = "Pillow-9.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:31b265496e603985fad54d52d11970383e317d11e18e856971bdbb86af7242a4"}, 29 | {file = "Pillow-9.0.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d154ed971a4cc04b93a6d5b47f37948d1f621f25de3e8fa0c26b2d44f24e3e8f"}, 30 | {file = "Pillow-9.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80fe92813d208ce8aa7d76da878bdc84b90809f79ccbad2a288e9bcbeac1d9bd"}, 31 | {file = "Pillow-9.0.0-cp310-cp310-win32.whl", hash = "sha256:d5dcea1387331c905405b09cdbfb34611050cc52c865d71f2362f354faee1e9f"}, 32 | {file = "Pillow-9.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:52abae4c96b5da630a8b4247de5428f593465291e5b239f3f843a911a3cf0105"}, 33 | {file = "Pillow-9.0.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:72c3110228944019e5f27232296c5923398496b28be42535e3b2dc7297b6e8b6"}, 34 | {file = "Pillow-9.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97b6d21771da41497b81652d44191489296555b761684f82b7b544c49989110f"}, 35 | {file = "Pillow-9.0.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:72f649d93d4cc4d8cf79c91ebc25137c358718ad75f99e99e043325ea7d56100"}, 36 | {file = "Pillow-9.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aaf07085c756f6cb1c692ee0d5a86c531703b6e8c9cae581b31b562c16b98ce"}, 37 | {file = "Pillow-9.0.0-cp37-cp37m-win32.whl", hash = "sha256:03b27b197deb4ee400ed57d8d4e572d2d8d80f825b6634daf6e2c18c3c6ccfa6"}, 38 | {file = "Pillow-9.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a09a9d4ec2b7887f7a088bbaacfd5c07160e746e3d47ec5e8050ae3b2a229e9f"}, 39 | {file = "Pillow-9.0.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:490e52e99224858f154975db61c060686df8a6b3f0212a678e5d2e2ce24675c9"}, 40 | {file = "Pillow-9.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:500d397ddf4bbf2ca42e198399ac13e7841956c72645513e8ddf243b31ad2128"}, 41 | {file = "Pillow-9.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ebd8b9137630a7bbbff8c4b31e774ff05bbb90f7911d93ea2c9371e41039b52"}, 42 | {file = "Pillow-9.0.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd0e5062f11cb3e730450a7d9f323f4051b532781026395c4323b8ad055523c4"}, 43 | {file = "Pillow-9.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f3b4522148586d35e78313db4db0df4b759ddd7649ef70002b6c3767d0fdeb7"}, 44 | {file = "Pillow-9.0.0-cp38-cp38-win32.whl", hash = "sha256:0b281fcadbb688607ea6ece7649c5d59d4bbd574e90db6cd030e9e85bde9fecc"}, 45 | {file = "Pillow-9.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:b5050d681bcf5c9f2570b93bee5d3ec8ae4cf23158812f91ed57f7126df91762"}, 46 | {file = "Pillow-9.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:c2067b3bb0781f14059b112c9da5a91c80a600a97915b4f48b37f197895dd925"}, 47 | {file = "Pillow-9.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2d16b6196fb7a54aff6b5e3ecd00f7c0bab1b56eee39214b2b223a9d938c50af"}, 48 | {file = "Pillow-9.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98cb63ca63cb61f594511c06218ab4394bf80388b3d66cd61d0b1f63ee0ea69f"}, 49 | {file = "Pillow-9.0.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc462d24500ba707e9cbdef436c16e5c8cbf29908278af053008d9f689f56dee"}, 50 | {file = "Pillow-9.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3586e12d874ce2f1bc875a3ffba98732ebb12e18fb6d97be482bd62b56803281"}, 51 | {file = "Pillow-9.0.0-cp39-cp39-win32.whl", hash = "sha256:68e06f8b2248f6dc8b899c3e7ecf02c9f413aab622f4d6190df53a78b93d97a5"}, 52 | {file = "Pillow-9.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:6579f9ba84a3d4f1807c4aab4be06f373017fc65fff43498885ac50a9b47a553"}, 53 | {file = "Pillow-9.0.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:47f5cf60bcb9fbc46011f75c9b45a8b5ad077ca352a78185bd3e7f1d294b98bb"}, 54 | {file = "Pillow-9.0.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fd8053e1f8ff1844419842fd474fc359676b2e2a2b66b11cc59f4fa0a301315"}, 55 | {file = "Pillow-9.0.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c5439bfb35a89cac50e81c751317faea647b9a3ec11c039900cd6915831064d"}, 56 | {file = "Pillow-9.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:95545137fc56ce8c10de646074d242001a112a92de169986abd8c88c27566a05"}, 57 | {file = "Pillow-9.0.0.tar.gz", hash = "sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e"}, 58 | ] 59 | 60 | [metadata] 61 | lock-version = "2.0" 62 | python-versions = "^3.7" 63 | content-hash = "767379b9abdb511d7ee0f56476e61c0760a2190f9ee2a474500259dfb74c5ddf" 64 | -------------------------------------------------------------------------------- /third_party/Fen-To-Board-Image/test/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "fenToBoardImagetest" 3 | version = "1.0.0" 4 | description = "" 5 | authors = ["red"] 6 | [tool.poetry.dependencies] 7 | python = "^3.7" 8 | pillow = "9.0.0" 9 | fenToBoardImage = {path = "../"} 10 | -------------------------------------------------------------------------------- /third_party/stockfish/stockfish-ubuntu-x86-64-avx2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TheOpenSI/CoSMIC/2358704e63ae72b814e9912418f6c6cc71efe835/third_party/stockfish/stockfish-ubuntu-x86-64-avx2 -------------------------------------------------------------------------------- /utils/chat_history.py: -------------------------------------------------------------------------------- 1 | def build_context_from_messages(messages: list, num_pairs: int) -> str: 2 | """ 3 | Build a chat history from the given number of conversation pairs. 4 | 5 | Args: 6 | messages (list): List of messages in the chat history. 7 | num_pairs (int): Number of conversation pairs to include in the context. 8 | 9 | Returns: 10 | str: Formatted string representing the chat history. 11 | """ 12 | if not messages: 13 | return "" 14 | 15 | pairs = [] 16 | i = 0 17 | while i < len(messages) - 1: 18 | if messages[i]["role"] == "user" and messages[i + 1]["role"] == "assistant": 19 | user_msg = messages[i]["content"] 20 | assistant_msg = messages[i + 1]["content"] 21 | pairs.append((user_msg, assistant_msg)) 22 | i += 2 23 | else: 24 | i += 1 25 | 26 | selected_pairs = pairs[-num_pairs:] 27 | 28 | context_parts = [] 29 | for idx, (user_msg, assistant_msg) in enumerate(selected_pairs, start=1): 30 | block = ( 31 | f"Previous Conversation Pair {idx}\n" 32 | f"{'-'*30}\n" 33 | f"**User:** {user_msg}\n" 34 | f"**Assistant:** {assistant_msg}" 35 | ) 36 | context_parts.append(block) 37 | 38 | full_context = ( 39 | "Conversation History: \n" 40 | + "\n\n".join(context_parts) 41 | + "\n" 42 | + f"{'='*15} End of Chat History {'='*15}\n" 43 | ) 44 | 45 | return full_context 46 | 47 | 48 | 49 | if __name__ == "__main__": 50 | messages = [ 51 | {'role': 'system', 'content': 'PDF content from OpenwebUI'}, 52 | {'role': 'user', 'content': 'who is Einstein?'}, 53 | {'role': 'assistant', 'content': 'Albert Einstein (1879-1955) was a renowned German-born physicist'}, 54 | {'role': 'user', 'content': 'is he still alive?'}, 55 | {'role': 'assistant', 'content': 'No, he passed away in 1955.'}, 56 | {'role': 'user', 'content': 'what is the theory of relativity?'} 57 | ] 58 | 59 | print(build_context_from_messages(messages, 5)) -------------------------------------------------------------------------------- /utils/general.py: -------------------------------------------------------------------------------- 1 | import openai 2 | 3 | def validate_openai_api_key(api_key: str) -> bool: 4 | """ 5 | Validates the given OpenAI API key by making a test request. 6 | 7 | Args: 8 | api_key (str): The OpenAI API key to validate. 9 | 10 | Returns: 11 | bool: True if the API key is valid, False otherwise. 12 | """ 13 | try: 14 | openai.api_key = api_key 15 | # Make a simple API call to validate the key 16 | openai.models.list() 17 | return True 18 | except openai.AuthenticationError: 19 | return False 20 | except Exception as e: 21 | print(f"An error occurred during validation: {e}") 22 | return False -------------------------------------------------------------------------------- /utils/log_tool.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: log_tool.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | # ============================================================================================================= 26 | 27 | class BCOLORS: 28 | HEADER = "\033[95m" 29 | OKBLUE = "\033[94m" 30 | OKCYAN = "\033[96m" 31 | OKGREEN = "\033[92m" 32 | WARNING = "\033[93m" 33 | FAIL = "\033[91m" 34 | ENDC = "\033[0m" 35 | BOLD = "\033[1m" 36 | UNDERLINE = "\033[4m" 37 | 38 | # ============================================================================================================= 39 | 40 | INFOR_DICT = { 41 | "success": {"color": BCOLORS.OKGREEN, "comment": "Success"}, 42 | "fail": {"color": BCOLORS.FAIL, "comment": "Fail"}, 43 | "warning": {"color": BCOLORS.WARNING, "comment": "Warning"}, 44 | "info": {"color": BCOLORS.HEADER, "comment": "Info"}, 45 | "error": {"color": BCOLORS.FAIL, "comment": "Error"}, 46 | "hint": {"color": BCOLORS.OKGREEN, "comment": "Hint"}, 47 | } 48 | 49 | # ============================================================================================================= 50 | 51 | def set_color( 52 | status: str, 53 | information: str 54 | ): 55 | """Set color to display information on terminal. 56 | 57 | Args: 58 | status (str): information type, see INFOR_DICT.keys. 59 | information (str): information to be printed. 60 | 61 | Returns: 62 | information (str): colorized information. 63 | """ 64 | status = status.lower() 65 | 66 | return f"{INFOR_DICT[status]['color']}[{INFOR_DICT[status]['comment']}]{BCOLORS.ENDC} {information}" -------------------------------------------------------------------------------- /utils/module.py: -------------------------------------------------------------------------------- 1 | 2 | # ------------------------------------------------------------------------------------------------------------- 3 | # File: module.py 4 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 5 | # Contributors: 6 | # Danny Xu 7 | # 8 | # Copyright (c) 2024 Open Source Institute 9 | # 10 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 11 | # documentation files (the "Software"), to deal in the Software without restriction, including without 12 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 13 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 14 | # conditions: 15 | # 16 | # The above copyright notice and this permission notice shall be included in all copies or substantial 17 | # portions of the Software. 18 | # 19 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 20 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | # ------------------------------------------------------------------------------------------------------------- 25 | 26 | # ============================================================================================================= 27 | 28 | def get_instance( 29 | instances, 30 | instance_name: str 31 | ): 32 | """Get a class instance from a file which is imported as instances. 33 | 34 | Args: 35 | instances (object): imported file containing all functions, classes, etc. 36 | instance_name (str): the name of function, class, etc., in the file. 37 | 38 | Returns: 39 | instance: the function, class, etc. 40 | """ 41 | instance = getattr(instances, instance_name) 42 | 43 | return instance -------------------------------------------------------------------------------- /utils/num2word.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: num2word.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Danny Xu 6 | # 7 | # Copyright (c) 2024 Open Source Institute 8 | # 9 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 10 | # documentation files (the "Software"), to deal in the Software without restriction, including without 11 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 12 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 13 | # conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all copies or substantial 16 | # portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 19 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 20 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | # ------------------------------------------------------------------------------------------------------------- 24 | 25 | # ============================================================================================================= 26 | 27 | NUM2WORD_DICT = { 28 | 1: "One", 29 | 2: "Two", 30 | 3: "Three", 31 | 4: "Four", 32 | 5: "Five", 33 | 6: "Six", 34 | 7: "Seven", 35 | 8: "Eight", 36 | 9: "Nine", 37 | 10: "Ten", 38 | 11: "Eleven", 39 | 12: "Twelve", 40 | 13: "Thirteen", 41 | 14: "Fourteen", 42 | 15: "Fifteen", 43 | 16: "Sixteen", 44 | 17: "Seventeen", 45 | 18: "Eighteen", 46 | 19: "Nineteen", 47 | 20: "Twenty", 48 | 30: "Thirty", 49 | 40: "Forty", 50 | 50: "Fifty", 51 | 60: "Sixty", 52 | 70: "Seventy", 53 | 80: "Eighty", 54 | 90: "Ninety", 55 | 0: "Zero" 56 | } 57 | 58 | # ============================================================================================================= 59 | 60 | def convert_number2word( 61 | number: int 62 | ): 63 | """Convert number to letter. 64 | 65 | Args: 66 | number (int): numerical digits. 67 | 68 | Returns: 69 | number: letter-style number. 70 | """ 71 | # Cannot cover all numbers, if not in the dictionary, just return the input 72 | if number in NUM2WORD_DICT.keys(): 73 | number = NUM2WORD_DICT[number].lower() 74 | 75 | return number -------------------------------------------------------------------------------- /utils/sanitise_input.py: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------------------------------------------------------- 2 | # File: sanitise_input.py 3 | # Project: Open Source Institute-Cognitive System of Machine Intelligent Computing (OpenSI-CoSMIC) 4 | # Contributors: 5 | # Muntasir Adnan 6 | # 7 | # IMPORTANT: 8 | # - This service will use docker containers 9 | # - So user will have to be have permission to run docker commands 10 | # 11 | # Copyright (c) 2024 Open Source Institute 12 | # 13 | # Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 14 | # documentation files (the "Software"), to deal in the Software without restriction, including without 15 | # limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 16 | # the Software, and to permit persons to whom the Software is furnished to do so, subject to the following 17 | # conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in all copies or substantial 20 | # portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 23 | # LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 | # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 | # ------------------------------------------------------------------------------------------------------------- 28 | 29 | # https://docs.python.org/3/library/shlex.html#shlex.quote 30 | 31 | import re 32 | import shlex 33 | import keyword 34 | 35 | def sanitise_input(input_string: str) -> str: 36 | """ 37 | Sanitizes input string by escaping special characters and validating it. 38 | Input string can only contain alphanumeric characters, '.', '_', ':', and '-'. 39 | 40 | Args: 41 | input_string (str): Input string to be sanitized. 42 | pattern (str): Regex pattern to validate the input. 43 | 44 | Raises: 45 | ValueError: If input string contains invalid characters. 46 | 47 | Returns: 48 | str: Sanitized input string. 49 | """ 50 | pattern = r"^[a-zA-Z0-9._:-]+$" 51 | 52 | # Validate the input against the provided pattern 53 | if not re.match(pattern, input_string): 54 | raise ValueError(f"Invalid input: {input_string}") 55 | 56 | # Escape the input for safe shell usage 57 | return shlex.quote(input_string) 58 | 59 | 60 | def sanitise_variable_name(name: str) -> str: 61 | """ 62 | Fixes a string to make it a valid Python variable name. 63 | 64 | Parameters: 65 | - name (str): The input string to sanitize. 66 | 67 | Returns: 68 | - str: A valid Python variable name. 69 | """ 70 | # Replace invalid characters with underscores 71 | name = re.sub(r"[^a-zA-Z0-9_]", "_", name) 72 | 73 | # Ensure the name doesn't start with a digit 74 | if name and name[0].isdigit(): 75 | name = f"_{name}" 76 | 77 | # Ensure the name isn't a Python reserved keyword 78 | if keyword.iskeyword(name): 79 | name = f"{name}_var" 80 | 81 | return name -------------------------------------------------------------------------------- /utils/statistics.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pandas as pd 3 | 4 | statistic_dir = "data/cosmic/statistic" 5 | statistic_dict = { 6 | "user_id": "unknown", 7 | "email": "unknown", 8 | "start_date": -1, 9 | "last_date": -1, 10 | "average_token_length": 0, 11 | "query_count": 0 12 | } 13 | 14 | def update_statistic_table(statistic_dict): 15 | global statistic_dir 16 | 17 | os.makedirs(statistic_dir, exist_ok=True) 18 | current_time = statistic_dict["last_date"] 19 | time_split = current_time.split(",")[0].split("-") 20 | current_month_year = f"{time_split[1]}-{time_split[2]}" 21 | statistic_path = os.path.join( 22 | statistic_dir, 23 | f"{current_month_year}.csv" 24 | ) 25 | 26 | if os.path.exists(statistic_path): 27 | data = pd.read_csv(statistic_path) 28 | user_emails = data["email"].tolist() 29 | else: 30 | user_emails = [] 31 | 32 | if statistic_dict["email"] in user_emails: 33 | idx = [idx for idx, user_email in enumerate(user_emails) if user_email == statistic_dict["email"]][0] 34 | data.loc[idx, "last_date"] = statistic_dict["last_date"] 35 | history_total_token_length = data["average_token_length"][idx] * data["query_count"][idx] 36 | current_total_token_length = statistic_dict["average_token_length"] * statistic_dict["query_count"] 37 | total_query_count = data["query_count"][idx] + statistic_dict["query_count"] 38 | data.loc[idx, "average_token_length"] = (history_total_token_length + current_total_token_length) / total_query_count 39 | data.loc[idx, "query_count"] = total_query_count 40 | else: 41 | df = pd.DataFrame([{ 42 | "user_id": statistic_dict["user_id"], 43 | "email": statistic_dict["email"], 44 | "start_date": statistic_dict["start_date"], 45 | "last_date": statistic_dict["last_date"], 46 | "average_token_length": statistic_dict["average_token_length"], 47 | "query_count": statistic_dict["query_count"] 48 | }]) 49 | if len(user_emails) > 0: df = pd.concat([data, df], axis=0) 50 | data = df 51 | 52 | data.to_csv( 53 | statistic_path, 54 | header=[ 55 | "user_id", 56 | "email", 57 | "start_date", 58 | "last_date", 59 | "average_token_length", 60 | "query_count" 61 | ], 62 | index=False 63 | ) 64 | 65 | def update_statistic_per_query( 66 | query, 67 | user_id, 68 | user_email, 69 | current_time 70 | ): 71 | global statistic_dict 72 | if False: 73 | # Save for the previous user (when the user_id changed). 74 | pre_user_id = statistic_dict["user_id"] 75 | pre_query_count = statistic_dict["query_count"] 76 | token_length = len(query) 77 | 78 | # Accumulate for the same user. 79 | if pre_user_id == user_id: 80 | pre_average_token_length = statistic_dict["average_token_length"] 81 | statistic_dict["last_date"] = current_time 82 | statistic_dict["average_token_length"] = \ 83 | (pre_average_token_length * pre_query_count + token_length) \ 84 | / (pre_query_count + 1) 85 | statistic_dict["query_count"] = pre_query_count + 1 86 | 87 | if pre_user_id != user_id: 88 | # Save previous user statistic. 89 | if pre_user_id != "unknown": 90 | update_statistic_table(statistic_dict) 91 | 92 | # Initialize for a different user. 93 | statistic_dict["user_id"] = user_id 94 | statistic_dict["email"] = user_email 95 | statistic_dict["start_date"] = current_time 96 | statistic_dict["last_date"] = current_time 97 | statistic_dict["average_token_length"] = token_length 98 | statistic_dict["query_count"] = 1 99 | else: 100 | # Save every query for the current user. 101 | token_length = len(query) 102 | statistic_dict["user_id"] = user_id 103 | statistic_dict["email"] = user_email 104 | statistic_dict["start_date"] = current_time 105 | statistic_dict["last_date"] = current_time 106 | statistic_dict["average_token_length"] = token_length 107 | statistic_dict["query_count"] = 1 108 | update_statistic_table(statistic_dict) 109 | --------------------------------------------------------------------------------