Skip to content

Commit af17238

Browse files
committed
ChatzGPT-UI
1 parent ea2e00c commit af17238

File tree

13 files changed

+712
-2
lines changed

13 files changed

+712
-2
lines changed

008-ChatGPT-UI/.gitignore

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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+
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+
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+
# Spyder project settings
113+
.spyderproject
114+
.spyproject
115+
116+
# Rope project settings
117+
.ropeproject
118+
119+
# mkdocs documentation
120+
/site
121+
122+
# mypy
123+
.mypy_cache/
124+
.dmypy.json
125+
dmypy.json
126+
127+
# Pyre type checker
128+
.pyre/
129+
.idea/

008-ChatGPT-UI/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
Build your ChatGPT app.
2+
3+
![GPT-UI](doc/1.jpg)
4+
5+
6+
# Run
7+
- 1.clone this repo
8+
- 2.edit your config.json
9+
```json
10+
{
11+
"key": "your api key", //create at https://platform.openai.com/account/api-keys
12+
"api_base": "",
13+
"model": "gpt-3.5-turbo", //support: gpt-3.5-turbo/gpt-4/gpt-4-32k
14+
"stream": true,
15+
"response": true,
16+
"folder": "/Users/Qincji/Desktop/gptfileout/", //directory where chat logs are saved
17+
"repeat": true, //if false: all chats in one file. if true: each chat is in a new file
18+
"proxy": "socks5://127.0.0.1:7890" //support proxy: HTTP/HTTPS/SOCKS4A/SOCKS5
19+
}
20+
21+
```
22+
- 3.run main.py
23+
24+
25+
# Build App
26+
- 4.install pyinstaller
27+
- 5.cd `GPT-UI`
28+
- 6.run `pyinstaller --windowed --name GPT-UI --add-data "config.ini:." --icon logo.ico main.py gpt.py utils.py`
29+
30+
31+
# Feature
32+
- [x] Support model: gpt-3.5-turbo/gpt-4/gpt-4-32k
33+
- [x] Support for exporting chat logs to files
34+
- [x] Support proxy: HTTP/HTTPS/SOCKS4A/SOCKS5
35+
- [x] Build MacOS App
36+
- [x] Build Window exe
37+
- [ ] Support for generating images
38+
39+
# Link
40+
- API key generated: [https://platform.openai.com/account/api-keys](https://platform.openai.com/account/api-keys)
41+
- [https://github.com/evilpan/gptcli](https://github.com/evilpan/gptcli)

008-ChatGPT-UI/config.ini

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[common]
2+
expired_time=2025/12/15 23:59:59
3+
4+
title=GPT-UI
5+
6+
version_name=v1.0.1--github/xhunmon
7+
8+
version_code=1010
9+
10+

008-ChatGPT-UI/config.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"key": "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",
3+
"api_base": "",
4+
"model": "gpt-3.5-turbo",
5+
"stream": true,
6+
"response": true,
7+
"folder": "",
8+
"repeat": true,
9+
"proxy": "socks5://127.0.0.1:7890"
10+
}

008-ChatGPT-UI/doc/1.jpg

49.4 KB
Loading

008-ChatGPT-UI/doc/config.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"api_base": "",
3+
"key": "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",
4+
"model": "gpt-3.5-turbo",
5+
"stream": true,
6+
"response": true,
7+
"folder": "/Users/Qincji/Desktop/develop/py/opengpt/gptcli/doc/",
8+
"repeat": true,
9+
"proxy": "socks5://127.0.0.1:7890"
10+
}

008-ChatGPT-UI/doc/pyinstaller.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/bin/bash
2+
3+
4+
pyinstaller --windowed --name GPT-UI --add-data "config.ini:." --icon logo.ico main.py gpt.py utils.py
5+
6+
#if use --onefile, the build file is small, but star very slow.
7+
#pyinstaller --onefile --windowed --name GPT-UI --add-data "config.ini:." --icon logo.ico main.py gpt.py utils.py

