본문 바로가기
AI/LLM

『Hey, 파이썬! 생성형 AI 활용 앱 만들어 줘』 Part 3. 음성 인식 AI 비서 만들기

by Night Fury 2024. 10. 8.
반응형
김한호, 최태온, 윤택한, 『Hey, 파이썬! 생성형 AI 활용 앱 만들어 줘』, 성안당(2024), p336-411.

 

STT: Speech To Text (e.g. Clova note, daglo)

Whisper: OpenAI 공개 모델

from openai import OpenAI

OPENAI_API_KEY = ""
client = OpenAI(api_key=OPENAI_API_KEY)

speech_output_path = "path" # 임의로 녹음한 음성 파일
audio_file= open(speech_output_path, "rb")
transcript = client.audio.transcriptions.create(
    model="whisper-1",
    file=audio_file
)
print(transcript.text)

 

TTS: Text To Speech (e.g. Clova voice, onair studio, typecast)

gTTS(Google Text to Speech): 텍스트로 음성 파일 저장

from gtts import gTTS
from IPython.display import Audio, display

message = "안녕하세요 NightFury 블로그에 놀러오신 것을 환영합니다."
tts = gTTS(message, lang="ko")
speech_output_path = "./test_output.mp3"
tts.save(speech_output_path)

audio_widget = Audio(speech_output_path)
display(audio_widget)

display 실행 시, 보여지는 화면

 

OpenAI TTS: 유료, 보이스 형태를 여러 가지로 지정할 수 있음

from openai import OpenAI
from IPython.display import Audio, display

OPENAI_API_KEY = ""
client = OpenAI(api_key=OPENAI_API_KEY)

message = "NightFury 블로그에 많이 놀러와주시고, 좋아요 눌러주세요."
response = client.audio.speech.create(
    model="tts-1",
    voice="alloy",
    input= message,
)
speech_output_path = "./openai_tts_output.mp3"
response.stream_to_file(speech_output_path)

audio_widget = Audio(speech_output_path)
display(audio_widget)

display 실행 후, 재생이 끝났을 때 보여지는 화면

문서 요약

pdf파일을 통한 prompt 방식

from langchain.document_loaders import PyPDFLoader

def pdf_loader(pdf_path):
    loader = PyPDFLoader(pdf_path)
    pdf_doc = loader.load()
    return pdf_doc
pdf_path = "hey_pdf_2.pdf"

pages_content = pdf_loader(pdf_path)[0].page_content # 첫 번째 페이지

# 영어로 해야 속도가 빠릅니다.
system_ai_en = """You are an artificial intelligence assistant, and you
should be able to respond to various topics such as reading PDFs,
summarizing documents, managing schedules, providing weather information,
searching for the shortest route, and conducting web searches. Please respond
briefly in Korean."""

prompt = """다음은 문서 중 일부 내용입니다.
{pages_content}
이 문서의 주요 내용을 요약해 주세요.
답변:"""

completion = client.chat.completions.create(
    model="gpt-3.5-turbo-1106",
    messages=[
        {"role": "system", "content": system_ai_en},
        {"role": "user", "content": prompt.format(pages_content=pages_content)},
    ]
)
print(completion.choices[0].message.content)

 

Langchain 방식

  • 분할된 문서 요약: map
  • 요약본 통합: reduce
### 문서 내용 로드
from langchain.document_loaders import PyPDFLoader

def pdf_loader(pdf_path):
    loader = PyPDFLoader(pdf_path)
    pdf_doc = loader.load()
    return pdf_doc

pdf_path = "hey_pdf.pdf"
pages_content = pdf_loader(pdf_path)


### 문서 내용 분할 (문서 전체 내용을 넣지 못하는 문제를 해결하기 위함)
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 스플리터 설정
text_splitter = RecursiveCharacterTextSplitter.from_tiktoken_encoder(
    chunk_size=3000, ## 분할 개수 가쥰 =
    chunk_overlap=0,
)
# pages_content 내용 분할
split_docs = text_splitter.split_documents(pages_content)
# 분할된 문서의 수 확인
print("분할된 문서의 개수는: ", len(split_docs))


### 각 문서별 요약 (Map)
from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain
from openai import OpenAI
import os
os.environ["OPENAI_API_KEY"] = ""

# map template 설정, {pages_content} 분할된 내용이 입력
map_template = """다음은 문서 중 일부 내용입니다
{pages_content}
이 문서의 주요 내용을 요약해 주세요.
"""
# map 기본 프롬프트
map_prompt = PromptTemplate.from_template(map_template)
# 문서내용이 길 수 있기 때문에 model을 gpt-3.5-turbo-16k 설정
llm = ChatOpenAI(temperature=0,
                 model_name='gpt-3.5-turbo-16k')
map_chain = LLMChain(llm=llm, prompt=map_prompt)

# reduce 단계에서 처리할 프롬프트 정의
reduce_template = """다음은 문서 요약의 집합입니다:
{summaries}
이 내용을 바탕으로 통합된 문서 요약을 작성해 주세요.
"""
# Reduce 프롬프트
reduce_prompt = PromptTemplate.from_template(reduce_template)

# Reduce에서 수행할 LLMChain 정의
reduce_chain = LLMChain(llm = llm, prompt = reduce_prompt)


### 각 문서 요약본 통합 (Reduce)
from langchain.chains.combine_documents.stuff import StuffDocumentsChain
from langchain.chains import ReduceDocumentsChain

# 문서 목록 통합 체인 설정
combine_doc_chain = StuffDocumentsChain( # 단순 요약, 보고서, 기사 작성 내용 작업에 사용
    llm_chain=reduce_chain,
    document_variable_name="summaries" # reduce 프롬프트에 대입되는 변수
)

# 분할된 문서를 순차적으로 reduce 처리
reduce_doc_chain = ReduceDocumentsChain(
    combine_documents_chain=combine_doc_chain,
    collapse_documents_chain=combine_doc_chain, # 컨텍스트를 초과할 때 문서 축소를 해야 할 경우에 실행
    token_max=4000,
)


### Langchain 생성
from langchain.chains import MapReduceDocumentsChain
# 최종 체인 연결
final_chain = MapReduceDocumentsChain(
    llm_chain=map_chain, # 각 문서 맵핑
    reduce_documents_chain=reduce_doc_chain,
    document_variable_name="pages_content",
    return_intermediate_steps=False,
)
# 최종 결과 실행
result_summary = final_chain.run(split_docs)
# 요약 결과 출력
print(result_summary)

 

 

반응형

댓글