├── requirements.txt ├── pages ├── 3_📋_Session.py ├── 4_💡_About.py ├── 2_📊_Test.py └── 1_🎭_Chat.py ├── run.bat ├── run.sh ├── .vscode └── launch.json ├── LICENSE ├── .devcontainer └── devcontainer.json ├── aliyun_serveless.yaml ├── README.md ├── comm_lib.py ├── .gitignore └── 0_Playground.py /requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | streamlit 3 | openai 4 | pandas -------------------------------------------------------------------------------- /pages/3_📋_Session.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | 4 | def main(): 5 | st.set_page_config(page_title='Session', page_icon='📋', layout='wide', initial_sidebar_state='auto') 6 | st.title("Streamlit Session State") 7 | st.write(st.session_state) 8 | 9 | 10 | if __name__ == "__main__": 11 | main() 12 | -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set VENV_DIR=venv 4 | set REQUIREMENTS_FILE=requirements.txt 5 | set PYTHON_SCRIPT=0_Playground.py 6 | 7 | if not exist "%VENV_DIR%\" ( 8 | python -m venv %VENV_DIR% 9 | 10 | if exist "%REQUIREMENTS_FILE%" ( 11 | %VENV_DIR%\Scripts\pip install -r "%REQUIREMENTS_FILE%" 12 | ) 13 | ) 14 | 15 | %VENV_DIR%\Scripts\streamlit run "%PYTHON_SCRIPT%" %* 16 | pause -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VENV_DIR="venv" 4 | REQUIREMENTS_FILE="requirements.txt" 5 | PYTHON_SCRIPT="0_Playground.py" 6 | 7 | if [ ! -d "${VENV_DIR}" ]; then 8 | python3 -m venv "${VENV_DIR}" 9 | 10 | if [ -f "${REQUIREMENTS_FILE}" ]; then 11 | ${VENV_DIR}/bin/pip install -r "${REQUIREMENTS_FILE}" 12 | fi 13 | fi 14 | 15 | sudo "${VENV_DIR}/bin/streamlit run" "${PYTHON_SCRIPT}" "$@" -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Python: Current File", 9 | "type": "python", 10 | "request": "launch", 11 | "program": "${file}", 12 | "console": "integratedTerminal", 13 | "justMyCode": true 14 | }, 15 | { 16 | "name": "Streamlit: Run Current File", 17 | "type": "python", 18 | "request": "launch", 19 | "module": "streamlit", 20 | "args": [ 21 | "run", 22 | "${file}" 23 | ], 24 | "justMyCode": true 25 | } 26 | 27 | ] 28 | } -------------------------------------------------------------------------------- /pages/4_💡_About.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | 3 | 4 | def main(): 5 | st.set_page_config(page_title='About', page_icon='💡', layout='wide', initial_sidebar_state='auto') 6 | st.title("About") 7 | st.image('https://github.com/hanckjt/openai_api_playground/assets/16874002/ce6eff49-51a9-45ed-936e-70fb3e12137e', width=512) 8 | st.write( 9 | ''' 10 | The reason why I developed this online application is because I enjoy researching various new LLMs, 11 | including open source and closed source online(API). However, after deploying the server, 12 | I often have to test it. I searched online for a long time but couldn't find a good one, 13 | so I wrote one myself with streamlit, you can play any API server that is compatible with OpenAI API, 14 | hoping to help friends with similar needs. 15 | ''' 16 | ) 17 | st.write('Github: https://github.com/hanckjt/openai_api_playground') 18 | 19 | 20 | if __name__ == "__main__": 21 | main() 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Hank 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 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Python 3", 3 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 4 | "image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye", 5 | "customizations": { 6 | "codespaces": { 7 | "openFiles": [ 8 | "README.md", 9 | "0_Playground.py" 10 | ] 11 | }, 12 | "vscode": { 13 | "settings": {}, 14 | "extensions": [ 15 | "ms-python.python", 16 | "ms-python.vscode-pylance" 17 | ] 18 | } 19 | }, 20 | "updateContentCommand": "[ -f packages.txt ] && sudo apt update && sudo apt upgrade -y && sudo xargs apt install -y - 17 | /opt/python3.10/bin:/usr/local/bin/apache-maven/bin:/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/ruby/bin:/opt/bin:/code:/code/bin 18 | PYTHONPATH: /opt/python:/code 19 | LD_LIBRARY_PATH: >- 20 | /code:/code/lib:/usr/local/lib:/opt/lib:/opt/php8.1/lib:/opt/php8.0/lib:/opt/php7.2/lib 21 | layers: 22 | - acs:fc:us-west-1:official:layers/Python310/versions/2 23 | - >- 24 | acs:fc:us-west-1:official:layers/Python310-Package-Collection/versions/2 25 | - acs:fc:us-west-1:official:layers/Python3-Flask2x/versions/2 26 | memorySize: 256 27 | cpu: 0.2 28 | timeout: 60 29 | codeUri: ./ 30 | diskSize: 512 31 | caPort: 8501 32 | customRuntimeConfig: 33 | command: 34 | - sh 35 | args: 36 | - run.sh 37 | triggers: 38 | - name: httpTrigger 39 | type: http 40 | config: 41 | authType: anonymous 42 | methods: 43 | - GET 44 | - POST 45 | - PUT 46 | - DELETE 47 | - HEAD 48 | - PATCH 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenAI API Playground 2 | 3 | 4 | 5 | The reason why I developed this online application is because I enjoy researching various new LLMs, including open source and closed source online. 6 | However, after deploying the server, I often have to test it. I searched online for a long time but couldn't find a good one, so I wrote one myself with streamlit. 7 | You can play any API server that compatible with OpenAI API, hoping to help friends with similar needs. 8 | 9 | Try it on streamlit cloud: [https://openai-api-playground.streamlit.app/](https://openai-api-playground.streamlit.app/) 10 | 11 | ![91bf86c9b3830da22b9a396f7614edd](https://github.com/hanckjt/openai_api_playground/assets/16874002/0090d833-2e87-4d24-8e00-589d78954a60) 12 | ![a20236222dca67f84e9a610091912de](https://github.com/hanckjt/openai_api_playground/assets/16874002/7e3d8ea5-8e5b-471a-bbd5-997829d41c4e) 13 | ![bc273669795010b976d3cb9d7a94505](https://github.com/hanckjt/openai_api_playground/assets/16874002/063bc804-d0ab-4ecf-ad91-a02eb49bd735) 14 | 15 | ## Feature List: 16 | 17 | - [X] Set API server URL and KEY 18 | - [X] List all models on the server and informations 19 | - [X] Specify a model and set its parameters 20 | - [X] Support for stream or non-stream mode 21 | - [X] Test the connection latency of the API server 22 | - [X] Test the token generation speed of the model with concurrency 23 | - [X] View the complete session state content of Streamlit 24 | - [ ] Support multimodal model, including images, audio or video 25 | - [ ] Conduct Q&A interactions using uploaded text files as a knowledge base 26 | - [ ] Support for online content search for reference 27 | 28 | ## Usage Instructions: 29 | 30 | ### 1. Download the Repository: 31 | 32 | ```bash 33 | git clone https://github.com/hanckjt/openai_api_playground.git 34 | cd openai_api_playground 35 | ``` 36 | 37 | ### 2. Run the Script: 38 | 39 | Linux: 40 | 41 | ```bash 42 | chmod +x run.sh 43 | ./run.sh 44 | ``` 45 | 46 | Windows: 47 | 48 | ```bash 49 | run.bat 50 | ``` 51 | -------------------------------------------------------------------------------- /comm_lib.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import openai 3 | import requests 4 | 5 | 6 | def test_speed_with_system_proxy(url, timeout=5): 7 | return requests.get(url, timeout=timeout).elapsed.total_seconds() * 1000.0 8 | 9 | 10 | @st.cache_resource 11 | def get_openai_client(): 12 | client = openai.OpenAI(base_url=get_app_setting('base_url', ''), api_key=get_app_setting('api_key', '')) 13 | return client 14 | 15 | 16 | def set_openai_client(base_url, api_key): 17 | set_app_setting('base_url', base_url) 18 | set_app_setting('api_key', api_key) 19 | get_openai_client.clear() 20 | 21 | 22 | def openai_completion(prompt, model, max_tokens=512, temperature=0.7, top_p=1, n=1, stream=False, logprobs=None, stop=None, presence_penalty=0, frequency_penalty=0, best_of=1, echo=False): 23 | return get_openai_client().completions.create(prompt=prompt, model=model) 24 | 25 | 26 | def openai_chat_completion(messages, model, stream=True, max_tokens=512, temperature=0.7, top_p=1.0, timeout=10): 27 | response = get_openai_client().chat.completions.create(messages=messages, model=model, max_tokens=max_tokens, stream=stream, temperature=temperature, top_p=top_p, timeout=timeout) 28 | 29 | return response 30 | 31 | 32 | def get_session_state(name, default=None): 33 | if name not in st.session_state: 34 | st.session_state[name] = default 35 | 36 | return st.session_state[name] 37 | 38 | 39 | def set_session_state(name, value): 40 | st.session_state[name] = value 41 | 42 | 43 | def get_app_setting(name, default=None): 44 | return get_session_state('settings', {}).get(name, default) 45 | 46 | 47 | def set_app_setting(name, value): 48 | get_session_state('settings', {})[name] = value 49 | 50 | 51 | def clear_app_setting(): 52 | set_session_state('settings', {}) 53 | 54 | 55 | def get_chat_history(): 56 | return get_session_state('chat_history', []) 57 | 58 | 59 | def add_chat_history(role, content): 60 | get_chat_history().append({'role': role, 'content': content}) 61 | 62 | 63 | def reset_chat_history(): 64 | set_session_state('chat_history', []) 65 | add_chat_history('system', get_app_setting('system_prompt', 'You are a hellpful assistant.')) 66 | 67 | 68 | def test(): 69 | st.write('test') 70 | reset_chat_history() 71 | add_chat_history('user', 'test') 72 | st.write(get_chat_history()) 73 | 74 | set_app_setting('base_url', 'my_base_url') 75 | st.write(get_app_setting('base_url')) 76 | 77 | 78 | if __name__ == "__main__": 79 | test() 80 | -------------------------------------------------------------------------------- /pages/2_📊_Test.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import time 3 | import asyncio 4 | from concurrent.futures import ThreadPoolExecutor 5 | 6 | from comm_lib import * 7 | 8 | 9 | def ask_openai(client, model, question): 10 | messages = [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": question}] 11 | response = client.chat.completions.create(messages=messages, model=model, max_tokens=512, stream=False) 12 | 13 | return response 14 | 15 | 16 | async def get_responses(client, model, questions): 17 | with ThreadPoolExecutor() as executor: 18 | loop = asyncio.get_event_loop() 19 | futures = [loop.run_in_executor(executor, ask_openai, client, model, question) for question in questions] 20 | return await asyncio.gather(*futures) 21 | 22 | 23 | def main(): 24 | st.set_page_config(page_title='Test', page_icon='📊', layout='wide', initial_sidebar_state='auto') 25 | model = get_app_setting('model') 26 | if not model: 27 | st.error('Please set the right API settings first.') 28 | return 29 | st.title(f'API Test: {model}') 30 | 31 | with st.container(border=True): 32 | st.write('Base URL Latency') 33 | cols = st.columns([0.6, 0.2, 0.2]) 34 | base_url = cols[0].text_input('Base URL', get_app_setting('base_url', 'https://api.openai.com/v1'), key='base_url') 35 | if cols[1].button('Connect Latency'): 36 | latency = test_speed_with_system_proxy(base_url) 37 | cols[2].write(f'Latency: {latency:.2f} ms') 38 | 39 | with st.container(border=True): 40 | st.write('Tokens Generate Speed:') 41 | cols = st.columns(2) 42 | prompt = cols[0].text_input('Prompt', 'Tell me a short joke.') 43 | concurrency = cols[1].number_input('Concurrency', 1, 100, 1) 44 | prompts = [prompt] * concurrency 45 | openai_client = get_openai_client() 46 | if st.button('Test Speed'): 47 | with st.chat_message('user'): 48 | st.markdown(prompt) 49 | with st.spinner('Testing...'): 50 | start_time = time.time() 51 | try: 52 | responses = asyncio.run(get_responses(openai_client, model, prompts)) 53 | except Exception as e: 54 | st.error(e) 55 | return 56 | end_time = time.time() 57 | completion_tokens = 0 58 | for i, response in enumerate(responses): 59 | with st.chat_message('assistant'): 60 | st.write(f'[{i+1}]: {response.choices[0].message.content}') 61 | completion_tokens += response.usage.completion_tokens 62 | speed = completion_tokens / (end_time - start_time) 63 | st.write(f'Speed: {speed:.2f} tokens/s') 64 | # with st.expander('Response'): 65 | # st.write(response) 66 | 67 | 68 | if __name__ == "__main__": 69 | main() 70 | -------------------------------------------------------------------------------- /pages/1_🎭_Chat.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | from comm_lib import * 3 | 4 | 5 | def chat_page(): 6 | model = get_app_setting('model') 7 | if not model: 8 | st.error('Please set the right API settings first.') 9 | return 10 | st.title(f'Chat: {model}') 11 | chat_tool = st.columns([0.6, 0.2, 0.2]) 12 | uploaded_file = chat_tool[0].file_uploader('Upload File', key='upload_file') 13 | file_type = chat_tool[1].selectbox('File Type', ['Text', 'Image', 'Audio', 'Video'], key='file_type') 14 | if chat_tool[2].button('Clean History'): 15 | reset_chat_history() 16 | if chat_tool[2].button('Regenerate'): 17 | get_chat_history().pop() 18 | set_session_state('regenerate', True) 19 | 20 | for msg in get_chat_history(): 21 | with st.chat_message(msg['role']): 22 | st.markdown(msg['content']) 23 | 24 | need_regenerate = get_session_state('regenerate', False) 25 | user_input = st.chat_input('User Input', key='user_input') 26 | if user_input or need_regenerate: 27 | if need_regenerate: 28 | user_input = get_session_state('last_user_input', '') 29 | else: 30 | add_chat_history('user', user_input) 31 | with st.chat_message('user'): 32 | st.markdown(user_input) 33 | max_tokens = get_app_setting('max_tokens', 512) 34 | temperature = get_app_setting('temperature', 0.7) 35 | top_p = get_app_setting('top_p', 1.0) 36 | stream = get_app_setting('stream', True) 37 | timeout = get_app_setting('timeout', 10) 38 | with st.chat_message('assistant'): 39 | with st.spinner('Thinking...'): 40 | try: 41 | response = openai_chat_completion(get_chat_history(), model, stream, max_tokens, temperature, top_p, timeout) 42 | except Exception as e: 43 | st.error(e) 44 | return 45 | if response: 46 | if stream: 47 | placeholder = st.empty() 48 | streaming_text = '' 49 | for chunk in response: 50 | if chunk.choices[0].finish_reason == 'stop': 51 | break 52 | chunk_text = chunk.choices[0].delta.content 53 | if chunk_text: 54 | streaming_text += chunk_text 55 | placeholder.markdown(streaming_text) 56 | model_msg = streaming_text 57 | else: 58 | model_msg = response.choices[0].message.content 59 | with st.chat_message('assistant'): 60 | st.markdown(model_msg) 61 | 62 | set_session_state('last_user_input', user_input) 63 | if need_regenerate: 64 | set_session_state('regenerate', False) 65 | 66 | add_chat_history('assistant', model_msg) 67 | 68 | 69 | def main(): 70 | st.set_page_config(page_title='Chat', page_icon='🎭', layout='wide', initial_sidebar_state='auto') 71 | chat_page() 72 | 73 | 74 | if __name__ == "__main__": 75 | main() 76 | -------------------------------------------------------------------------------- /.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 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /0_Playground.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import pandas as pd 3 | from comm_lib import * 4 | 5 | 6 | @st.cache_data 7 | def get_models_df(): 8 | if get_app_setting('api_key', 'YOUR_API_KEY') == 'YOUR_API_KEY': 9 | return None 10 | try: 11 | models = get_openai_client().models.list().to_dict()['data'] 12 | except Exception as e: 13 | st.error(e) 14 | return None 15 | df = pd.DataFrame(models) 16 | if 'created' in df.columns: 17 | df['created'] = pd.to_datetime(df['created'], unit='s') 18 | if 'permission' in df.columns: 19 | permission_df = df['permission'].apply(lambda x: x[0] if x else []).apply(pd.Series) 20 | permission_df.drop(columns=['id', 'created', 'object'], inplace=True) 21 | df = df.drop(columns=['permission']).join(permission_df) 22 | return df 23 | 24 | 25 | def show_models_page(): 26 | st.title('Models List:') 27 | models_df = get_models_df() 28 | if models_df is None: 29 | st.warning('Please set API settings first.') 30 | else: 31 | st.dataframe(models_df) 32 | 33 | 34 | def settings_page(): 35 | st.title('Settings') 36 | with st.form(key='openai_api_settings_form'): 37 | base_url = st.text_input('Base URL', get_app_setting('base_url', 'https://api.openai.com/v1'), key='base_url') 38 | api_key = st.text_input('API Key', get_app_setting('api_key', 'YOUR_API_KEY'), type='password', key='api_key') 39 | if st.form_submit_button('Get Models') or not get_session_state('inited', False): 40 | clear_app_setting() 41 | set_openai_client(base_url, api_key) 42 | get_models_df.clear() 43 | reset_chat_history() 44 | set_session_state('inited', True) 45 | 46 | if get_app_setting('api_key', 'YOUR_API_KEY') == 'YOUR_API_KEY': 47 | return 48 | 49 | models_df = get_models_df() 50 | if models_df is None: 51 | with st.container(border=True): 52 | st.text('Get models from OpenAI API failed, you can set the model name manually.') 53 | model_name = st.text_input('Model Name', get_app_setting('model', 'gpt-3.5-turbo'), key='model_name') 54 | models_df = pd.DataFrame([{'id': model_name, 'created': pd.to_datetime('now'), 'object': 'model'}]) 55 | 56 | with st.form(key='model_settings_form'): 57 | models = models_df['id'].tolist() 58 | model = get_app_setting('model', models[0]) 59 | if model in models: 60 | model_index = models.index(get_app_setting('model', models[0])) 61 | model_selected = st.selectbox('Select Models', models, key='select_model', index=model_index) 62 | else: 63 | model_selected = model 64 | model = st.text_input('Model (you can change name manually if it is not in the models list)', model_selected, key='model') 65 | max_tokens = st.number_input('Max Tokens', 1, 200000, get_app_setting('max_tokens', 512), key='max_tokens') 66 | temperature = st.slider('Temperature', 0.0, 1.0, get_app_setting('temperature', 0.7), key='temperature') 67 | top_p = st.slider('Top P', 0.0, 1.0, get_app_setting('top_p', 1.0), key='top_p') 68 | timeout = st.slider('Time Out', 1, 60, get_app_setting('timeout', 10), key='timeout') 69 | system_prompt = st.text_input('System Prompt', get_app_setting('system_prompt', 'You are a hellpful assistant.'), key='system_prompt') 70 | stream = st.checkbox('Stream', get_app_setting('stream', True), key='stream') 71 | if st.form_submit_button('Confirm'): 72 | set_app_setting('model', model) 73 | set_app_setting('max_tokens', max_tokens) 74 | set_app_setting('temperature', temperature) 75 | set_app_setting('top_p', top_p) 76 | set_app_setting('timeout', timeout) 77 | set_app_setting('stream', stream) 78 | set_app_setting('system_prompt', system_prompt) 79 | 80 | reset_chat_history() 81 | st.toast('Model Settings Updated') 82 | 83 | 84 | def main(): 85 | st.set_page_config(page_title='OpenAI API Playground', page_icon=':robot_face:', layout='wide', initial_sidebar_state='auto') 86 | # hide streamlit footer 87 | # hide_streamlit_style = """ 88 | # 92 | # """ 93 | # st.markdown(hide_streamlit_style, unsafe_allow_html=True) 94 | settings_page() 95 | 96 | show_models_page() 97 | 98 | 99 | if __name__ == '__main__': 100 | main() 101 | --------------------------------------------------------------------------------