chatGPT官网经常会因为系统升级等情况而不能用, 有时候响应也特别慢, 于是API排上用场.
之前写了一个简易的命令窗式的问答, 能多轮对话, 还能保存对话, 但是输入很不方便.
回头一看额度才用了4毛钱, 于是在api免费期限还剩一个一个月的时候写了一个对话界面, 目前只是单轮对话,后期将加入更多功能, 尽最大努力用完剩下余额.
API接口
首先是chatGPT的接口, 这个网上例程很多, 主要是返回消息和所耗费的taken.
import os
import openai
import json
# from main_window import *
if os.getenv('chatgpt_key'):
openai.api_key = os.getenv('chatgpt_key')
else:
openai.api_key_path = "E:\chatgpt\key.txt"
def connect(message):
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=message
)
message = response["choices"][0]["message"]
token = int(response["usage"]["total_tokens"])
return token, message
主界面
主界面采用tkinter, 利用chatGPT先生成一个简单示例, 然后在此基础上不断优化界面, 在不拥专门学习这个库的情况下就能写出外观不错的界面, 可以很容易修改输入内容. 同时能够显示对话耗费了多少taken, 换算的多少刀.
代码如下, 没太注意格式风格, 只为快速迭代
import tkinter as tk
import time
import threading
import uChat_0.coreChat as core
class DarkChatGUI():
def __init__(self, title="Chat"):
self.title = title
self.message_user = ''
self.taken = 0
self.total_taken = 0
self.cost = 0
self.info = ''
font = 'Consolas'
# 创建主窗口
self.root = tk.Tk()
self.root.title(self.title)
self.root.configure(bg="black")
self.root.geometry("700x580")
# self.root.overrideredirect(True) # 使窗口没有边框和标题栏
# 创建聊天显示框
self.display_frame = tk.Frame(self.root, bg="#262626") # #262626 black
self.display_frame.pack(side="top", fill="both", expand=True)
self.chat_display = tk.Text(self.display_frame, bg="#2f2f2f", fg="white", wrap="word", state="disabled",
font=(font, 12))
self.chat_display.pack(side="top", fill="both", expand=True, padx=8, pady=8)
# 聊天显示样式设置
self.chat_display.tag_configure('user_name', background="red", font=(font, 12, 'bold'))
self.chat_display.tag_configure('ai_name', background="green", font=(font, 12, 'bold'))
self.chat_display.tag_configure('user_text', spacing1=10, spacing2=8, foreground='#D6D6D6')
self.chat_display.tag_configure('ai_text', spacing1=10, spacing2=8, foreground='#D6D6D6')
self.chat_display.tag_configure('info', foreground='orange', font=(font, 11, 'bold'))
# 创建信息输入框
self.input_frame = tk.Frame(self.root, bg="#262626")
self.input_frame.pack(side="bottom", fill="both", expand=False, padx=3, pady=3)
self.message_entry = tk.Text(self.input_frame, height=10, spacing3=10, bg="#2f2f2f",
fg="white", font=(font, 11), insertbackground='white')
self.message_entry.pack(side="left", fill="both", expand=True)
self.message_entry.tag_configure('text', spacing2=6, foreground='white')
# 发送按键
self.send_button = tk.Button(self.input_frame, text="Send", bg="#3860C0", fg="white",
font=(font, 12, 'bold'), command=self.send_message)
self.send_button.pack(side="left", fill="both")
# 监听 Enter 键
self.root.bind('<Control-Return>', self.send_message)
def send_message(self, event=None):
self.message_user = self.message_entry.get('0.0', "end").strip()
if self.message_user:
# cut_line = '\t '*7 + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
self.message_entry.delete('0.0', "end")
self.chat_display.configure(state="normal")
self.chat_display.insert("end", ' 我:\t', 'user_name')
print(self.info)
cut_line = '\n' + '--' * 40 + ''
self.chat_display.insert("end", cut_line, 'info')
self.chat_display.insert("end", '\n' + self.message_user + "\n\n", "user_text")
# 弹出提示框
self.chat_display.insert("end",
"\n\t\t\t---------- 等待AI回应 ---------\n", 'info')
# self.chat_display.configure(state="disabled")
self.chat_display.see(tk.END)
t = threading.Thread(target=self.receive_message, args=())
t.start()
# self.receive_message()
def receive_message(self):
send_message = [{"role": "user", "content": self.message_user}]
self.taken, message_r = core.connect(send_message)
message = message_r['content']
self.comp_taken()
if message:
# print(message)
self.chat_display.delete("end-2l", tk.END)
self.chat_display.configure(state="normal")
self.chat_display.insert("end", ' ChatGPT:\t', 'ai_name')
self.chat_display.insert("end", self.info, 'info')
self.chat_display.insert("end", '\n' + message + "\n\n", "ai_text")
self.chat_display.configure(state="disabled")
self.chat_display.see(tk.END)
def start(self):
self.root.mainloop()
def comp_taken(self):
self.total_taken += self.taken
self.cost = self.total_taken * 0.002/1000
self.info = '\t\tpast: ' + str(self.taken) + \
'\t\ttotal: ' + str(self.total_taken) + \
'\t\tcost: $' + str(round(self.cost, 4))
if __name__ == "__main__":
gui = DarkChatGUI()
gui.start()
后续有空了再加人更多功能, 例如对本地数据库文献库的管理, 还可以结合单机的本地模型. 实现高效学习和工作