NIPA-ORACLE #16,17 - 랭그래프

HyunJunSon·2025년 10월 22일

NIPA-ORACLE

목록 보기
21/28

1. [LangGragh Index]

  1. 탄생 배경

    1) 랭체인으로 생성한 답변이 Hallucination이 아닐까? (없는사전지식으로 답변한게 아닐까?)
    2) 문서 검색에 원하는 내용이 없는경우, 인터넷, 논문에서 부족한 정보 검색해 보강할수 없을까?

  2. 2024-1월 출시

  3. 문제상황

    a. rag 수행시 정확한 문서를 검색하지 못하는 경우가 생김
    i. RAG + web 검색 합쳐서 정보 생성으로 보완
    b. 잘못된 정보포함, 검색걸과에 없다면? (Hallucination)
    i. 지속적으로 무한루프 검색 → 토큰사용량 폭증

  4. 기본적 RAG 문제점

    a. 사전에 정의된 데이터소싱(pdf,db,tabl), Fixed Size Chunk, Query 입 력, 검색방법
    b. 신뢰하기 어려운 LLM 혹은 Agent
    c. 고정된 프롬프트 형식
    d. LLM 답변 결과에 대한 문서와의 관련성/신뢰성
    e. Document Loader > Answer 의 단방향 구조 :: 모든 단계를 다 잘해야함. 이전단계로 돌아가기 어렵고, 이전 과정의 결과물을 수정하기 어려움

  5. 랭그래프의 제안

    1. 각 세부과정을 Node 라고 정의
    2. 이전노드 > 다음노드 : 엣지(Edge) 연결
    3. 조건부엣지를 통해 분기 처리
  6. 주요 용어

2. 랭그래프 요소

  1. State(상태)

class GraphState(TypedDict) :
  1. Node (노드)
    1) 함수로 구현
    2) 노드에 어떤값을 넘길지 직접 정의해서 넘김
    3) 처음에 “START”로 명시적 진입점을 만들어 줄수도 있고, 안해주면 처음 등록해 준 노드가 진입점으로 역할을 하게 된다.

  2. 엣지 - 노드간 연결

  3. 조건부 엣지

    1. 분기를 나눌수 있음
    2. add_conditional_edges(”노드이름”, “조건부판단함수”, “dict 다음단계 결정”)
  4. 시작점지정
    1. workfow.set_entry_point(”retrieve”)
    2. 시작점 지정전에 필요한 노드는 모드 등록해두어야 함
    . checkpointer = memory

  5. 그래프 시각화

    1. get_graph(xray=True).draw_mermaid_png()
  6. RunnableConfig ( recursion_limit (최대 노드 실행 개수 지정), thread_id)

3. [랭체인, 랭그래프의 응용]

Collective RAG

  • 배경 :RAG 답변 결과는 문서의 관련성에 크게 의존정, 따라서 검색이 잘못되면 답변 품질이 우려됨
  • 제안 : 사용자 입력 쿼리에 대해 검색된 문서의 품질 평가 → 사영자 입력쿼리와 관련성 높도록 쿼리를 수정

4. "노드 함수가 일반 딕셔너리를 반환하는데, 어떻게 이 딕셔너리가 GraphState 객체에 반영되어 LangGraph 전체에서 같은 상태를 유지할 수 있는가?"


`GraphState`는 `TypedDict`입니다.
       * TypedDict는 런타임 시에는 기본적으로 일반 Python 딕셔너리처럼 동작합니다., GraphState 인스턴스는 일반
         딕셔너리와 동일하게 키-값 쌍을 저장하고 접근할 수 있습니다.

   2. LangGraph의 상태 업데이트는 "병합(Merge)" 방식입니다.
       * LangGraph의 StateGraph는 각 노드 함수가 전체 `GraphState` 객체를 반환하도록 요구하지 않습니다.
       * 대신, 각 노드 함수는 현재 상태에 대한 "부분적인 업데이트"를 일반 Python 딕셔너리 형태로 반환합니다.
       * StateGraph는 이 반환된 딕셔너리(부분 업데이트)를 받아서, 자신이 내부적으로 관리하고 있는 현재 `GraphState` 
         객체에 병합(merge)합니다. 이 병합 과정은 Python 딕셔너리의 update() 메서드와 매우 유사하게 작동합니다.
       *, 노드 함수가 반환한 딕셔너리에 있는 키-값 쌍만 GraphState에서 업데이트되고, 반환된 딕셔너리에 없는 키들은
         GraphState에서 기존 값을 그대로 유지합니다.

5. LangGragh 주요 객체

# After a model makes a tool call
ai_message = AIMessage(
    content=[],
    tool_calls=[{
        "name": "get_weather",
        "args": {"location": "San Francisco"},
        "id": "call_123"
    }]
)

