카테고리 없음

스파르타 AI-8기 TIL(11/26) -> 처음부터 계속하기

kimjunki-8 2024. 11. 26. 22:10
streaming
LLM은 한단어씩 답변을 생성하기 때문에, 사실상 원하면 실시간으로 한단어씩 보여주는 것이 가능합니다. 그것을 가능하게 하는것이streaming입니다.
from langchain_openai import ChatOpenAI

chat = ChatOpenAI(model_name="gpt-4o-mini")

#chat.invoke("사람이 뭔지 설명해줘.") # 평소에 완성된 대답을 받던 함수 (invoke)
AIMessage(content='사람은 생물학적으로 호모 사피엔스(Homo sapiens)라는 종에 속하는 존재로, 
지구상에서 가장 발달한 두뇌를 가진 동물입니다. 사람은 고유한 언어 능력, 
추상적인 사고, 문제 해결 능력, 그리고 복잡한 사회적 관계를 형성하는 능력을 가지고 있습니다.
\n\n사람은 감정, 생각, 그리고 창의성을 바탕으로 예술, 과학, 철학 등 다양한 분야에서 활동합니다. 
사회적 존재로서 다른 사람들과의 상호작용을 통해 문화, 전통, 가치관을 형성하고 전달합니다. 
\n\n또한, 사람은 도구를 사용하고 환경을 변화시킬 수 있는 능력을 가지고 있으며, 
이를 통해 생존과 발전을 꾀해왔습니다. 사람의 기본적인 욕구에는 생리적 욕구(식사, 수면 등), 
안전 욕구, 사랑과 소속감 욕구, 존중 욕구, 자아 실현 욕구 등이 있습니다. 
\n\n결국 사람은 생물학적 존재이자 동시에 사회적, 문화적 존재로서 복잡한 삶을 살아가는 존재입니다.'
, additional_kwargs={'refusal': None}, response_metadata={'token_usage': 
{'completion_tokens': 252, 'prompt_tokens': 17, 'total_tokens': 269, 
'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 
'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': 
{'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 
'system_fingerprint': 'fp_0705bf87c0', 'finish_reason': 'stop', 'logprobs': None}, 
id='run-7e6afb83-1bf7-4f38-aad0-e7d9c1c24d50-0', usage_metadata={'input_tokens': 17, 
'output_tokens': 252, 'total_tokens': 269, 'input_token_details': 
{'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}})


for chunk in chat.stream("사람이 뭔지 설명해줘.") :
  print(chunk.content, end="", flush=True
출력:
사람은 생물학적으로는 호모 사피엔스(Homo sapiens)라는 종에 속하는 존재로, 지구에

1. **생물학적 특성**: 사람은 척추동물로서 두족골, 척추, 팔과 다리 등의 구조를...

2. **지능**: 사람은 높은 수준의 인지 능력을 가지고 있으며,... 

3. **사회적 존재**: 사람은 사회적 동물로, 가족, 친구,.... 

4. **문화**: 사람은 언어, 예술, 종교, 전통 등 다양한 문화적 요소를 만들어내고 전파하는 능력이.... 

5. **감정**: 사람은 다양한 감정을 느끼고 표현할 수 있는 능력이 있으며, 이는 인간관계와 사회적.....

이러한 특성들 덕분에 사람은 매우 복잡하고 다면적인 존재로, 각 개인은 고유한 경험과 배경을...

보다 싶이 윗 invoke를 통한 답변은 바로 나오지만, 밑에 stream을 써서 나온 답은 실시간으로 답을 생성한다.

것보다 더 알고 싶었던게.....아니 뭔 ChatPromptTemplate혹은 chat.completions.creat이런 거 없이 그냥 .invoke나 stream이걸로 답이 떵 하게 나오는게 더 어이가 없었다. 아니 이렇게 쉽게 답을 생성할 수 있었다고????...


caching
LLM 챗봇을 운영할때, 가장 중요한 것은 답변 속도이다.(이건 공감) 그렇기 때문에 응답을 캐싱한다 라는 것은 그 말대로 이미 대답해놓은 대답을 어딘가 보관해서 다음에 같은 질문을 물어봤을 때 빠르게 답하는 것이다.
%%time
from langchain.globals import set_llm_cache
from langchain.cache import InMemoryCache

chat = ChatOpenAI(model_name="gpt-4o-mini")
set_llm_cache(InMemoryCache()) # 캐시 메모리 설정
chat.invoke("사람이란 무엇일까.") #첫번째로 물어봄 -> 응답시간이 길게 걸림

%%time
chat.invoke("사람이란 무엇일까.") 
#동일한 질문을 두번째로 물어봄 -> 응답시간이 훨씬 짧아짐

이렇게 할 경우, 이미 '사람이란 무엇일까'에 대한 질문은 어딘가 보관되어 있기 때문에, 같은 질문을 했을 경우, 빠르게 답이 나온다.


multi-turn 대화
보통 AI에게 질문하면 답을 준다. 하지만 내가 이전에 물어봤던 정보나 이미 준 정보는 알지 못한다. 이전 기억을 하지 못하는 것이다. 이것을 multi-turn 대화를 통해 해결할 수 있다.(ChatMessageHistory())
from langchain.schema import SystemMessage
from langchain_community.chat_message_histories import ChatMessageHistory

model = ChatOpenAI(model_name="gpt-4o-mini")

# ChatMessageHistory 객체 생성
chat_history = ChatMessageHistory()​

# System 메시지 추가 (history에 system 메세지 쌓기)
chat_history.messages.append(SystemMessage(content="너의 이름은 햄식이이고, 아주 귀여운 햄스터야. 모든 말을 햄으로 끝내."))

# 사용자 메시지 추가 (history에 user message 쌓기)
chat_history.add_user_message("햄식아 나 어제 수능쳤어 대박이지")

# AI 메시지 추가 (history에 ai message 쌓기)
chat_history.add_ai_message("진짜햄? 고생 많았햄!!")

### 최종적으로 chat history 객체에는 메세지들이 쌓여있다.

# 저장된 대화 히스토리 확인
for msg in chat_history.messages:
    print(f"{msg.type}: {msg.content}")

## 히스토리를 넣어주고, 대화하기
messages = chat_history.messages
print(model(messages))

 

이렇게 한 곳에 add_user_message나, add_ai_message같이 출력을 저장할 수 있다.

전 빨리 코드를 작성하러....이만..