# Chapter4. 打造自己的 ChatGPT
:+1: 完整程式碼在 https://github.com/iamalex33329/chatgpt-develop-guide-zhtw
## 其他章節
[Chapter1. OpenAI API 入門](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/S1cNMYi6T)
[Chapter2. 使用 Python 呼叫 API](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/HyZBg5ia6)
[Chapter3. API 參數解析與錯誤處理](https://hackmd.io/@U3f2IzHERbymAst2-lDdjA/BJWNtsh6p)
[Chapter5. 突破時空限制 - 整合搜尋功能](https://hackmd.io/@112356044/HkbVM-ApT)
[Chapter6. 讓 AI 幫 AI - 自動串接流程](https://hackmd.io/@112356044/r1Ke-GR6T)
[Chapter7. 網頁版聊天程式與文字生圖 Image API](https://hackmd.io/@112356044/Hyf-AvgAT)
[Chapter8. 設計 LINE AI 聊天機器人](https://hackmd.io/@112356044/r1d6HsgAa)
[Chapter9. 自媒體業者必看!使用 AI 自動生成高品質字幕](https://hackmd.io/@112356044/rJ2T37V0T)
[Chapter10. 把 AI 帶到 Discord](https://hackmd.io/@112356044/Sy_L-B40T)
[Chapter11. AI 客製化投資理財應用實戰](https://hackmd.io/@112356044/HkUE0rER6)
[Chapter12. 用 LangChain 實作新書宣傳自動小編](https://hackmd.io/@112356044/SybvbdN0p)
## 目錄結構
[TOC]
## 文字模式簡易聊天程式
先把與 openai 傳送訊息的部分獨立成 `get_reply()` 函式
``` python=
def get_reply(messages):
try:
response = openai.ChatCompletion.create(
model='gpt-3.5-turbo',
messages=messages
)
reply = response['choices'][0]['message']['content']
except openai.OpenAIError as err:
reply = f'Error Type: {err.error.type}\nError msg: {err.error.message}'
return reply
```
接下來寫一個無窮迴圈,讓使用者能夠持續輸入文字,達到聊天的效果
``` python=+
while True:
user_msg = input('=> ')
if not user_msg.strip(): break
user_messages = [{'role': 'user', 'content': user_msg}]
ai_msg = get_reply(user_messages)
print(f'=> {ai_msg}\n')
```
但這裡**有個問題**,openai 並不能延續先前的對話脈絡(因為每次對話都是呼叫新的)
## 加入聊天記錄維持聊天脈絡
我們可以定義兩個變數:`hist=[]` 和 `backtrace`,來記錄**歷史對話**以及最多**回朔到前幾次對話**
``` python=
import openai
import apikey
openai.api_key = apikey.OPENAI_API_KEY
hist = [] # 歷史對話紀錄
backtrace = 3 # 記錄幾組對話
def chat(sys_msg, user_msg):
hist.append({"role": "user", "content": user_msg})
reply = get_reply(hist + [{"role": "system", "content": sys_msg}])
while len(hist) >= 2 * backtrace:
hist.pop(0)
hist.append({"role": "assistant", "content": reply})
return reply
def get_reply(messages):
try:
response = openai.ChatCompletion.create(
model='gpt-3.5-turbo',
messages=messages,
temperature=1.5,
)
reply = response['choices'][0]['message']['content']
except openai.OpenAIError as err:
reply = f'Error Type: {err.error.type}\nError msg: {err.error.message}'
return reply
if __name__ == '__main__':
sys_msg = input("AI Role: ")
if not sys_msg.strip(): sys_msg = 'Assistant'
print()
while True:
msg = input('=> ')
if not msg.strip(): break
ai_reply = chat(sys_msg, msg)
print(f'=> {ai_reply}\n')
hist = []
```
## 串流版本的聊天程式
前一章介紹過,若使用串流方式,會以 generator 的方式傳回,因此這邊示範如何用串流方式進行對話。
``` python=
import openai
import apikey
openai.api_key = apikey.OPENAI_API_KEY
hist = [] # 歷史對話紀錄
backtrace = 5 # 記錄幾組對話
def chat_stream(sys_msg, user_msg):
hist.append({"role": "user", "content": user_msg})
reply_full = ""
for reply in get_reply_stream(
hist + [{"role": "system", "content": sys_msg}]):
reply_full += reply
yield reply
while len(hist) >= 2 * backtrace:
hist.pop(0)
hist.append({"role": "assistant", "content": reply_full})
def get_reply_stream(messages):
try:
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=messages,
stream=True
)
for chunk in response:
if 'content' in chunk['choices'][0]['delta']:
yield chunk["choices"][0]["delta"]["content"]
except openai.OpenAIError as err:
reply = f'Error Type: {err.error.type}\nError msg: {err.error.message}'
if __name__ == '__main__':
sys_msg = input("AI Role: ")
if not sys_msg.strip(): sys_msg = 'Assistant'
print()
while True:
msg = input('=> ')
if not msg.strip(): break
for reply in chat_stream(sys_msg, msg):
print(f'{reply}', end='')
print('\n')
```