# Execute tool and create result message
weather_result = "Sunny, 72°F"
tool_message = ToolMessage(
    content=weather_result,
    tool_call_id="call_123"  # Must match the call ID
)

# Continue conversation
messages = [
    HumanMessage("What's the weather in San Francisco?"),
    ai_message,  # Model's tool call
    tool_message,  # Tool execution result
]
response = model.invoke(messages)  # Model processes the result

6. SubGraph Structure

  • 구현해볼것
  • 랭그래프를 어떻게 구성했는데 예시 코드와 종류를 많이 읽어보는걸 추천 (설계요소가 많이 필요하므로)

7. ReAct, CoT, ToT

ReAct, CoT, ToT는 모두 대규모 언어 모델(LLM)이 단순한 답변 생성을 넘어, 복잡한 문제를 더 정확하고 논리적으로 해결할 수 있도록 돕는 고급 프롬프팅(Prompting) 또는 추론(Reasoning) 기법입니다.

간단히 요약하면 다음과 같습니다.

  • CoT (Chain of Thought): "단계별로 생각하기"
  • ReAct (Reasoning and Acting): "생각하고, 도구 사용하기"
  • ToT (Tree of Thoughts): "여러 가능성을 탐색하고 최선책 찾기"

각각에 대해 자세히 설명해 드리겠습니다.


1. CoT (Chain of Thought): 생각의 사슬
  • *CoT(생각의 사슬)는 LLM이 복잡한 질문에 대해 최종 답변만 내놓는 것이 아니라, 답변에 도달하기까지의 중간 추론 과정을 단계별로(step-by-step) 서술하도록** 유도하는 기법입니다. (Source 3.1, 1.3)
  • 작동 방식: 사용자나 프롬프트가 모델에게 "차근차근 생각해 보자(Let's think step-by-step)"와 같은 지시어를 제공합니다. (Source 3.1)
  • 비유: 수학 문제를 풀 때, 답만 적는 것이 아니라 풀이 과정을 모두 적는 것과 같습니다.
  • 효과: 이 과정을 통해 모델은 복잡한 문제를 작은 단위로 나누어 생각하게 되므로, 특히 논리, 연산, 상식 추론 문제에서 정확도가 크게 향상됩니다. (Source 3.1)
  • 한계: 모델이 학습한 내부 지식에만 의존하기 때문에, 최신 정보가 없거나 사실이 아닌 정보(환각, Hallucination)를 기반으로 추론할 수 있습니다. (Source 3.2, 3.4)
2. ReAct (Reasoning and Acting): 추론과 행동
  • *ReAct(추론과 행동)는 CoT의 한계를 극복하기 위해 제안된 프레임워크입니다. LLM의 내부 추론(Reasoning) 능력과 외부 도구(Acting)를 사용하는 능력을 결합**한 것입니다. (Source 5.1, 5.3)
  • 작동 방식: 모델은 생각 → 행동 → 관찰 → 생각...의 순환 구조를 따릅니다. (Source 5.1, 5.4)
    1. Thought (추론): "서울의 현재 날씨를 알려면 정보가 필요해."
    2. Action (행동): 외부 도구(예: 구글 검색 API)를 호출합니다. search("서울 현재 날씨")
    3. Observation (관찰): 도구로부터 "서울 15°C, 맑음"이라는 결과를 받습니다.
    4. Thought (추론): "정보를 확인했으니, 사용자에게 답변할 수 있어."
    5. Final Answer: "서울의 현재 날씨는 15°C이며 맑습니다."
  • 비유: 사건을 해결하는 탐정이 머릿속으로 추리(Reasoning)만 하는 것이 아니라, 직접 증거를 수집(Acting)하러 나가는 것과 같습니다.
  • 효과: LLM이 최신 정보를 검색하거나, 계산기를 사용하거나, 특정 API를 호출하는 등 외부 세계와 상호작용할 수 있게 되어, CoT의 한계(내부 지식 의존)를 극복하고 더 사실에 기반한 답변을 생성할 수 있습니다. (Source 5.2)
