├── README.md ├── requirements.txt ├── docker-compose.yaml ├── deepseek_chainlit.py ├── deepseek_streamlit.py └── .gitignore /README.md: -------------------------------------------------------------------------------- 1 | # Deepseek-R1-GUI 2 | Deepseek R1 GUI 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | chainlit 2 | streamlit 3 | ollama 4 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | ollama: 3 | image: ollama/ollama:latest 4 | container_name: ollama 5 | volumes: 6 | - ollama:/root/.ollama 7 | ports: 8 | - "11434:11434" 9 | restart: unless-stopped 10 | 11 | open-webui: 12 | image: ghcr.io/open-webui/open-webui:main 13 | container_name: open-webui 14 | ports: 15 | - "3000:8080" 16 | volumes: 17 | - open-webui:/app/backend/data 18 | extra_hosts: 19 | - "host.docker.internal:host-gateway" 20 | restart: always 21 | 22 | volumes: 23 | ollama: 24 | name: ollama 25 | open-webui: 26 | name: open-webui 27 | -------------------------------------------------------------------------------- /deepseek_chainlit.py: -------------------------------------------------------------------------------- 1 | import chainlit as cl 2 | import ollama 3 | import json 4 | 5 | @cl.on_message 6 | async def main(message: cl.Message): 7 | # Create a message dictionary instead of using Message objects directly 8 | messages = [{'role': 'user', "content": str(message.content)}] 9 | 10 | # Create a message first 11 | msg = cl.Message(content="") 12 | await msg.send() 13 | 14 | # create a stream with ollama 15 | stream = ollama.chat( 16 | model='deepseek-r1:1.5b', 17 | messages= messages, 18 | stream= True 19 | ) 20 | 21 | # STREAM THE RESPONSE TOKEN BY TOKEN 22 | for chunk in stream: 23 | if token := chunk['message']['content']: 24 | await msg.stream_token(token) 25 | 26 | # Update msg final time 27 | await msg.update() 28 | 29 | @cl.on_chat_start 30 | async def start(): 31 | await cl.Message(content="Hello, AI Anytime! How can I help you today?").send() -------------------------------------------------------------------------------- /deepseek_streamlit.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import ollama 3 | 4 | # setting page title 5 | st.title("Chat with DeepSeek-r1 🐳 ") 6 | 7 | 8 | # Initialize chat history in session state if it doesn't exist 9 | if 'messages' not in st.session_state: 10 | st.session_state.messages = [ 11 | {'role': 'system', 'content': 'You are AI helpful assistant.'} 12 | ] 13 | 14 | # Display chat input box for user to enter their message 15 | user_input = st.chat_input("Your Message: ") 16 | 17 | # Display chat history and handle new user inputs 18 | for message in st.session_state.messages: 19 | if message['role'] != 'system': 20 | with st.chat_message(message['role']): 21 | st.write(message['content']) 22 | 23 | # If there is a new user input, process it 24 | if user_input: 25 | # Display the user's message in the chat interface 26 | with st.chat_message('user'): 27 | st.write(user_input) 28 | 29 | # Add the user's message to the chat history 30 | st.session_state.messages.append({'role': 'user', 'content': user_input}) 31 | 32 | # Get a streaming response from the AI model 33 | with st.chat_message('assistant'): 34 | message_placeholder = st.empty() 35 | full_response = "" 36 | 37 | # Send the chat history to the AI model and stream the response 38 | completion = ollama.chat( 39 | model='deepseek-r1:1.5b', 40 | messages=st.session_state.messages, 41 | stream=True 42 | ) 43 | 44 | # Process the streaming response from the AI model 45 | for chunk in completion: 46 | if 'message' in chunk and 'content' in chunk['message']: 47 | content = chunk['message']['content'] 48 | content = content.replace('', 'thinking.............................................\n').replace("", "\n\n\n\n Answer:") 49 | full_response += content 50 | message_placeholder.write(full_response + "|... ") 51 | 52 | # Display the full response from the AI model 53 | message_placeholder.write(full_response) 54 | 55 | # Add the AI model's response to the chat history 56 | st.session_state.messages.append({'role': 'assistant', 'content': full_response}) -------------------------------------------------------------------------------- /.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 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # UV 98 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | #uv.lock 102 | 103 | # poetry 104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 105 | # This is especially recommended for binary packages to ensure reproducibility, and is more 106 | # commonly ignored for libraries. 107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 108 | #poetry.lock 109 | 110 | # pdm 111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 112 | #pdm.lock 113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 114 | # in version control. 115 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 116 | .pdm.toml 117 | .pdm-python 118 | .pdm-build/ 119 | 120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 121 | __pypackages__/ 122 | 123 | # Celery stuff 124 | celerybeat-schedule 125 | celerybeat.pid 126 | 127 | # SageMath parsed files 128 | *.sage.py 129 | 130 | # Environments 131 | .env 132 | .venv 133 | env/ 134 | venv/ 135 | ENV/ 136 | env.bak/ 137 | venv.bak/ 138 | 139 | # Spyder project settings 140 | .spyderproject 141 | .spyproject 142 | 143 | # Rope project settings 144 | .ropeproject 145 | 146 | # mkdocs documentation 147 | /site 148 | 149 | # mypy 150 | .mypy_cache/ 151 | .dmypy.json 152 | dmypy.json 153 | 154 | # Pyre type checker 155 | .pyre/ 156 | 157 | # pytype static type analyzer 158 | .pytype/ 159 | 160 | # Cython debug symbols 161 | cython_debug/ 162 | 163 | # PyCharm 164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 166 | # and can be added to the global gitignore or merged into this file. For a more nuclear 167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 168 | #.idea/ 169 | 170 | # PyPI configuration file 171 | .pypirc 172 | --------------------------------------------------------------------------------