[8기 랭체인] Chat Model 제대로 알고 쓰기

안녕하세요. 8기 랭체인방 정정민입니다.

오늘은 chat model에 관한 공부를 진행했고

중간 과정을 공유드리겠습니다.


호출

다양한 문서나 코드를 보면 아래와 같은 방식으로 chat model을 사용합니다.

result = chat.generate(message) 
혹은 
results = chat(message) 
혹은 
results = chat.invoke([message]) 
혹은 
results = chat.batch([message]) 


뭐가 맞을까요?

  • 결론은 모두 맞습니다. 그리고 모두 작동합니다.

  • 다만 langchain이 업데이트 되면서 호출 방법이 업데이트 됩니다.

  • 그래서 공식 문서에서도 legacy 라고 표시를 해 놨네요. (__call__, generate)


어떤게 가장 최신이죠?

  • 지금은 Langchain 모든 모듈은 LCEL 표현 방식을 사용하도록 권장됩니다.

  • 따라서 invoke와 batch 방식이 가장 최신입니다.


구조는 어떻게 구성되나요?

  • 아래와 같은 구조를 갖고 있습니다.

  • 결국 근본은 generate 함수입니다.

  • 다른 method 들은 내부적으로 generate 함수를 호출하고 있죠


왜 이렇게 쓰나요?

  • 모든 Langchain 사용 과정을 본건 아니지만

  • LCEL이라는 통일된 형태로 모든 정보를 사용하기 위함으로 보입니다.

  • invoke의 결과물은 LCEL로 사용할 수 있는 모듈로 casting을 진행합니다. (코드)

  • 즉, pipeline 과정에서 수월히 쓰기 위함이죠


1차 결론

  • LCEL는 앞으로(이미??) Langchain에 근본이 되는 구조로 보입니다.

    • 빨리 공부해서 숙지해야겠네요.

  • 잘 와닿지는 않아도 invoke, batch, steam을 써보기로!


대화하기

chatGPT가 단순 LLM보다 큰 의미를 갖는 이유는 대화가 가능성이 한 몫 할겁니다.

Langchain도 이것한 가능한 모델을 제공해 대화가 가능하게 합니다.

chat = ChatOpenAI(openai_api_key=OPENAI_API_KEY)


내부에 구현된 chat model로 대화를 시도합니다.

  • while 문으로 반복적으로 입력을 제공합니다.

  • 희망하건데, 이전 질문과 답변에 결을 맞춘 대답을 해주길..


결과가..??

  • 잘 안됩니다

  • 이전에 얘기 했던 질문과 그에 맞는 적절한 답변에 추가적인 질문을 제공했을 때

  • 쌩뚱맞은 결과를 보여줍니다.

    • 마치 처음 받는 질문 같은 모습이죠??

  • 이 모습은 단순 LLM 모델을 쓰는 것과 같습니다.


내부 코드도 그렇습니다.

  • 위는 OpenAI 에게 호출을 보내기 직전의 코드

  • 제공하는 kwargs를 보면 마지막 질문에 대한 내용만 입력으로 들어갑니다.

  • 과거 정보를 알 수 없겠죠??

  • OpenAI에서 제 호출을 기억해주고 있으면 모르겠지만.. 그렇게 해주지는 않겠죠?


2차 결론

  • 단순 chat model은 (특별한 세팅을 하기 전에) 대화를 저장하는 기능이 없습니다.

  • 물론 system message, human message, AI message를 강제로 세팅은 가능

messages = [
    SystemMessage(content="너는 친절한 도우미다"),
    HumanMessage(content="머신러닝이 뭐냐?"),
]

대화같은 대화하기

생각보다 대화같은 대화를 하는건 어렵지 않았습니다.


how?

  • 대화 기록을 Message Module의 형태로 listing 해서 보관하고 모델에 넣어주면 됩니다.

conversation = []
while True:
    user_input = input("사용자 입력: ")
    if user_input.lower() == "종료":
        break
    
    user_message = HumanMessage(content=user_input)
    conversation.append(user_message)

    response = chat.invoke(conversation)
    conversation.append(response)
    print("모델 응답:", response.content)


  • 추후 사용 시 필요에 따라 사용할 이전 내용을 핸들링 해주면 될 듯

    • 전체 단어수로 조절 하던지

    • 전체 list 수로 조절 하던지

    • 등등


떠오르는 질문

  • model.batch([message1, message2]) 와의 차이를 알아봐야 함


삽질 : InMemoryCache

  • 대화 저장 과정을 모델의 새로운 입력으로 사용하기 위한 기능을 찾아보던 중 너무 매력적인 코드를 보게 됨 (링크)

  • 또한, docs에도 설명이 구체적이지 않았구요.. 링크

  • 결론적으로 이는 대화 내용을 저장하는건 맞지만, 이것을 이용해 모델의 출력에 긍정적인 영향을 주는 것은 아님


InMemoryCache

  • 코드 내부에 저장되는 dict 저장소

    • key : tuple( (str)사용자입력, (str)LLM출력 )

    • value : LLM의 AIMessage 객체

  • 이전에 있었던 사용자 입력과 똑같은 입력이 들어오면 빠른 답변을 주기 위한 기능


세팅 및 사용

  • 코드 맨 앞에 이를 적어주면 됨

cache = InMemoryCache()
set_llm_cache(cache)
  • 필요시 상기 명시한 내용대로 key, value를 넣어서 dict를 update 시키면 됨


마지막 결론

  • chat model은 이전 대화 내용을 유지한 상태로 대화가 가능함

    • List의 형태로 저장해서 넣어주면 됨

  • 이전 대화가 없다면 단순 LLM과 다름이 없음

  • LCEL는 Langchain을 관통하는 큰 개념이라 추가 공부 필요!



작성자

4
4개의 답글

👉 이 게시글도 읽어보세요