├── .env ├── .gitignore ├── .vscode └── launch.json ├── Dockerfile ├── README.md ├── app ├── main.py ├── routers │ └── base.py └── services │ ├── open_interpreter_service.py │ └── websocket_service.py ├── conversation_histories ├── .keep └── 20231006.json ├── docker-compose.yml ├── en_README.md ├── requirements.txt └── workspace └── output └── .keep /.env: -------------------------------------------------------------------------------- 1 | OPENAI_API_KEY= 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | db.sqlite3-journal 62 | 63 | # Flask stuff: 64 | instance/ 65 | .webassets-cache 66 | 67 | # Scrapy stuff: 68 | .scrapy 69 | 70 | # Sphinx documentation 71 | docs/_build/ 72 | 73 | # PyBuilder 74 | target/ 75 | 76 | # Jupyter Notebook 77 | .ipynb_checkpoints 78 | 79 | # IPython 80 | profile_default/ 81 | ipython_config.py 82 | 83 | # pyenv 84 | .python-version 85 | 86 | # pipenv 87 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 88 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 89 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 90 | # install all needed dependencies. 91 | #Pipfile.lock 92 | 93 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 94 | __pypackages__/ 95 | 96 | # Celery stuff 97 | celerybeat-schedule 98 | celerybeat.pid 99 | 100 | # SageMath parsed files 101 | *.sage.py 102 | 103 | # Environments 104 | # .env 105 | .venv 106 | env/ 107 | venv/ 108 | ENV/ 109 | env.bak/ 110 | venv.bak/ 111 | 112 | # Pycharm, VSCode 113 | .idea/ 114 | # .vscode/ 115 | *.iml 116 | *.iws 117 | *.iws 118 | 119 | # Databases 120 | *.sqlite 121 | 122 | # Logs 123 | *.log 124 | 125 | # Others 126 | .DS_Store 127 | *.swp 128 | *~ 129 | ._* 130 | /workspace/* 131 | !/workspace/output 132 | /workspace/output/* 133 | !/workspace/output/.keep 134 | # conversation_histories/* 135 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Python: Remote Attach", 6 | "type": "python", 7 | "request": "attach", 8 | "connect": { 9 | "host": "localhost", 10 | "port": 5678 11 | }, 12 | "pathMappings": [ 13 | { 14 | "localRoot": "${workspaceFolder}", 15 | "remoteRoot": "/app" 16 | } 17 | ] 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Use an official Python runtime as a parent image 2 | FROM python:3.11-bookworm 3 | 4 | # Set environment variables 5 | ENV PYTHONDONTWRITEBYTECODE 1 6 | ENV PYTHONUNBUFFERED 1 7 | 8 | # Set work directory 9 | WORKDIR /app 10 | 11 | # Install dependencies 12 | COPY requirements.txt /app/ 13 | RUN pip install --upgrade pip && pip install -r requirements.txt 14 | 15 | # Copy project 16 | COPY . /app/ 17 | 18 | # Expose the application on port 8000 19 | EXPOSE 8000 20 | 21 | # Define the command to start the server 22 | CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AITuberKit サーバーサイド 2 | [English version](./en_README.md) 3 | 4 | ## 注意 5 | 6 | - 今後メンテナンスをする予定は今のところありません。 7 | - OpenInterpreterを含む全てのライブラリのバージョンは固定しています('24/08/20 時点の最新は0.3.7) 8 | 9 | ## 関連 10 | 11 | - フロントサイドリポジトリ -> [tegnike/aituber-kit](https://github.com/tegnike/aituber-kit) 12 | - 解説記事 -> [美少女と一緒に開発しようぜ!!【Open Interpreter】](https://note.com/nike_cha_n/n/nabcfeb7aaf3f) 13 | 14 | ## できること 15 | 16 | 1. WebSocketでメッセージを受け取って、Open Interpreterからレスポンスを取得することができます(stream対応)。 17 | 2. ファイルを送信してサーバー側に保存することができます。このファイルに対してOpen Interpreterに指示を出すことも可能です。 18 | 19 | ## 事前準備 20 | 21 | 1. 本リポジトリはWebSocketでの起動を前提としているため、ご自身の環境に合わせて接続先を準備してください。 22 | 2. 接続URLはデフォルトで`ws://127.0.0.1:8000/ws`です。 23 | 24 | ## 実行方法 25 | 26 | 1. `.env`にOPENAI_API_KEYを設定 27 | 2. `docker-compose up -d --build` 実行 28 | 29 | ## デバッグ 30 | 31 | 1. 実行環境がVSCodeのときに、DEBUG_MODE=1でデバッグモードを起動します。 32 | 2. ブレークポイントを設置して快適にデバッグしましょう。 33 | 34 | 参考: [VS Codeエディタ入門](https://zenn.dev/karaage0703/books/80b6999d429abc8051bb/viewer/898591) 35 | 36 | ## コード解説 37 | 38 | 長くなるので下記に記載しました。 39 | 40 | - [【コード解説】美少女OPInterpreter簡易版](https://note.com/nike_cha_n/n/n39f62ee846e3) 41 | 42 | ## その他 43 | 44 | 1. ライセンスは[KillianLucas/open-interpreter](https://github.com/KillianLucas/open-interpreter)に準拠します。 45 | 2. Open Interpreterの使用方法は下記にまとめています。 46 | 47 | - [【開発者向け】Open Interpreterの使い方をコード付きで説明する(python編)](https://note.com/nike_cha_n/n/n764514cf5351) 48 | -------------------------------------------------------------------------------- /app/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from app.routers import base 3 | import ptvsd 4 | import os 5 | 6 | if os.getenv('DEBUG_MODE') == "1": 7 | # デバッグ用コード 8 | ptvsd.enable_attach(address=('0.0.0.0', 5678), redirect_output=True) 9 | ptvsd.wait_for_attach() 10 | 11 | app = FastAPI() 12 | app.include_router(base.router) 13 | -------------------------------------------------------------------------------- /app/routers/base.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from fastapi import APIRouter, WebSocket, Request, WebSocketDisconnect 3 | from ..services.open_interpreter_service import stream_open_interpreter 4 | from ..services.websocket_service import send_websocket_message 5 | 6 | router = APIRouter() 7 | 8 | 9 | class ConnectionManager: 10 | def __init__(self): 11 | self.active_connections: List[WebSocket] = [] 12 | 13 | async def connect(self, websocket: WebSocket): 14 | await websocket.accept() 15 | self.active_connections.append(websocket) 16 | 17 | def disconnect(self, websocket: WebSocket): 18 | self.active_connections.remove(websocket) 19 | 20 | async def send_personal_message(self, message: str, websocket: WebSocket): 21 | await websocket.send_text(message) 22 | 23 | async def broadcast(self, message: str): 24 | for connection in self.active_connections: 25 | await connection.send_text(message) 26 | 27 | async def send_message_to_all(self, message: str, type: str): 28 | closed_connections = [] 29 | for websocket in self.active_connections: 30 | try: 31 | await send_websocket_message(websocket, "", "assistant", "start") 32 | await send_websocket_message(websocket, message, type) 33 | await send_websocket_message(websocket, "", "assistant", "end") 34 | except RuntimeError: 35 | # WebSocketが閉じられている場合、後で削除するためにリストに追加 36 | closed_connections.append(websocket) 37 | 38 | # 閉じられたコネクションを削除 39 | for closed_websocket in closed_connections: 40 | self.disconnect(closed_websocket) 41 | 42 | 43 | manager = ConnectionManager() 44 | 45 | 46 | @router.websocket("/ws") 47 | async def websocket_endpoint(websocket: WebSocket): 48 | await manager.connect(websocket) 49 | try: 50 | await stream_open_interpreter(websocket) 51 | except WebSocketDisconnect: 52 | manager.disconnect(websocket) 53 | 54 | 55 | @router.post("/send_message") 56 | async def send_message(request: Request): 57 | message = await request.json() 58 | await manager.send_message_to_all(message["message"], message.get("type", "message")) 59 | return {"status": "ok", "message": message["message"]} 60 | 61 | 62 | @router.get("/") 63 | async def test(): 64 | print("/test called.") 65 | return {"message": "Hello World"} 66 | -------------------------------------------------------------------------------- /app/services/open_interpreter_service.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import base64 4 | import traceback 5 | from interpreter import interpreter 6 | from datetime import datetime 7 | from .websocket_service import send_websocket_message 8 | 9 | async def stream_open_interpreter(websocket): 10 | language = os.getenv('LANGUAGE') or "japanese" 11 | 12 | try: 13 | # 1日の記憶を保持する 14 | interpreter.conversation_filename = f"{datetime.now().strftime('%Y%m%d')}.json" 15 | interpreter.conversation_history_path = "./conversation_histories/" 16 | if os.path.exists(interpreter.conversation_history_path + interpreter.conversation_filename): 17 | # あったら読み込んで記憶として設定する 18 | with open(interpreter.conversation_history_path + interpreter.conversation_filename, "r") as f: 19 | interpreter.messages = json.load(f) 20 | print("Loaded conversation history.") 21 | else: 22 | # なかったら作成する 23 | with open(interpreter.conversation_history_path + interpreter.conversation_filename, "w") as f: 24 | json.dump([], f) 25 | print("Created conversation history.") 26 | 27 | interpreter.llm.model = "gpt-4o" 28 | interpreter.auto_run = True 29 | # interpreter.debug_mode = True 30 | interpreter.system_message = f""" 31 | You can use the following libraries without installing: 32 | - pandas 33 | - numpy 34 | - matplotlib 35 | - seaborn 36 | - scikit-learn 37 | - pandas-datareader 38 | - mplfinance 39 | - yfinance 40 | - requests 41 | - scrapy 42 | - beautifulsoup4 43 | - opencv-python 44 | - ffmpeg-python 45 | - PyMuPDF 46 | - pytube 47 | - pyocr 48 | - easyocr 49 | - pydub 50 | - pdfkit 51 | - weasyprint 52 | Your workspace is `./workspace` folder. If you make an output file, please put it in `./workspace/output`. 53 | {'[[Please answer in Japanese. 日本語でお答えください。]]' if language == 'japanese' else ''} 54 | """ 55 | 56 | message = "" 57 | saved_file = "" 58 | prev_type = "" 59 | 60 | while True: 61 | try: 62 | if message != "" and message != "\n": 63 | await send_websocket_message(websocket, message, prev_type) 64 | await send_websocket_message(websocket, "", "assistant", "end") 65 | 66 | message = "" 67 | prev_type = "" 68 | 69 | # WebSocketでメッセージ受け取り待機 70 | print("Waiting for user message...") 71 | user_message = await websocket.receive_text() 72 | print(f"Received user message: {user_message}") 73 | 74 | parsed_data = json.loads(user_message) 75 | message_content = parsed_data.get("content") 76 | message_type = parsed_data.get("type") 77 | 78 | # WebSocketでテキストメッセージを受け取った場合 79 | # ex. {"type": "message", "text": "こんにちは"} 80 | if message_type == "chat" and message_content != "": 81 | if saved_file != "": 82 | user_message = saved_file + user_message 83 | saved_file = "" 84 | 85 | # 処理開始時に"start"を送信 86 | await send_websocket_message(websocket, "", "assistant", "start") 87 | 88 | # OpenInterpreterの結果をstreamモードで取得、chunk毎に処理 89 | is_source_code = False 90 | try: 91 | for chunk in interpreter.chat(message_content, display=True, stream=True): 92 | current_type = chunk["type"] 93 | exculde_types = ["language", "active_line", "end_of_execution", "start_of_message", "end_of_message", "start_of_code", "end_of_code"] 94 | if current_type not in exculde_types: 95 | # message typeの場合は、文節に区切ってメッセージを送信 96 | if message and (current_type != prev_type or (len(message) > 15 and message[-1] in ['、', '。', '!', '?', ';', '…', ':'] or message[-1] == "\n")): 97 | if message != "": 98 | if "```" in message: 99 | # Toggle is_source_code 100 | is_source_code = not is_source_code 101 | else: 102 | type_ = "code" if is_source_code else prev_type 103 | await send_websocket_message(websocket, message, type_) 104 | message = "" 105 | 106 | if current_type == "executing": 107 | message += f"{chunk['content']}\n\n========================\nrunning...\n========================" 108 | else: 109 | try: 110 | if isinstance(chunk["content"], dict): 111 | await send_websocket_message(websocket, chunk["content"]["content"], type_) 112 | elif isinstance(chunk["content"], str): 113 | message += chunk["content"] 114 | else: 115 | pass 116 | except KeyError: 117 | pass 118 | prev_type = current_type 119 | finally: 120 | # 処理終了時に必ず"end"を送信 121 | await send_websocket_message(websocket, "", "assistant", "end") 122 | 123 | # WebSocketでファイルを受け取った場合 124 | # ex. {"type": "file", "fileName": "sample.txt", "fileData": "data:;base64,SGVsbG8sIHdvcmxkIQ=="} 125 | elif message_type == "file": 126 | # JSONデータをパースして、ファイル名とファイルデータを取得 127 | file_name = parsed_data.get("fileName") 128 | base64_data = parsed_data.get("fileData").split(",")[1] 129 | file_data = base64.b64decode(base64_data) 130 | 131 | # ファイルを保存するディレクトリを指定 132 | directory = "./workspace" 133 | 134 | # ディレクトリが存在しない場合、作成 135 | if not os.path.exists(directory): 136 | os.makedirs(directory) 137 | 138 | # ファイルのフルパスを作成 139 | file_path = os.path.join(directory, file_name) 140 | 141 | # ファイルを保存 142 | with open(file_path, "wb") as f: 143 | f.write(file_data) 144 | 145 | # 処理開始時に"start"を送信 146 | await send_websocket_message(websocket, "", "assistant", "start") 147 | 148 | # メッセージを追加 149 | saved_file = f"{directory}/{file_name}にファイルを保存しました。" if language == 'japanese' else f"Saved file to {directory}/{file_name}." 150 | save_message = "ファイルを保存しました。" if language == 'japanese' else f"Saved file." 151 | await send_websocket_message(websocket, save_message, "assistant") 152 | 153 | # 処理終了時に"end"を送信 154 | await send_websocket_message(websocket, "", "assistant", "end") 155 | 156 | # WebSocketで未設定のメッセージを受け取った場合 157 | else: 158 | # 処理開始時に"start"を送信 159 | await send_websocket_message(websocket, "", "assistant", "start") 160 | 161 | error_message = "不正な送信が送られたようです。" if language == 'japanese' else "An invalid message was sent." 162 | await send_websocket_message(websocket, error_message, "assistant") 163 | 164 | # 処理終了時に"end"を送信 165 | await send_websocket_message(websocket, "", "assistant", "end") 166 | 167 | except Exception as e: 168 | print(f"Error in message processing: {e}") 169 | traceback.print_exc() 170 | await send_websocket_message(websocket, "エラーが発生しました。", "assistant") 171 | await send_websocket_message(websocket, "", "assistant", "end") 172 | 173 | except Exception as e: 174 | print(f"Fatal error: {e}") 175 | traceback.print_exc() 176 | finally: 177 | await websocket.close() 178 | -------------------------------------------------------------------------------- /app/services/websocket_service.py: -------------------------------------------------------------------------------- 1 | import json 2 | import asyncio 3 | 4 | 5 | async def send_websocket_message(websocket, message, role, type="", emotion="neutral"): 6 | role = "assistant" if role == "message" else role 7 | 8 | if not websocket: 9 | print("Can't send message, WebSocket connection is closed.") 10 | return 11 | elif type == "" and message == "": 12 | print("Can't send message, message is empty.") 13 | return 14 | else: 15 | json_data = json.dumps( 16 | {"role": role, "text": message, "emotion": emotion, "type": type}, 17 | ensure_ascii=False, 18 | ) 19 | print(f"Sending message: {json_data}") 20 | await websocket.send_text(json_data) 21 | await asyncio.sleep(0.01) # 10ミリ秒の遅延を追加 22 | print("Send complete.") 23 | -------------------------------------------------------------------------------- /conversation_histories/.keep: -------------------------------------------------------------------------------- 1 | [{"type": "error", "content": "Traceback (most recent call last):\n File \"/app/app/services/open_interpreter_service.py\", line 119, in stream_open_interpreter\n for chunk in interpreter.chat(message_content, display=True, stream=True):\n File \"/usr/local/lib/python3.11/site-packages/interpreter/core/core.py\", line 87, in _streaming_chat\n yield from terminal_interface(self, message)\n File \"/usr/local/lib/python3.11/site-packages/interpreter/terminal_interface/terminal_interface.py\", line 62, in terminal_interface\n for chunk in interpreter.chat(message, display=False, stream=True):\n File \"/usr/local/lib/python3.11/site-packages/interpreter/core/core.py\", line 95, in _streaming_chat\n yield from self._respond()\n File \"/usr/local/lib/python3.11/site-packages/interpreter/core/core.py\", line 121, in _respond\n yield from respond(self)\n File \"/usr/local/lib/python3.11/site-packages/interpreter/core/respond.py\", line 24, in respond\n get_relevant_procedures(interpreter.messages[-2:])\n File \"/usr/local/lib/python3.11/site-packages/interpreter/rag/get_relevant_procedures.py\", line 9, in get_relevant_procedures\n query = {\"query\": convert_to_openai_messages(messages)}\n ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/interpreter/utils/convert_to_openai_messages.py\", line 8, in convert_to_openai_messages\n \"role\": message[\"role\"],\n ~~~~~~~^^^^^^^^\nKeyError: 'role'\n"}, {"type": "error", "content": "Traceback (most recent call last):\n File \"/app/app/services/open_interpreter_service.py\", line 130, in stream_open_interpreter\n await send_websocket_message(websocket, message, type_)\n File \"/app/app/services/websocket_service.py\", line 11, in send_websocket_message\n await websocket.send({\"type\": \"websocket.send\", \"text\": json_data})\n File \"/usr/local/lib/python3.11/site-packages/starlette/websockets.py\", line 85, in send\n await self._send(message)\n File \"/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py\", line 65, in sender\n await send(message)\n File \"/usr/local/lib/python3.11/site-packages/uvicorn/protocols/websockets/websockets_impl.py\", line 320, in asgi_send\n await self.send(data) # type: ignore[arg-type]\n ^^^^^^^^^^^^^^^^^^^^^\n File \"/usr/local/lib/python3.11/site-packages/websockets/legacy/protocol.py\", line 647, in send\n await self.write_frame(True, opcode, data)\n File \"/usr/local/lib/python3.11/site-packages/websockets/legacy/protocol.py\", line 1205, in write_frame\n await self.drain()\n File \"/usr/local/lib/python3.11/site-packages/websockets/legacy/protocol.py\", line 1194, in drain\n await self.ensure_open()\n File \"/usr/local/lib/python3.11/site-packages/websockets/legacy/protocol.py\", line 935, in ensure_open\n raise self.connection_closed_exc()\nwebsockets.exceptions.ConnectionClosedError: no close frame received or sent\n"}] -------------------------------------------------------------------------------- /conversation_histories/20231006.json: -------------------------------------------------------------------------------- 1 | [{"role": "user", "message": "\u304a\u306f\u3088\u3046"}, {"role": "assistant", "message": "\u304a\u306f\u3088\u3046\u3054\u3056\u3044\u307e\u3059\u3002\u4f55\u304b\u304a\u624b\u4f1d\u3044\u3067\u304d\u308b\u3053\u3068\u304c\u3042\u308c\u3070\u304a\u77e5\u3089\u305b\u304f\u3060\u3055\u3044\u3002"}] -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | web: 5 | build: . 6 | command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload 7 | volumes: 8 | - .:/app 9 | ports: 10 | - 8000:8000 11 | - 5678:5678 12 | env_file: 13 | - .env 14 | -------------------------------------------------------------------------------- /en_README.md: -------------------------------------------------------------------------------- 1 | # AITuberKit Server Side 2 | [Japanese version](./README.md) 3 | 4 | ## Note 5 | 6 | - There are currently no plans for future maintenance. 7 | - All library versions, including OpenInterpreter, are fixed (the latest as of 20/08/24 is 0.3.7) 8 | 9 | ## Relation 10 | 11 | - Front-side repository -> [tegnike/aituber-kit](https://github.com/tegnike/aituber-kit) 12 | - Explanatory article -> [Let's develop with a beautiful girl!! [Open Interpreter]](https://note.com/nike_cha_n/n/nabcfeb7aaf3f) 13 | 14 | ## Features 15 | 16 | 1. You can receive messages via WebSocket and obtain responses from the Open Interpreter (supports stream mode). 17 | 2. You can send files to be saved on the server side. You can also issue commands to the Open Interpreter for these files. 18 | 19 | ## Prerequisites 20 | 21 | 1. This repository assumes operation via WebSocket, so please prepare a connection destination suitable for your environment. 22 | 2. The default connection URL is `ws://127.0.0.1:8000/ws`. 23 | 24 | ## Execution Steps 25 | 26 | 1. Set the OPENAI_API_KEY in `.env`. 27 | 2. Execute `docker-compose up -d --build`. 28 | 29 | ## Debugging 30 | 31 | 1. When using VSCode as the execution environment, launch in debug mode with DEBUG_MODE=1. 32 | 2. Set breakpoints and enjoy comfortable debugging. 33 | 34 | Reference: [VS Code Editor Introduction](https://zenn.dev/karaage0703/books/80b6999d429abc8051bb/viewer/898591) 35 | 36 | ## Code Explanation 37 | 38 | It's lengthy, so I've detailed it in the link below: 39 | 40 | - [Code Explanation: Simple Version of Beautiful Girl OPInterpreter](https://note.com/nike_cha_n/n/n39f62ee846e3) 41 | 42 | ## Miscellaneous 43 | 44 | 1. The license conforms to [KillianLucas/open-interpreter](https://github.com/KillianLucas/open-interpreter). 45 | 2. Instructions on using the Open Interpreter are consolidated in the link below: 46 | 47 | - [For Developers: Explaining How to Use Open Interpreter with Code (Python Edition)](https://note.com/nike_cha_n/n/n764514cf5351) 48 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aifs==0.0.9 2 | aiohappyeyeballs==2.4.0 3 | aiohttp==3.10.5 4 | aiosignal==1.3.1 5 | annotated-types==0.7.0 6 | anyio==4.4.0 7 | asgiref==3.8.1 8 | astor==0.8.1 9 | asttokens==2.4.1 10 | attrs==24.2.0 11 | Automat==24.8.1 12 | backoff==2.2.1 13 | bcrypt==4.2.0 14 | beautifulsoup4==4.12.3 15 | blessed==1.20.0 16 | Brotli==1.1.0 17 | build==1.2.1 18 | cachetools==5.5.0 19 | certifi==2024.7.4 20 | cffi==1.17.0 21 | chardet==5.2.0 22 | charset-normalizer==3.3.2 23 | chroma-hnswlib==0.7.3 24 | chromadb==0.4.24 25 | click==8.1.7 26 | coloredlogs==15.0.1 27 | comm==0.2.2 28 | constantly==23.10.4 29 | contourpy==1.2.1 30 | cryptography==43.0.0 31 | cssselect==1.2.0 32 | cssselect2==0.7.0 33 | cycler==0.12.1 34 | dataclasses-json==0.6.7 35 | debugpy==1.8.5 36 | decorator==5.1.1 37 | deepdiff==7.0.1 38 | defusedxml==0.7.1 39 | Deprecated==1.2.14 40 | distro==1.9.0 41 | easyocr==1.7.1 42 | editor==1.6.6 43 | emoji==2.12.1 44 | executing==2.0.1 45 | fastapi==0.110.3 46 | ffmpeg-python==0.2.0 47 | filelock==3.15.4 48 | filetype==1.2.0 49 | flatbuffers==24.3.25 50 | fonttools==4.53.1 51 | frozendict==2.4.4 52 | frozenlist==1.4.1 53 | fsspec==2024.6.1 54 | future==1.0.0 55 | git-python==1.0.3 56 | gitdb==4.0.11 57 | GitPython==3.1.43 58 | google-api-core==2.19.1 59 | google-api-python-client==2.141.0 60 | google-auth==2.34.0 61 | google-auth-httplib2==0.2.0 62 | googleapis-common-protos==1.63.2 63 | grpcio==1.65.5 64 | h11==0.14.0 65 | html2image==2.0.4.3 66 | html5lib==1.1 67 | httpcore==1.0.5 68 | httplib2==0.22.0 69 | httptools==0.6.1 70 | httpx==0.27.0 71 | huggingface-hub==0.24.6 72 | humanfriendly==10.0 73 | hyperlink==21.0.0 74 | idna==3.7 75 | imageio==2.35.1 76 | importlib_metadata==8.0.0 77 | importlib_resources==6.4.3 78 | incremental==24.7.2 79 | iniconfig==2.0.0 80 | inquirer==3.4.0 81 | ipykernel==6.29.5 82 | ipython==8.26.0 83 | itemadapter==0.9.0 84 | itemloaders==1.3.1 85 | jedi==0.19.1 86 | Jinja2==3.1.4 87 | jiter==0.5.0 88 | jmespath==1.0.1 89 | joblib==1.4.2 90 | jsonpath-python==1.0.6 91 | jupyter_client==8.6.2 92 | jupyter_core==5.7.2 93 | kiwisolver==1.4.5 94 | kubernetes==30.1.0 95 | langdetect==1.0.9 96 | lazy_loader==0.4 97 | litellm==1.40.8 98 | lxml==5.3.0 99 | markdown-it-py==3.0.0 100 | MarkupSafe==2.1.5 101 | marshmallow==3.21.3 102 | matplotlib==3.9.2 103 | matplotlib-inline==0.1.7 104 | mdurl==0.1.2 105 | mmh3==4.1.0 106 | monotonic==1.6 107 | mplfinance==0.12.10b0 108 | mpmath==1.3.0 109 | multidict==6.0.5 110 | multitasking==0.0.11 111 | mypy-extensions==1.0.0 112 | nest-asyncio==1.6.0 113 | networkx==3.3 114 | ninja==1.11.1.1 115 | nltk==3.9.1 116 | numpy>=1.23.5,<2.3 117 | oauthlib==3.2.2 118 | onnxruntime==1.19.0 119 | open-interpreter==0.2.2 120 | openai==1.41.1 121 | opencv-python>=4.5.0,<5.0.0 122 | opencv-python-headless>=4.5.0,<5.0.0 123 | opentelemetry-api==1.26.0 124 | opentelemetry-exporter-otlp-proto-common==1.26.0 125 | opentelemetry-exporter-otlp-proto-grpc==1.26.0 126 | opentelemetry-instrumentation==0.47b0 127 | opentelemetry-instrumentation-asgi==0.47b0 128 | opentelemetry-instrumentation-fastapi==0.47b0 129 | opentelemetry-proto==1.26.0 130 | opentelemetry-sdk==1.26.0 131 | opentelemetry-semantic-conventions==0.47b0 132 | opentelemetry-util-http==0.47b0 133 | ordered-set==4.1.0 134 | orjson==3.10.7 135 | overrides==7.7.0 136 | packaging==24.1 137 | pandas>=1.3.0,<3.0.0 138 | pandas-datareader==0.10.0 139 | parsel==1.9.1 140 | parso==0.8.4 141 | pdfkit==1.0.0 142 | peewee==3.17.6 143 | pexpect==4.9.0 144 | pillow==10.4.0 145 | platformdirs==4.2.2 146 | pluggy==1.5.0 147 | posthog==3.5.0 148 | prompt_toolkit==3.0.47 149 | Protego==0.3.1 150 | proto-plus==1.24.0 151 | protobuf==4.25.4 152 | psutil==5.9.8 153 | ptvsd==4.3.2 154 | ptyprocess==0.7.0 155 | pulsar-client==3.5.0 156 | pure_eval==0.2.3 157 | pyasn1==0.6.0 158 | pyasn1_modules==0.4.0 159 | pyclipper==1.3.0.post5 160 | pycparser==2.22 161 | pydantic==2.8.2 162 | pydantic_core==2.20.1 163 | PyDispatcher==2.0.7 164 | pydub==0.25.1 165 | pydyf==0.11.0 166 | Pygments==2.18.0 167 | PyMuPDF==1.24.9 168 | PyMuPDFb==1.24.9 169 | pyocr==0.8.5 170 | pyOpenSSL==24.2.1 171 | pyparsing==3.1.2 172 | pypdf==4.3.1 173 | pyphen==0.16.0 174 | PyPika==0.48.9 175 | pyproject_hooks==1.1.0 176 | pytest==8.3.2 177 | python-bidi==0.6.0 178 | python-dateutil==2.9.0.post0 179 | python-dotenv==1.0.1 180 | python-iso639==2024.4.27 181 | python-magic==0.4.27 182 | pytube==15.0.0 183 | pytz==2024.1 184 | PyYAML==6.0.2 185 | pyzmq==26.1.1 186 | queuelib==1.7.0 187 | rapidfuzz==3.9.6 188 | readchar==4.2.0 189 | regex==2024.7.24 190 | requests==2.32.3 191 | requests-file==2.1.0 192 | requests-oauthlib==2.0.0 193 | requests-toolbelt==1.0.0 194 | rich==13.7.1 195 | rsa==4.9 196 | runs==1.2.2 197 | scikit-image==0.24.0 198 | scikit-learn==1.5.1 199 | scipy==1.14.0 200 | Scrapy==2.11.2 201 | seaborn==0.13.2 202 | Send2Trash==1.8.3 203 | service-identity==24.1.0 204 | shapely==2.0.6 205 | shellingham==1.5.4 206 | six==1.16.0 207 | smmap==5.0.1 208 | sniffio==1.3.1 209 | soupsieve==2.6 210 | stack-data==0.6.3 211 | starlette==0.37.2 212 | sympy==1.13.2 213 | tabulate==0.9.0 214 | tenacity==9.0.0 215 | threadpoolctl==3.5.0 216 | tifffile==2024.8.10 217 | tiktoken==0.5.2 218 | tinycss2==1.3.0 219 | tldextract==5.1.2 220 | tokenizers==0.20.0 221 | tokentrim==0.1.13 222 | toml==0.10.2 223 | torch==2.4.0 224 | torchvision>=0.13.0,<1.0.0 225 | tornado==6.4.1 226 | tqdm==4.66.5 227 | traitlets==5.14.3 228 | Twisted==24.7.0 229 | typer==0.12.4 230 | typing-inspect==0.9.0 231 | typing_extensions==4.12.2 232 | tzdata==2024.1 233 | unstructured==0.12.5 234 | unstructured-client==0.25.5 235 | uritemplate==4.1.1 236 | urllib3==2.2.2 237 | uvicorn==0.27.1 238 | w3lib==2.2.1 239 | watchdog==4.0.2 240 | watchfiles==0.23.0 241 | wcwidth==0.2.13 242 | weasyprint==62.3 243 | webencodings==0.5.1 244 | websocket-client==1.8.0 245 | websockets==12.0 246 | wget==3.2 247 | wrapt==1.16.0 248 | xmod==1.8.1 249 | yarl==1.9.4 250 | yfinance==0.2.41 251 | zipp==3.20.0 252 | zope.interface==7.0.1 253 | zopfli==0.2.3 254 | -------------------------------------------------------------------------------- /workspace/output/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tegnike/aituber-server/8f09eca06ae5458f3646908cd22b4a824577ef98/workspace/output/.keep --------------------------------------------------------------------------------