Skip to content

Commit

Permalink
ChatzGPT-UI
Browse files Browse the repository at this point in the history
  • Loading branch information
xhunmon committed Apr 6, 2023
1 parent ea2e00c commit af17238
Show file tree
Hide file tree
Showing 13 changed files with 712 additions and 2 deletions.
129 changes: 129 additions & 0 deletions 008-ChatGPT-UI/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/
.idea/
41 changes: 41 additions & 0 deletions 008-ChatGPT-UI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Build your ChatGPT app.

![GPT-UI](doc/1.jpg)


# Run
- 1.clone this repo
- 2.edit your config.json
```json
{
"key": "your api key", //create at https://platform.openai.com/account/api-keys
"api_base": "",
"model": "gpt-3.5-turbo", //support: gpt-3.5-turbo/gpt-4/gpt-4-32k
"stream": true,
"response": true,
"folder": "/Users/Qincji/Desktop/gptfileout/", //directory where chat logs are saved
"repeat": true, //if false: all chats in one file. if true: each chat is in a new file
"proxy": "socks5://127.0.0.1:7890" //support proxy: HTTP/HTTPS/SOCKS4A/SOCKS5
}

```
- 3.run main.py


# Build App
- 4.install pyinstaller
- 5.cd `GPT-UI`
- 6.run `pyinstaller --windowed --name GPT-UI --add-data "config.ini:." --icon logo.ico main.py gpt.py utils.py`


# Feature
- [x] Support model: gpt-3.5-turbo/gpt-4/gpt-4-32k
- [x] Support for exporting chat logs to files
- [x] Support proxy: HTTP/HTTPS/SOCKS4A/SOCKS5
- [x] Build MacOS App
- [x] Build Window exe
- [ ] Support for generating images

# Link
- API key generated: [https://platform.openai.com/account/api-keys](https://platform.openai.com/account/api-keys)
- [https://github.com/evilpan/gptcli](https://github.com/evilpan/gptcli)
10 changes: 10 additions & 0 deletions 008-ChatGPT-UI/config.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[common]
expired_time=2025/12/15 23:59:59

title=GPT-UI

version_name=v1.0.1--github/xhunmon

version_code=1010

email=xhunmon@126.com
10 changes: 10 additions & 0 deletions 008-ChatGPT-UI/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"key": "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",
"api_base": "",
"model": "gpt-3.5-turbo",
"stream": true,
"response": true,
"folder": "",
"repeat": true,
"proxy": "socks5://127.0.0.1:7890"
}
Binary file added 008-ChatGPT-UI/doc/1.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions 008-ChatGPT-UI/doc/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"api_base": "",
"key": "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",
"model": "gpt-3.5-turbo",
"stream": true,
"response": true,
"folder": "/Users/Qincji/Desktop/develop/py/opengpt/gptcli/doc/",
"repeat": true,
"proxy": "socks5://127.0.0.1:7890"
}
7 changes: 7 additions & 0 deletions 008-ChatGPT-UI/doc/pyinstaller.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash


pyinstaller --windowed --name GPT-UI --add-data "config.ini:." --icon logo.ico main.py gpt.py utils.py

#if use --onefile, the build file is small, but star very slow.
#pyinstaller --onefile --windowed --name GPT-UI --add-data "config.ini:." --icon logo.ico main.py gpt.py utils.py
138 changes: 138 additions & 0 deletions 008-ChatGPT-UI/gpt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
@Description:gpt.py
@Date :2023/03/31
@Author :xhunmon
@Mail :xhunmon@126.com
"""

import time
from datetime import datetime

from utils import *


class Gpt(object):
func_ui_print = None

def __init__(self, config: Config):
self.session = []
self.api_prompt = []
self.update_config(config)
self.content = ""
self.is_change = False
self.is_finish = True
gpt_t = threading.Thread(target=self.start)
gpt_t.setDaemon(True)
gpt_t.start()

def update_config(self, config: Config):
self.cfg = config
self.api_key = self.cfg.api_key
self.api_base = self.cfg.api_base
self.api_model = self.cfg.model
self.api_stream = self.cfg.stream
self.api_response = self.cfg.response
self.proxy = self.cfg.proxy
openai.api_key = self.api_key
if self.api_base:
openai.api_base = self.api_base
openai.proxy = self.proxy

def start(self):
while True:
if self.is_finish:
while not self.is_change:
time.sleep(0.3)
self.print("\nMY:\n{}".format(self.content))
self.print("\nGPT:\n")
self.is_change = False
self.is_finish = False
self.handle_input(self.content)
time.sleep(1)

def print(self, content):
Gpt.func_ui_print(content)

def query_openai_stream(self, data: dict) -> str:
messages = []
messages.extend(self.api_prompt)
messages.extend(data)
answer = ""
try:
response = openai.ChatCompletion.create(
model=self.api_model,
messages=messages,
stream=True)
for part in response:
finish_reason = part["choices"][0]["finish_reason"]
if "content" in part["choices"][0]["delta"]:
content = part["choices"][0]["delta"]["content"]
answer += content
self.print(content)
elif finish_reason:
pass

except KeyboardInterrupt:
self.print("Canceled")
except openai.error.OpenAIError as e:
self.print("OpenAIError:{}".format(e))
answer = ""
return answer

def content_change(self, content: str):
if not content:
return
if self.content != content:
self.content = content
self.is_change = True

def handle_input(self, content: str):
if not content:
return
self.is_finish = False
self.session.append({"role": "user", "content": content})
if self.api_stream:
answer = self.query_openai_stream(self.session)
else:
answer = self.query_openai(self.session)
if not answer:
self.session.pop()
elif self.api_response:
self.session.append({"role": "assistant", "content": answer})
if answer:
try:
if self.cfg.folder and not os.path.exists(self.cfg.folder):
os.makedirs(self.cfg.folder)
wfile = os.path.join(self.cfg.folder, "gpt.md" if self.cfg.repeat else "gpt_{}.md".format(
datetime.now().strftime("%Y%m%d%H%M:%S")))
if self.cfg.repeat:
with open(wfile, mode='a', encoding="utf-8") as f:
f.write("MY:\n{}\n".format(content))
f.write("\nGPT:\n{}\n\n".format(answer))
f.close()
else:
with open(wfile, mode='w', encoding="utf-8") as f:
f.write("MY:\n{}\n".format(content))
f.write("\nGPT:{}".format(answer))
f.close()
except Exception as e:
self.print("Write error: {} ".format(e))
self.is_finish = True

def query_openai(self, data: dict) -> str:
messages = []
messages.extend(self.api_prompt)
messages.extend(data)
try:
response = openai.ChatCompletion.create(
model=self.api_model,
messages=messages
)
content = response["choices"][0]["message"]["content"]
self.print(content)
return content
except openai.error.OpenAIError as e:
self.print("OpenAI error: {} ".format(e))
return ""
Binary file added 008-ChatGPT-UI/logo.ico
Binary file not shown.

0 comments on commit af17238

Please sign in to comment.