ChatGPT와 ElevenLabs를 실습해볼 것이다. 간단한 질의응답 프로그램을 먼저 만들고, 그 후에 대화를 하는 인공지능을 만들어볼 것이고, 주어진 입력을 음성으로 바꾸는 실습도 해볼 것이다.
ChatGPT를 사용한 간단한 질의응답 프로그램
일회성. 질의응답
먼저, 간단한 환영 인사 프로그램을 만들어보자.
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "너는 변호사야 나에게 법적인 상담을 해줘"},
{"role": "user", "content": "안녕하세요 저는 ㅇㅇㅇ입니다."}
]
)
print("대답" + completion.choices[0].message.content)
터미널에 python 파일명을 적은 후, 코드를 출력해보면 "API 사용 한도를 초과했습니다. 잠시 후 다시 시도해주세요." 라고 출력된다. API를 결제해야 한다는 것이다. 그러나 코드는 정상적으로 동작하는 것이라고 한다. 결과를 제대로 출력하려면 API를 결제해야 한다는 것이다.
최근에 ChatGPT가 의료나 변호사와 관련된 전문 지식이 필요한 경우, 주의 문구를 먼저 전달해준다고 한다. 우리가 이 부분을 막는 방법이 있을까? YES! 이게 우리가 AI 서비스를 활용해서 다른 서비스를 만들어낼 때의 주의점인데, system의 content에 "단, 주의사항은 말하지마"라고 추가해주면 된다.
from openai import OpenAI
client = OpenAI()
completion = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "system", "content": "너는 변호사야 나에게 법적인 상담을 해줘, 단 주의사항은 말하지마"},
{"role": "user", "content": "안녕하세요 저는 ㅇㅇㅇ입니다."}
]
)
print("대답" + completion.choices[0].message.content)
이렇게 하면 이전과 다르게 주의사항이 나오지 않게 된다. 이를 통해 사용자가 어느 정도 개발자의 의도를 회피할 수 있다는 것을 알 수 있다. 그러나 사용 시 굉장히 주의해야 한다.
대화 형태
이번에는 대화 형태로 한번 만들어보자.
from openai import OpenAI
client = OpenAI()
system_message = {
"role": "system", "content": "너는 변호사야 나에게 법률적인 상담을 해줘. 그리고 주의사항은 말하지마. 한국법을 기준으로 해"
}
messages = [system_message]
while True :
user_input = input("사용자 전달:")
if user_input == "exit":
print("대답: 즐거운 대화였습니다! 감사합니다!")
break
messages.append({"role" : "user" , "content" : user_input })
completion = client.chat.completions.create(
model = "gpt-4o",
messages = messages
)
reply = completion.choices[0].message.content
print("대답: " + reply)
messages.append({"role" : "assistant" , "content" : reply })
기본 단계는 일회성의 질의응답으로 만들 때와 유사하다.
content에 "너는 변호사야. ~ 한국법을 기준으로 해" 라고 넣어준다. 그리고 대화 내역을 저장할 공간을 하나 만들어준다.
그 후에는 반복문을 짠다. 대화를 할거기 때문에, 계속해서 동작하게 하는 것이다. 이제 종료 지점을 설정해줘야 한다. 우리는 "exit"라고 들어오면 해당 코드를 중단하도록 코드를 작성하겠다. 대화가 중단되면 "즐거운 대화였습니다! 감사합니다!" 가 출력되도록 마지막 문구를 쳐주고 break 해준다.
사용자가 입력을 전달했기 때문에, 우리는 이 전달 내용을 대화 형태로 ChatGPT에게 제공해줘야 한다. reply는 간단하게 가져올 수 있었다. 그 다음, 한 가지 작업이 기존에서 추가된다. 바로 messages에다가 대답을 넣어주는 것이다. assistant에 reply(대답)을 넣어주면, ChatGPT는 대화내역을 인지할 수 있게 된다.
아래의 코드와 같이, messages = [system_message]에다가 나에 대한 정보를 저장해놓으면, 대화 전체적으로 나에 대한 정보가 반영된다.
messages = [system_message,
{"role":"user","content":"내 이름은 ㅇㅇㅇ"},
{"role":"user","content":"직업은 ㅁㅁ"},
{"role":"user","content":"달을 좋아함"}]
이렇게, 정보를 전달하는 방법은 굉장히 다양한데, 학습되지 않은 정보도, ChatGPT가 적당히 답변할 수 있도록 바꿔줄 수 있다. 단순히 이렇게 문장을 전달하는 게 아니라, 문서나 책을 전달할 수도 있다. 해당 기법이 ChatGPT에서나 언어형 모델에서 굉장히 많이 사용되는 기법이기 때문에, 우리가 인지해두면 좋다.
system에다가 명령어를 지정하는 것을 프롬프트 엔지니어링이라고 많이 통칭하는데, 우리가 언어형 모델을 사용할 때는, 조건을 줘서 대답을 원하는 대로 유도하기 위해 필수적으로 수행돼야 한다.
이렇게 정보를 전달하는 기법 중에 대표적인 기법으로는 RAG라는 기법이 있다. LLM의 성능을 향상시키는 데 굉장히 유용하다. 이는 언어 생성 모델과 정보 검색 기능을 결합한 것이다.
주의점이 하나 있다. 챗봇이 주는 정보가 정확하지 않으면, 챗봇에서는 큰 문제가 될 수 있다. 그러니, 적절한 주의 문구를 항상 넣어주어야 한다는 점도 기억해주자.
ElevenLabs를 사용한 음성 합성 프로그램
우리는 음성 생성을 하기 위해 ElevenLabs라는 서비스를 활용해볼 것이다. ElevenLabs에는 이미 학습된 많은 모델들도 있고, 파인튜닝을 통해서 내 목소리를 녹음할 수도 있다. 내 목소리를 녹음할 때 주의를 기울여야 한다.
첫 번째로는, 당연히 패키지를 설치해야 한다. 그런데 ElevenLabs는 직접적으로 API를 추상화해주지는 않고, 우리가 직접 requests라는 라이브러리를 통해 HTTP 메서드를 호출해야 한다. requests를 설치해주자.
pip install requests
실습에서 사용한 코드는 아래와 같다.
import os
import requests
from pydub import AudioSegment
from pydub.playback import play
import io
# 설정 가능한 변수
output_filename = "output_audio.mp3"
url = "모델 URL"
headers = {
"xi-api-key": "API - KEY",
"Content-Type": "application/json"
}
# 문장을 입력받습니다.
text = input("텍스트를 입력하세요: ")
# 음성 생성 요청을 보냅니다.
data = {
"text": text,
"model_id": "eleven_multilingual_v2",
"voice_settings": {
"stability": 0.3,
"similarity_boost": 1,
"style": 1,
"use_speaker_boost": True
}
}
response = requests.post(url, json=data, headers=headers, stream=True)
if response.status_code == 200:
audio_content = b""
for chunk in response.iter_content(chunk_size=1024):
if chunk:
audio_content += chunk
segment = AudioSegment.from_mp3(io.BytesIO(audio_content))
segment.export(output_filename, format="mp3")
print(f"Success! Wrote audio to {output_filename}")
# 오디오를 재생합니다.
play(segment)
else:
print(f"Failed to save file: {response.status_code}")
이제 실제로 동작을 시켜볼건데, 주의점이 하나 있다. 해당 코드가 실행될 때, 여러 가지 인포메이션이 나온다. 그런데, 그 속에 모델 정보나 보이스 아이디 같은 것이 포함돼있는 경우도 있기 때문에, 실행 화면을 최대한 조심해서 전달해야 한다. 입력 데이터로 여러 가지를 전달해보면서 실습해보았다. stability 값을 0.6, style을 0.8로 바꾸는 등, 값을 적절히 바꾸면, 본인 목소리를 넣은 경우, 점점 더 자신의 목소리와 비슷해질 것이다.
실습에서 항상 명심할 점은, 해당 모델은 API 키도 그렇지만, 모델 자체도 굉장히 철저하게 관리돼야 한다는 것이다.