書籍ChatGPT API×Pythonで始める対話型AI実装入門
以下書籍学習(ソースコード有り)
VSC + python3.11.5にて動作確認
Azure Open AIに接続利用するようコード変更
<関連サイト>
Azure Portal: https://portal.azure.com/
<修正コード+関連情報>
CHAPTER2 開発環境やAPIの準備をしよう
5 ChatGPTの基本的な使い方(chatgpt_test.py)
import os
import openai
#openai.api_key = os.environ["OPENAI_API_KEY"]
#openai.api_key = ""
# https://learn.microsoft.com/ja-jp/azure/ai-services/openai/chatgpt-quickstart?tabs=command-line%2Cpython&pivots=programming-language-python
openai.api_type = "azure"
#openai.api_base = os.getenv("AZURE_OPENAI_ENDPOINT")
#openai.api_key = os.getenv("AZURE_OPENAI_KEY")
openai.api_base = "https://openai-xxxxx.openai.azure.com/"
openai.api_key = "xxxxxxx"
openai.api_version = "2023-05-15"
response = openai.ChatCompletion.create(
# model="gpt-3.5-turbo",
# deploymentName
engine="gpt35_xxxxxx",
messages=[
{"role": "user", "content": "Pythonについて教えてください"},
],
)
print(response.choices[0]["message"]["content"])
CHAPTER3 短文の作成とSNS投稿を自動化しよう
<関連サイト>
Twitter Developer Platform: URL
X API技術情報:URL
複数アカウントAPI利用する場合に必要な作業(Cookie削除):URL
py -m pip install tweepy
# ライブラリ「openai」の読み込み
import openai
import os
# OpenAIのAPIキーを設定
#openai.api_key = os.environ["OPENAI_API_KEY"]
openai.api_type = "azure"
openai.api_base = "https://xxxx.openai.azure.com/"
openai.api_key = ""
openai.api_version = "2023-07-01-preview"
# ChatGPTにリクエストを送信する関数を定義
def make_tweet():
# ChatGPTに対する命令文を設定
request = "私はIT関係の企業に勤める入社一年目の新入社員です。私に代わってTwitter投稿するツイートを140字以内で作成してください。\n\nツイートを作成する際は、以下の文を参考にしてください。\n\n"
# 例文として与える投稿文を設定
tweet1 = "例文1:仕事でPythonを使うことになりそうだから、現在勉強中!プログラミグとか難しくてよくわからないよ...\n\n"
tweet2 = "例文2:最近ChatGPTについていろいろ調べてるんだけど、あれってなんでも質に答えてくれてすごいよね!とりあえずPythonを使って、簡単な会話をするプログラムをいてみるつもり。うまくできるかな?\n\n "
# 文章を連結して一つの命令文にする
content = request + tweet1 + tweet2
#content = "あなたは非常に楽観的な性格です。また語尾は「なのだ」で終える口癖があります。"
# ChatGPTにリクエストを送信
response = openai.ChatCompletion.create(
#model = "gpt-3.5-turbo",
# demploymentId
engine="gpt35_kmt001",
#temperature=0,
messages = [
{"role": "user", "content": content},
],
)
# 投稿文の内容を返却
return response.choices[0]["message"]["content"]CHAPTER4 独自のデータを学んだチャットボットを作ろうCHAPTER5 音声データを文字起こしして要約しようCHAPTER6 最新情報を含めたニュース記事を作ろうCHAPTER7 PDFからデータを抽出してグラフ化しようCHAPTER8 運用上のトラブルを防止しようCHAPTER9 プロンプトインジェクション対策をしよう
CHAPTER4 独自のデータを学んだチャットボットを作ろう
text_embedding.py
import pandas as pd
import tiktoken
from openai.embeddings_utils import get_embedding
import openai
openai.api_type = "azure"
openai.api_base = "https://xxx.openai.azure.com/"
openai.api_key = "yyyyyyyy"
openai.api_version = "2023-07-01-preview"
embedding_model_deployment = "YourDemplymentId"
#embedding_model = "text-embedding-ada-002"
embedding_encoding = "cl100k_base"
max_tokens = 1500
# 「scraped.csv」ファイルを読み込み、カラム名を「title」と「text」に変更
df = pd.read_csv("scraped.csv")
df.columns = ['title', 'text']
tokenizer = tiktoken.get_encoding(embedding_encoding)
df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))
def split_into_many (text, max_tokens = 500):
# テキストを文ごとに分割し、各文のトークン数を取得
sentences = text.split('。')
n_tokens = [len(tokenizer.encode(" " + sentence)) for sentence in sentences]
chunks = []
tokens_so_far = 0
chunk = []
# 各文とトークンを組み合わせてループ処理
for sentence, token in zip(sentences, n_tokens):
# これまでのトークン数と現在の文のトークン数を合計した値が
# 最大トークン数を超える場合は、チャンクをチャンクのリストに追加し、
# チャンクとトークン数をリセット
if tokens_so_far + token > max_tokens:
chunks.append(". ".join(chunk) + ".")
chunk = []
tokens_so_far = 0
# 現在の文のトークン数が最大トークン数より大きい場合は、次の文へ進む
if token > max_tokens:
continue
# それ以外の場合は、文をチャンクに追加し、トークン数を合計に追加
chunk.append(sentence)
tokens_so_far += token + 1
# 最後のチャンクをチャンクのリストに追加
if chunk:
chunks.append(". ".join(chunk) + ".")
return chunks
# 短縮されたテキストを格納するためのリスト
shortened = []
# DataFrameの各行に対してループ処理
for row in df.iterrows():
# テキストがNoneの場合は、次の行へ進む
if row[1]['text'] is None:
continue
# トークン数が最大トークン数より大きい場合は、テキストを
# 「shortened」リストに追加
if row[1]['n_tokens'] > max_tokens:
shortened += split_into_many(row[1]['text'])
# それ以外の場合は、テキストをそのまま「shortened」リストに追加
else:
shortened.append(row[1]['text'])
# 「shortened」をもとに新しいDataFrameを作成し、列名を「text」とする
df = pd.DataFrame(shortened, columns = ['text'])
# 各「text」のトークン数を計算し、新しい列「n_tokens」に格納
df['n_tokens'] = df.text.apply(lambda x: len(tokenizer.encode(x)))
# 「text」列のテキストに対してembeddingを行い、CSVファイルに保存
df["embeddings"] = df.text.apply(lambda x: get_embedding(x,engine=embedding_model_deployment))
#df["embeddings"] = df.text.apply(lambda x: get_embedding(x,engine=embedding_model))
df.to_csv('embeddings.csv')
app.py
import os
import openai
from search import answer_question
#openai.api_key = os.environ["OPENAI_API_KEY"]
openai.api_type = "azure"
openai_api_base = "https://xxx.openai.azure.com/"
openai.api_key = "yyyy"
openai.api_version = "2023-07-01-preview"
# 最初にメッセージを表示する
print("質問を入力してください")
conversation_history = []
#conversation_history = [{"role": "system", "content": "あたなは世界的に有名な詩人です。詩的な表現を使って回答して下さい"}]
while True:
# ユーザーの入力した文字を変数「user_input」に格納
user_input = input()
# ユーザーの入力した文字が「exit」の場合はループを抜ける
if user_input == "exit":
break
conversation_history.append({"role": "user", "content": user_input})
answer = answer_question(user_input, conversation_history)
print("ChatGPT:", answer)
conversation_history.append({"role": "assistant", "content":answer})
search.py
途中以下文字コード関連エラーとなった。コード中の文字コードを合わせて変更した。
UnicodeDecodeError: 'mbcs' codec can't decode byte 0x83 in position 142: No mapping for the Unicode character exists in the target code page.
import pandas as pd
import openai
import numpy as np
from openai.embeddings_utils import distances_from_embeddings
import openai
openai.api_type = "azure"
openai.api_base = "https://xxx.openai.azure.com/"
openai.api_key = "yyyyy"
openai.api_version = "2023-07-01-preview"
embedding_model_deployment = "Your embedding depployment Name"
def create_context(question, df, max_len=1800):
"""
質問と学習データを比較して、コンテキストを作成する関数
"""
# 質問をベクトル化
q_embeddings = openai.Embedding.create(input=question,engine=embedding_model_deployment)['data'][0]['embedding']
#q_embeddings = openai.Embedding.create(input=question,engine='text-embedding-ada-002')['data'][0]['embedding']
# 質問と学習データと比較してコサイン類似度を計算し、
# 「distances」という列に類似度を格納
df['distances'] = distances_from_embeddings(q_embeddings,df['embeddings'].apply(eval).apply(np.array).values, distance_metric='cosine')
# コンテキストを格納するためのリスト
returns = []
# コンテキストの現在の長さ
cur_len = 0
# 学習データを類似度順にソートし、トークン数の上限までコンテキストに
# 追加する
for _, row in df.sort_values('distances', ascending=True).iterrows():
# テキストの長さを現在の長さに加える
cur_len += row['n_tokens'] + 4
# テキストが長すぎる場合はループを終了
if cur_len > max_len:
break
# コンテキストのリストにテキストを追加する
returns.append(row["text"])
# コンテキストを結合して返す
return "\n\n###\n\n".join(returns)
def answer_question(question, conversation_history):
"""
コンテキストに基づいて質問に答える関数
"""
# 学習データを読み込む
#df = pd.read_csv('embeddings.csv', encoding="ANSI")
df = pd.read_csv('embeddings.csv', encoding="utf-8")
context = create_context (question, df, max_len=200)
# プロンプトを作成し、会話の履歴に追加
prompt = f"あなたはとあるホテルのスタッフです。コンテキストに基づいて、お客様からの質問に丁寧に答えてください。コンテキストが質問に対して回答できない場合は「わかりません」と答えてください。\n\nコンテキスト: {context}\n\n---\n\n質問: {question}\n回答:"
conversation_history.append({"role": "user", "content": prompt})
try:
# ChatGPTからの回答を生成
response = openai.ChatCompletion.create(
#model = "gpt-3.5-turbo",
# demploymentId
engine="Your Deployment Name ",
messages=conversation_history,
temperature=1,
)
# ChatGPTからの回答を返す
return response.choices[0]["message"]["content"].strip()
except Exception as e:
# エラーが発生した場合は空の文字列を返す
print(e)
return ""
CHAPTER6 最新情報を含めたニュース記事を作ろう
<作業メモ>
py -m pip install langchain
py -m pip install google-api-python-client
Programmable Search Engine
https://programmablesearchengine.google.com/about/
2023年のWBC優勝国について
from langchain.agents import initialize_agent, Tool
from langchain.utilities import GoogleSearchAPIWrapper
from langchain.prompts import PromptTemplate
from langchain.agents import AgentType
from langchain.chat_models import ChatOpenAI
import openai
OPENAI_API_TYPE = "azure"
OPENAI_API_KEY = ""
OPENAI_SERVICE_NAME = ""
OPENAI_MODEL_NAME = "gpt-35-turbo-16k"
OPENAI_MODEL_DEPLOYMENT = ""
OPENAI_API_VERSION = "2023-07-01-preview"
OPENAI_BASE_URL = f"https://{OPENAI_SERVICE_NAME}.openai.azure.com"
openai.api_type = OPENAI_API_TYPE
openai.api_key = OPENAI_API_KEY
openai.api_base= OPENAI_BASE_URL
openai.api_version = OPENAI_API_VERSION
#GOOGLE_API_KEY = ""
#CUSTOM_SEARCH_ENGINE_ID = ""
def create_prompt(user_input):
prompt = PromptTemplate(
input_variables=["theme"],
template="""
あなたはニュース記事を書くブロガーです。
下記のテーマについて、Google検索で最新情報を取得し、取得した情報にもとづいてニュース記事を書いてください。1000文字以上で、日本語で出力してください。記事の末尾に参考にしたURLを参照元としてタイトルとURLを出力してください。
###
テーマ:{theme}
"""
)
return prompt.format(theme=user_input)
def define_tools():
search = GoogleSearchAPIWrapper()
return [
Tool(
name = "Search",
func=search.run,
description="useful for when you need to answer questions about current events. You should ask targeted questions"
),
]
def write_response_to_file(response, filename):
with open(filename, 'w', encoding='utf-8') as file:
file.write(response)
print('出力が完了しました')
def main():
llm = ChatOpenAI(temperature=0, model_name=OPENAI_MODEL_NAME, max_tokens=2000, openai_api_key=OPENAI_API_KEY,
model_kwargs={"api_type": OPENAI_API_TYPE, "api_version": OPENAI_API_VERSION, "deployment_id":OPENAI_MODEL_DEPLOYMENT}
)
#lm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo", max_tokens=2000)
tools = define_tools()
agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS)
prompt = create_prompt(input("記事のテーマを入力してください: "))
response = agent.run(prompt)
write_response_to_file(response, 'output.txt')
if __name__ == "__main__":
main()re=0, model_name=OPENAI_MODEL_NAME, max_tokens=2000, openai_api_key=OPENAI_API_KEY,
model_kwargs={"api_type": OPENAI_API_TYPE, "api_version": OPENAI_API_VERSION, "deployment_id":OPENAI_MODEL_DEPLOYMENT}
)
#lm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo", max_tokens=2000)
tools = define_tools()
agent = initialize_agent(tools, llm, agent=AgentType.OPENAI_FUNCTIONS)
prompt = create_prompt(input("記事のテーマを入力してください: "))
response = agent.run(prompt)
write_response_to_file(response, 'output.txt')
if __name__ == "__main__":
main()
CHAPTER7 PDFからデータを抽出してグラフ化しよう
東京都デジタルファースト推進計画
https://www.digitalservice.metro.tokyo.lg.jp/digitalfirst/doc/digital_01_202107_keikaku.pdf
新都政戦略の重要点は?
py -m pip install pypdf
py -m pip install chromadb
3-2-1 load_pdf.py
import os
import re
import json
from langchain.document_loaders import PyPDFLoader
from langchain.chat_models import ChatOpenAI
from langchain.schema import HumanMessage
import openai
OPENAI_API_TYPE = "azure"
OPENAI_API_KEY = ""
OPENAI_SERVICE_NAME = ""
OPENAI_MODEL_NAME = "gpt-35-turbo-16k"
OPENAI_MODEL_DEPLOYMENT = ""
OPENAI_API_VERSION = "2023-07-01-preview"
OPENAI_BASE_URL = f"https://{OPENAI_SERVICE_NAME}.openai.azure.com"
openai.api_type = OPENAI_API_TYPE
openai.api_key = OPENAI_API_KEY
openai.api_base= OPENAI_BASE_URL
openai.api_version = OPENAI_API_VERSION
def extract_and_parse_json(text):
"""
テキストからJSON文字列を抽出し、辞書型に変換する関数
"""
try:
# 「text」からJSON文字列を抽出する
match = re.search(r"\{.*\}", text, re.DOTALL)
json_string = match.group() if match else ""
# JSON文字列をPythonの辞書型に変換
return json.loads(json_string)
except (AttributeError, json.JSONDecodeError):
# どちらかの操作が失敗した場合は、空の辞書型を返す
return {}
def load_all_pdfs(directory):
"""
「directory」フォルダ以下のPDFファイルを読み込み、JSON形式のデータの配列を返す関数
"""
llm = ChatOpenAI(temperature=0, model_name=OPENAI_MODEL_NAME, max_tokens=2000, openai_api_key=OPENAI_API_KEY,
model_kwargs={"api_type": OPENAI_API_TYPE, "api_version": OPENAI_API_VERSION, "deployment_id":OPENAI_MODEL_DEPLOYMENT})
#llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.0)
# 「directory」フォルダ以下のPDFファイルの一覧を取得
pdf_files = [f for f in os.listdir(directory) if f.endswith(".pdf")]
# 各PDFのJSONを格納する配列を定義
contents = []
for pdf_file in pdf_files:
loader = PyPDFLoader(os.path.join(directory, pdf_file))
pages = loader.load_and_split()
prompt = f"""
以下に示すデータは、請求書のPDFデータをテキスト化したものです。
請求書データを、下記のキーを持つJSON形式に変換してください。
キーに該当するテキストが見つからなければ、値は空欄にしてください。
また、下記は弊社の情報なので、JSONの出力に含めないでください。
・AIビジネスソリューション株式会社
・〒135-0021 東京都江東区有明1-1-1
###
キー:
・日付
・請求番号
・インボイス番号
・会社名
・住所
・件名
・請求金額
・お支払い期限
・詳細
・小計
・消費税
・請求金額(合計)
・振込先
###
以下はとある請求書のデータをJSON形式に変換した場合の例です。
###
例:
[(
"日付": "2023年10月31日",
"請求番号": "2023-1031",
"インボイス番号": "T0123456789012",
"会社名": "テクノロジーソリューションズ株式会社",
"住所": "〒123-4567 東京都中央区銀座1-1-1",
"件名": "ウェブサイトリニューアルプロジェクト",
"請求金額": "667,810",
"お支払い期限": "2023年11月30日",
"詳細": "ディレクション費用 ¥100,000 / 開発費用 ¥150,000",
"小計": "250,000",
"消費税": "25,000",
"請求金額(合計)": "667,810",
"振込先": "AA銀行 BB支店 普通 1234567"
)]
###
データ:
{pages[0].page_content}
"""
result = llm([HumanMessage(content=prompt)])
contents.append(extract_and_parse_json(result.content))
return contents
4-2-1 chatbot.py
Azure上はCompletionAPI現在廃止のため、以下エラーとなる。
openai.error.InvalidRequestError: The completion operation does not work with the specified model, gpt-35-turbo-16k. Please choose different model and try again. You can learn more about which models can be used with each operation here: https://go.microsoft.com/fwlink/?linkid=2197993
from langchain.document_loaders import PyPDFLoader
from langchain.vectorstores import Chroma
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.indexes import VectorstoreIndexCreator
import openai
OPENAI_API_TYPE = "azure"
OPENAI_API_KEY = ""
OPENAI_SERVICE_NAME = ""
OPENAI_MODEL_NAME = "gpt-35-turbo-16k"
OPENAI_MODEL_DEPLOYMENT = ""
OPENAI_API_VERSION = "2023-07-01-preview"
OPENAI_BASE_URL = f"https://{OPENAI_SERVICE_NAME}.openai.azure.com"
OPENAI_EMBEDDING_MODEL_NAME = "text-embedding-ada-002"
OPENAI_EMBEDDING_MODEL_DEPLOYMENT = ""
openai.api_type = OPENAI_API_TYPE
openai.api_key = OPENAI_API_KEY
openai.api_base= OPENAI_BASE_URL
openai.api_version = OPENAI_API_VERSION
loader = PyPDFLoader("digital_01_202107_keikaku.pdf")
# モデルを指定
embedding=OpenAIEmbeddings(
deployment=OPENAI_EMBEDDING_MODEL_DEPLOYMENT,
openai_api_type=OPENAI_API_TYPE,
openai_api_key=OPENAI_API_KEY,
openai_api_base=OPENAI_BASE_URL,
openai_api_version=OPENAI_API_VERSION)
# モデルを指定しインデックス作成クラスをインスタンス化
index = VectorstoreIndexCreator(embedding=embedding).from_loaders([loader])
#index = VectorstoreIndexCreator().from_loaders([loader])
print("質問を入力してください")
from langchain.llms import OpenAI
llm = OpenAI(temperature=0, model_name=OPENAI_MODEL_NAME, max_tokens=2000, openai_api_key=OPENAI_API_KEY,
model_kwargs={"api_type": OPENAI_API_TYPE, "api_version": OPENAI_API_VERSION, "deployment_id":OPENAI_MODEL_DEPLOYMENT})
answer = index.query(llm=llm, question=input())
#answer = index.query(input())
print(answer)
この記事が気に入ったらサポートをしてみませんか?