![見出し画像](https://assets.st-note.com/production/uploads/images/108449702/rectangle_large_type_2_799a81e7f79e0e4f6a1f2aed2ec3e11a.png?width=1200)
OpenAIのFunction calling機能を活かした、LangChainの新機能Taggingを試す
⚡️Tagging
— Harrison Chase (@hwchase17) June 16, 2023
Specify a schema and tag a document with those attributes
As opposed to Extraction, this extracts only one instance of that schema so its more useful for classification of attributes pertaining to the text as a whole
Docs: https://t.co/HUMn92Z2V8 pic.twitter.com/mv3wXqcSIG
Tagging機能
OpenAIのFunction calling機能を活かした、LangChainのTagging(tags)機能を試してみます。
pydanticの機能を使ってスキーマを設定して、テキストにタグ付けできる機能のようです。
さっそく試してみます
ネタは青空文庫の「走れメロス」の読み上げをシュッと試してみようと思います。読み上げの実装はbbzさんの記事を参考にさせてもらいました。
ファイル読み込み
# ファイルを読み込み、テキストを取得します。
with open("hashire_merosu.txt", mode="r", encoding="utf-8") as f:
text_original = f.read()
print(text_original)
整形
import re
# ルビなどを削除
text = re.sub("《[^》]+》", "", text_original)
text = re.sub("[[^]]+]", "", text)
text = re.sub("[| ]", "", text)
seperator = "\n"
text_list = text.split(seperator)
text_list.pop()
スキーマ定義
from typing import Optional, List
from pydantic import BaseModel, Field
# PydanticのBaseModelを継承して、新しいデータモデルを定義します。
class Tags(BaseModel):
sentiment: str =Field(...,description="Speaker's emotion" , enum=['talk','happy','sad','angry','fear','surprised'])
speed: float = Field(..., description="Speaking speed in line with emotional intensity, default:1.0", ge=0.5, le=5.0)
volume: float = Field(..., description="Loudness of voice in line with emotional intensity, default:1.0", ge=0.5, le=5.0)
sentiment = {'talk':1, 'happy':2, 'sad':3, 'angry':5, 'fear':6, 'surprised':7}
音声生成用の関数
import requests
import json
from langchain.chat_models import ChatOpenAI
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain.chains import create_tagging_chain, create_tagging_chain_pydantic
def txt_to_speach(text, filename):
# APIのエンドポイントURL
url = "https://api.rinna.co.jp/models/cttse/v2"
# Tags生成用 chain
llm = ChatOpenAI(model_name="gpt-3.5-turbo-0613", streaming=True, callbacks=[StreamingStdOutCallbackHandler()], temperature=0.7)
chain = create_tagging_chain_pydantic(Tags, llm)
tags = chain.run(text)
tid = sentiment[tags.sentiment]
# tid = 7
# リクエストボディの作成
data = {
"sid": 28, # ボイスID
"tid": tid, # スタイルID
"speed": tags.speed, # 話速
"text": text, # 合成するテキスト
"volume": tags.volume, # 音量
"format": "wav" # 出力ファイル形式
}
# リクエストヘッダーの作成
headers = {
"Content-Type": "application/json",
"Cache-Control": "no-cache",
"Ocp-Apim-Subscription-Key": RINNA_API_KEY
}
# POSTリクエストの送信
response = requests.post(url, data=json.dumps(data), headers=headers)
# レスポンスの確認
if response.status_code == 200:
print("Request was successful.")
response_data = response.json()
print("Media Content URL: ", response_data['mediaContentUrl'])
print("Type: ", response_data['type'])
# 音声ファイルのダウンロードと保存
audio_response = requests.get(response_data['mediaContentUrl'])
with open(f"./outputs/{filename}.wav", 'wb') as f:
f.write(audio_response.content)
print(f"Audio file has been saved as {filename}.wav.")
else:
print("Request failed. Status code: ", response.status_code)
実行!
import time
for index, value in enumerate(text_list):
txt_to_speach(value, index)
time.sleep(1)
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) /tmp/ipykernel_1458/2411938320.py in 23 for index, value in enumerate(text_list): ----> 4 txt_to_speach(value, index) 5 time.sleep(1) /tmp/ipykernel_1458/608713805.py in txt_to_speach(text, filename) 1516 tags = chain.run(text) ---> 17 tid = sentiment[tags.sentiment] 1819 # リクエストボディの作成 KeyError: 'embarrassed'
ありゃりゃ、一番最後で止まってしまいました。
「勇者は、ひどく赤面した。」の部分を感情推定しようとすると、確かに 'embarrassed'が適当だと思いますよ、gpt -3.5-turboさん😓。でも、残念ながら選択肢にないんですよ…ごめんね。
というわけで、たまにエラーが発生してしまうようなので、実際に使うときは例外処理も書かないといけませんね。今回は、お試しですし、一番最後の部分だったので、ひとまず手動で生成しました。😋
いちおう結果はこちら
最終的に生成された音声ファイルは、期待通りの結果を得ることができました。感情推定がなんとも微妙な感じの部分はありますが、Tagging機能を使い方が分かったので、今回はここまで。
参考情報
おしまい