인공지능

LCEL로 간단한 LLM Application 구축하기

kchabin 2024. 11. 12. 13:22

https://python.langchain.com/docs/tutorials/llm_chain/

 

 


RAG로 졸업프로젝트를 진행했었는데, 깊이 없이 부랴부랴 개발했던 것 같아서 제대로 다시 공식문서부터 읽어보면서 공부하려고 한다.
LangChain외에도 LlamaIndex, Spring AI가 있는데 일단 대중적이고 한번 써본 LangChain부터 실습했다.
모든 실습은 VSCode, Jupyter Notebook을 통해 이뤄진다.


만들 app : 영어에서 다른 언어로 텍스트를 번역하는 애플리케이션

  • 언어 모델 사용
  • PromptTemplates 및 OutputParsers 사용
  • LangChain Expression Language(LCEL)를 사용하여 컴포넌트 연결하기
  • LangSmith를 사용한 애플리케이션 디버깅 및 추적
  • LangServe로 배포하기

LangChain 설치하기

주피터 노트북 기반

%pip install langchain

LangSmith

LLM 애플리케이션 개발, 모니터링 및 테스트를 위한 플랫폼

 

LangChain으로 빌드하는 애플리케이션에서는 LLM을 여러번 호출한다. 애플리케이션이 점점 더 복잡해짐에 따라 chain이나 agent 내부에서 정확히 무슨 일이 일어나고 있는지 검사하기 위해 LangSmith를 활용할 수 있다.
LangSmith 사이트로 접속해서 회원가입

  1. Setting
  2. Personal
  3. Create API Key
  4. Personal Access Token
    키 description은 임의로 설정한다.
    생성된 키는 유출하지 않도록 안전한 곳에 복사한다.
#주피터 노트북에서 LangSmith 키 설정 방법
import getpass
import os

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()

키 설정은 vscode에서 할 경우 .env 파일을 사용하고 주피터노트북에선 getpass를 활용한다. 런타임이 종료되면 매번 다시 api 키를 입력해줘야 한다는 번거로움이 있다.

언어 모델

LangChain에서 사용가능한 LLM은 다음과 같다.

  • OpenAI
  • Anthropic -> Claude
  • Azure -> Azure OpenAI
  • Google
  • Cohere
  • NVIDIA
  • FireworksAI
  • AWS
  • Groq
  • MistralAI
  • TogetherAI

난 개인적으로 API 키가 있는 openai 모델을 사용했다.
openai api를 처음 사용하는 계정은 무료 토큰이 일정량, 일정 기간동안 제공되는 것으로 안다. 난 작년에 만들어두고 잊고 있다가 올해 보니까 무료 기간이 지나버려서 최소 금액 $5를 결제해서 사용 중인데 이정도만 돼도 해보고 싶은 실습은 웬만큼 다 해볼 수 있는 것 같다.

%pip install -qU langchain-openai

LangSmith 키와 마찬가지로 getpass를 사용한다.

import getpass
import os

os.environ["OPENAI_API_KEY"] = getpass.getpass()

from langchain_openai import ChatOpenAI

model = ChatOpenAI(model="gpt-4")

LLM 객체를 생성할 때, temperature, model 값을 지정할 수 있다. temperature는 0~1 값을 갖는데, 1에 가까울 수록 창의적인 답변이 만들어진다.

ChatModel 은 LangChain "Runnables"의 객체이다.

Runnable : Runnable 구성 요소가 다음과 같이 동작할 수 있도록 하는 표준 인터페이스를 정의한다.

  • stream : 응답의 청크를 스트리밍 -> 실시간 출력.
  • invoke : 입력에 대해 체인 호출
  • batch : 입력 목록에 대해 체인 호출 -> 일괄 처리

단순히 모델을 호출하기 위해선 invoke 메서드에 메시지의 리스트를 전달하면 된다.

from langchain_core.messages import HumanMessage, SystemMessage

msgs = [
    SystemMessage(content="You are a helpful assistant that translates English to Korean."),
    HumanMessage(content="I love programming.")
]

model.invoke(msgs)

LangSmith로 토큰 사용량 등을 추적할 수 있다.

OutputParsers

