# 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') ```