008-ChatGPT-UI/gpt.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#!/usr/bin/env python
2+
# -*- encoding: utf-8 -*-
3+
"""
4+
@Description:gpt.py
5+
@Date :2023/03/31
6+
@Author :xhunmon
7+
8+
"""
9+
10+
import time
11+
from datetime import datetime
12+
13+
from utils import *
14+
15+
16+
class Gpt(object):
17+
func_ui_print = None
18+
19+
def __init__(self, config: Config):
20+
self.session = []
21+
self.api_prompt = []
22+
self.update_config(config)
23+
self.content = ""
24+
self.is_change = False
25+
self.is_finish = True
26+
gpt_t = threading.Thread(target=self.start)
27+
gpt_t.setDaemon(True)
28+
gpt_t.start()
29+
30+
def update_config(self, config: Config):
31+
self.cfg = config
32+
self.api_key = self.cfg.api_key
33+
self.api_base = self.cfg.api_base
34+
self.api_model = self.cfg.model
35+
self.api_stream = self.cfg.stream
36+
self.api_response = self.cfg.response
37+
self.proxy = self.cfg.proxy
38+
openai.api_key = self.api_key
39+
if self.api_base:
40+
openai.api_base = self.api_base
41+
openai.proxy = self.proxy
42+
43+
def start(self):
44+
while True:
45+
if self.is_finish:
46+
while not self.is_change:
47+
time.sleep(0.3)
48+
self.print("\nMY:\n{}".format(self.content))
49+
self.print("\nGPT:\n")
50+
self.is_change = False
51+
self.is_finish = False
52+
self.handle_input(self.content)
53+
time.sleep(1)
54+
55+
def print(self, content):
56+
Gpt.func_ui_print(content)
57+
58+
def query_openai_stream(self, data: dict) -> str:
59+
messages = []
60+
messages.extend(self.api_prompt)
61+
messages.extend(data)
62+
answer = ""
63+
try:
64+
response = openai.ChatCompletion.create(
65+
model=self.api_model,
66+
messages=messages,
67+
stream=True)
68+
for part in response:
69+
finish_reason = part["choices"][0]["finish_reason"]
70+
if "content" in part["choices"][0]["delta"]:
71+
content = part["choices"][0]["delta"]["content"]
72+
answer += content
73+
self.print(content)
74+
elif finish_reason:
75+
pass
76+
77+
except KeyboardInterrupt:
78+
self.print("Canceled")
79+
except openai.error.OpenAIError as e:
80+
self.print("OpenAIError:{}".format(e))
81+
answer = ""
82+
return answer
83+
84+
def content_change(self, content: str):
85+
if not content:
86+
return
87+
if self.content != content:
88+
self.content = content
89+
self.is_change = True
90+
91+
def handle_input(self, content: str):
92+
if not content:
93+
return
94+
self.is_finish = False
95+
self.session.append({"role": "user", "content": content})
96+
if self.api_stream:
97+
answer = self.query_openai_stream(self.session)
98+
else:
99+
answer = self.query_openai(self.session)
100+
if not answer:
101+
self.session.pop()
102+
elif self.api_response:
103+
self.session.append({"role": "assistant", "content": answer})
104+
if answer:
105+
try:
106+
if self.cfg.folder and not os.path.exists(self.cfg.folder):
107+
os.makedirs(self.cfg.folder)
108+
wfile = os.path.join(self.cfg.folder, "gpt.md" if self.cfg.repeat else "gpt_{}.md".format(
109+
datetime.now().strftime("%Y%m%d%H%M:%S")))
110+
if self.cfg.repeat:
111+
with open(wfile, mode='a', encoding="utf-8") as f:
112+
f.write("MY:\n{}\n".format(content))
113+
f.write("\nGPT:\n{}\n\n".format(answer))
114+
f.close()
115+
else:
116+
with open(wfile, mode='w', encoding="utf-8") as f:
117+
f.write("MY:\n{}\n".format(content))
118+
f.write("\nGPT:{}".format(answer))
119+
f.close()
120+
except Exception as e:
121+
self.print("Write error: {} ".format(e))
122+
self.is_finish = True
123+
124+
def query_openai(self, data: dict) -> str:
125+
messages = []
126+
messages.extend(self.api_prompt)
127+
messages.extend(data)
128+
try:
129+
response = openai.ChatCompletion.create(
130+
model=self.api_model,
131+
messages=messages
132+
)
133+
content = response["choices"][0]["message"]["content"]
134+
self.print(content)
135+
return content
136+
except openai.error.OpenAIError as e:
137+
self.print("OpenAI error: {} ".format(e))
138+
return ""

008-ChatGPT-UI/logo.ico

37.2 KB
Binary file not shown.

0 commit comments

Comments
 (0)