AIMessage는 모델의 응답으로, 방금 전 보았던 출력처럼 string과 응답에 대한 메타데이터를 포함한다. 우리가 문자열 형태로만 응답을 얻고 싶다면 출력 파서를 사용해야 한다.

  • LLM의 출력을 받아 더 적합한 형식으로 변환
  • 구조화된 데이터 생성에 매우 유용함
  • LangChain 프레임워크에서 다양한 종류의 출력 데이터를 파싱하고 처리

주요 특징

다양성, 스트리밍 지원, 확장성

from langchain_core.output_parsers import StrOutputParser

parser = StrOutputParser()

result = model.invoke(msgs)

parser.invoke(result) # 출력 : 나는 프로그래밍을 사랑한다

Chain 생성

invoke할 때마다 parser를 사용하는 대신 | 을 사용해서 모델의 응답과 parser를 연결할 수 있다.
이 연결을 통해 chain을 호출할 때마다 우리가 선언한 출력 parser를 사용할 수 있게 된다.

chain = model | parser
chain.invoke(msgs)

Prompt Templates

프롬프트 템플릿은 사용자의 입력값을 언어 모델에 전달될 수 있는 형태로 포맷팅한다. 여기선 기본적인 chat 관련 템플릿인 ChatPromptTemplate을 사용했다. 커스터마이징할 수도있는데, 이런 템플릿들은 LangChain Hub에 업로드돼있다. 도커 이미지 허브와 비슷하다.

langchain_core.prompts

from langchain_core.prompts import ChatPromptTemplate

system_template = "Translate the following into {language}:"
prompt_template = ChatPromptTemplate.from_messages(
    [("system", system_template), ("user", "{text}")]
)

 

prompt_template의 입력은 dictionary 형태이다. invoke하면 ChatPromptValue를 반환하는데, 이때 SystemMessage content의 {language}가 korean이 된 걸 확인할 수 있다.

result = prompt_template.invoke({"language": "korean", "text": "hi"})
#ChatPromptValue 객체 반환
result

result.to_messages() #메시지에 직접 액세스

[SystemMessage(content='Translate the following into korean:', additional_kwargs={}, response_metadata={}),
HumanMessage(content='hi', additional_kwargs={}, response_metadata={})]

 

| 연산자를 사용해서 모델과 출력파서를 결합할 수 있다.

 chain = prompt_template | model | parser
 chain.invoke({"language": "korean", "text": "hi"})

LangServe로 모델 서빙하기

  1. 체인 정의
  2. FastAPI 앱
  3. langserve.add_routes에 chain을 서비스할 경로가 정의된다.
#!/usr/bin/env python
from dotenv import load_dotenv
from fastapi import FastAPI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langserve import add_routes

#API KEY
load_dotenv()

# 1. Create prompt template
system_template = "Translate the following into {language}:"
prompt_template = ChatPromptTemplate.from_messages([
    ('system', system_template),
    ('user', '{text}')
])

# 2. Create model
model = ChatOpenAI()

# 3. Create parser
parser = StrOutputParser()

# 4. Create chain
chain = prompt_template | model | parser

# 5. App definition
app = FastAPI(
  title="LangChain Server",
  version="1.0",
  description="A simple API server using LangChain's Runnable interfaces",
)

# 6. Adding chain route
add_routes(
    app,
    chain,
    path="/chain",
)

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="localhost", port=8000)


LangServe는 간단한 UI를 가진 Playground를 제공한다. 서버를 실행하고 Inputs에 번역할 텍스트와 language를 입력하면 번역 결과가 나온다.
Streamlit으로도 대화형 UI 프론트엔드를 구현할 수 있다.

import streamlit as st
from langserve import RemoteRunnable

st.title('Simple LLM Translator')

language = st.text_input("Language:")
text = st.text_input("Text:")

if st.button('전송'):
    remote_chain = RemoteRunnable("http://localhost:8000/chain/")
    result = remote_chain.invoke({"language": language, "text": text})
    st.write("응답:", result)

'인공지능' 카테고리의 다른 글

데이터 전처리  (0) 2024.10.22
생선 분류하기  (0) 2024.10.16
인공지능 스터디 2  (1) 2023.02.26
인공지능 1  (0) 2023.02.20