인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

SEO님의 프로필 이미지

작성한 질문수

LangGraph를 활용한 LLM Agent 개발

langgraph를 streamlit과 연동(?)하는 과정에서 질문이 있습니다.

해결된 질문

작성

·

66

0

안녕하세요! section3을 듣고나서 제 나름대로 langgraph를 만들고 이걸.. streamlit으로 구현을 해봤는데요. 이번 강의에서와 같이 chat-history를 checkpointer를 사용해서 연결하려고하면 Checkpointer requires one or more of the following 'configurable' keys: ['thread_id', 'checkpoint_ns', 'checkpoint_id'] 이런 오류가 뜨고 있는 상태입니다.

chat-gpt와 구글 서치를 통해 나름대로 아래와 같이 해보았지만(간략하게 서술하면 CustomMememorySaver라는 클라스를 통해 ['thread_id', 'checkpoint_ns', 'checkpoint_id'] 를 checkpointer에 넣는 것입니다.) 이 역시 제대로 동작하지 않습니다.

system_message_template = SystemMessagePromptTemplate.from_template("You are a helpful assistant.")
chat_prompt = ChatPromptTemplate.from_messages([system_message_template])

# 세션 키 생성 (세션 관리)
def generate_session_key():
    if 'session_key' not in st.session_state:
        st.session_state['session_key'] = str(uuid.uuid4())
    return st.session_state['session_key']

# Checkpointer 설정 (세션 상태 관리)
class CustomMemorySaver(MemorySaver):
    def __init__(self, session_key):
        super().__init__()
        self.session_key = session_key

    def get_checkpoints(self):
        # 필요한 체크포인트 정보 반환
        return {
            "thread_id": self.session_key,  # session_key를 thread_id로 사용
            "checkpoint_ns": "default",  # 기본 네임스페이스
            "checkpoint_id": f"checkpoint_{self.session_key}"  # 고유한 checkpoint_id
        }

# 시스템 메시지와 메모리 체크포인터 설정
session_key = generate_session_key()
checkpointer = CustomMemorySaver(session_key=session_key)

# LangGraph만을 사용한 에이전트 생성 (tools는 빈 리스트로 설정)
agent_executor = create_react_agent(llm, [], state_modifier=chat_prompt, checkpointer=checkpointer)

또, 예전 langchain 강의에서 알려주셨던 chat-with-history 코드를 활용하려는 시도도 해봤는데요. (가독성을 위해 프롬프트 내용이나 중간 중간 선언 내용은 지웠습니다.) 하지만 이거 같은 경우에는 langgraph를 사용하는 입장에서, rag-chain을 ai_response에 넣는 과정을 어떻게 처리해야될지 모르겠어서 중도포기한 상태입니다. ㅠㅠ;;

store = {}

def get_session_history(session_id: str) -> BaseChatMessageHistory:
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

def get_rag_chain():
    llm = get_llm()
    retriever = get_retriever()
    contextualize_q_system_prompt = ("생략")
    contextualize_q_prompt = "생략"
    history_aware_retriever = create_history_aware_retriever(
    llm, retriever, contextualize_q_prompt
    )
    system_prompt = ("생략")
    qa_prompt = ChatPromptTemplate.from_messages("생략")
    question_answer_chain = create_stuff_documents_chain(llm, qa_prompt)  
    rag_chain = create_retrieval_chain(history_aware_retriever, question_answer_chain)
    conversational_rag_chain = RunnableWithMessageHistory(
    "생략"
    history_messages_key="chat_history",
    output_messages_key="answer",
    ).pick('answer')
    return conversational_rag_chain

def get_ai_response(user_message):
    rag_chain = get_rag_chain()   
    loan_chain ={"input": dictionary_chain} | rag_chain
    ai_message = loan_chain.stream(
        {
            "question": user_message
        },
        config={
            "configurable": {"session_id": "abc123"}
        },
    )
    return ai_message

결론적으로 말하면 langgraph로 어떻게해야 langchain에서 했던것처럼 streamlit상에서 구현할 수 있을지 궁금합니다! 질문 읽어주셔서 감사합니다!

답변 1

1

강병진님의 프로필 이미지
강병진
지식공유자

안녕하세요! 좋은 질문 감사합니다.

사실 streamlit은 production에서 쓰기 어렵다고 판단해서 LangGraph와는 연동을 해보지 못해 저도 질문해주신 덕분에 처음으로 시도해봤습니다.

여기서 장황하게 설명하는 것 보다는 코드를 보시는게 이해하기 편하실 것 같아서, .invoke() 를 활용해서 답변을 출력하는 chat.py.stream() 을 활용해서 답변을 출력하는 chat_stream.py 를 추가해서 소스코드에 반영해두었습니다. invoke()는 간단한데, stream()은 쉽지 않더라구요. 자료를 찾던 와중에 LangGraph + Streamlit Cookbook을 발견해서 참고해서 작성했습니다.

한번 확인 부탁드립니다!

https://github.com/jasonkang14/inflearn-langgraph-agent

SEO님의 프로필 이미지
SEO
질문자

와우.. 선생님 감사합니다! 이렇게 코드까지 주실줄이야ㅠㅠ 실은 답변주시고 30분 정도 후에 확인했는데, 본 뒤로 제 코드에 적용하려니까 바로 안돼서 혼자 지지고 볶다가 스알짝 찝찝하긴하지만 지금은 chat.py로 원하는대로 됐어요! 내일부터는 chat_stream 동작에 도전하겟습니다. 정말 감사합니다 bb..

SEO님의 프로필 이미지

작성한 질문수

질문하기