3. ToT (Tree of Thoughts): 생각의 트리
  • *ToT(생각의 트리)는 CoT를 더욱 발전시킨 형태입니다. CoT가 하나의 선형적인 생각의 사슬을 따르는 반면, ToT는 문제 해결 과정에서 여러 개의 가능한 추론 경로(가지)를 동시에 탐색**합니다. (Source 4.3, 4.4)
  • 작동 방식:
    1. 가지치기 (Branching): 특정 단계에서 모델은 하나의 다음 단계가 아니라, 여러 개의 가능한 다음 생각(경로)을 생성합니다. (Source 4.3)
    2. 평가 (Evaluation): 생성된 각 생각(가지)이 최종 목표에 도달할 가능성이 얼마나 높은지 스스로 평가합니다. (Source 4.4)
    3. 탐색 (Search): 가장 유망한 경로를 선택하여 탐색을 계속 진행하며, 막다른 길에 다다르면 이전 단계로 돌아가(Backtracking) 다른 경로를 탐색합니다. (Source 4.4, 4.5)
  • 비유: 체스를 둘 때, 하나의 수만 생각하는 것(CoT)이 아니라, 여러 가능한 수와 그에 따른 상대방의 대응까지 여러 갈래로 미리 생각해 보는(ToT) 것과 같습니다.
  • 효과: 하나의 경로가 막혔을 때 포기하지 않고 다른 대안을 모색할 수 있어, 복잡한 계획, 퍼즐 풀이, 창의적인 글쓰기 등 탐색과 전략적 평가가 필요한 문제에서 CoT보다 뛰어난 성능을 보입니다. (Source 1.2)

요약 비교
기법핵심 개념비유주요 특징
CoT단계별 순차적 사고수학 풀이 과정 적기모델의 내부 지식을 활용해 논리적 오류를 줄임
ReAct사고 + 외부 도구 활용증거를 수집하는 탐정외부 정보(검색, API)에 접근하여 사실성을 높임
ToT다중 경로 탐색 및 평가체스 게임 전략 수립여러 해결책을 동시에 탐색하고 최적의 경로를 선택함

8. Guardrails

OpenAI가 말하는 '가드레일(Guardrails)'은 AI 모델(GPT 등)이 안전하고 윤리적인 범위 내에서 작동하도록 제어하는 '안전 장치' 또는 '정책 및 기술적 통제 시스템'을 의미합니다.

9. Open AI sdk

https://openai.github.io/openai-agents-python/

10. < lang server 관련 코드 생성 팁>

  1. 모델 생성은 함수로 구현하는 것보다는 전체로직에서 한번만 생성되도록 하는게 좋다.
  2. 세팅은 BasicSetting을 상속받은 객체로 한번에 관리해서 import 해서 사용
  3. 프로젝트구조도

LANGSERVE_API/
├── __pycache__/
├── .venv/
├── .vscode/
├── app/
│   ├── __pycache__/
│   ├── api/
│   └── interface/
│       ├── chunking/
│       ├── dao/
│       ├── dbconn/
│       ├── embedding/
│       ├── inference/
│       └── LLM/
│           ├── __pycache__/
│           └── call_api_llm.py
│
├── tools/
│   └── main.py
│
├── .env
├── config.json
├── config.py
├── crag_graph.png
├── Dockerfile
├── init_database.sql
├── requirements.txt
└── server.py

11. conda 환경 설정 설치법

conda install --yes --file requirements.txt

12. 설계에 도움이 되는 노코드 툴 - 먼저 설계 가능

  • makeAI
  • zapier
  • n8n ( 14일간 무료)
  • node-red (open source)
  • dify

13.


  prompt = ChatPromptTemplate.from_messages([
        ("system", system_prompt), 
        ("user", "{input}"), 
        AIMessage(content=""), 
        ("placeholder", "{agent_scratchpad}")
    ])
    

14. 랭체인과 -tool

  • 휴먼메시지에 대해 어떤 도구를 써야 한다는 tool_call의 정보는 llm의 응답을 통해 자동 작성된다.

  • tool 의 description과 매개변수, 이름 정보를 바탕으로 llm 이 추론함
  • description은 의무는 아니지만, 사실상 매우 중요합니다.
  • LLM이 “이 도구가 어떤 일을 하는지”를 알 수 있는 유일한 설명이기 때문이에요.
  • 실무에서는 거의 항상 docstring 형태로 간단한 한 줄 설명을 넣는 게 베스트 프랙티스입니다.

15. llm.with_structured_output(Tasks)


prompt = ChatPromptTemplate.from_messages([
            ("system", system_prompt),
            ("user", "주어진 요청: {input}\n\n이 요청을 다음 팀원들에게 할당할 구체적인 하위 작업 목록으로 분해해주세요: {members_str}")
        ])
        
        # with_structured_output(Tasks): LLM이 Tasks 모델 형식으로 출력하도록 강제
        # 이를 통해 JSON 파싱 없이 바로 Python 객체로 받을 수 있음
        chain = prompt | llm.with_structured_output(Tasks)
        

llm.with_structured_output(Tasks) 는 LangChain의 출력 구조화 기능으로, LLM이 “자연어 텍스트” 대신 지정한 Pydantic 모델 형식으로 정확히 맞춘 결과를 생성하도록 강제하는 메서드임

profile
즐겁게 공부하고 사람들에게 도움을 주는 개발자가 되고 싶습니다.

0개의 댓글