탄생 배경
1) 랭체인으로 생성한 답변이 Hallucination이 아닐까? (없는사전지식으로 답변한게 아닐까?)
2) 문서 검색에 원하는 내용이 없는경우, 인터넷, 논문에서 부족한 정보 검색해 보강할수 없을까?
2024-1월 출시
문제상황
a. rag 수행시 정확한 문서를 검색하지 못하는 경우가 생김
i. RAG + web 검색 합쳐서 정보 생성으로 보완
b. 잘못된 정보포함, 검색걸과에 없다면? (Hallucination)
i. 지속적으로 무한루프 검색 → 토큰사용량 폭증
기본적 RAG 문제점
a. 사전에 정의된 데이터소싱(pdf,db,tabl), Fixed Size Chunk, Query 입 력, 검색방법
b. 신뢰하기 어려운 LLM 혹은 Agent
c. 고정된 프롬프트 형식
d. LLM 답변 결과에 대한 문서와의 관련성/신뢰성
e. Document Loader > Answer 의 단방향 구조 :: 모든 단계를 다 잘해야함. 이전단계로 돌아가기 어렵고, 이전 과정의 결과물을 수정하기 어려움
랭그래프의 제안
주요 용어

class GraphState(TypedDict) :
Node (노드)
1) 함수로 구현
2) 노드에 어떤값을 넘길지 직접 정의해서 넘김
3) 처음에 “START”로 명시적 진입점을 만들어 줄수도 있고, 안해주면 처음 등록해 준 노드가 진입점으로 역할을 하게 된다.
엣지 - 노드간 연결
조건부 엣지
시작점지정
1. workfow.set_entry_point(”retrieve”)
2. 시작점 지정전에 필요한 노드는 모드 등록해두어야 함
. checkpointer = memory
그래프 시각화
RunnableConfig ( recursion_limit (최대 노드 실행 개수 지정), thread_id)
Collective RAG
`GraphState`는 `TypedDict`입니다.
* TypedDict는 런타임 시에는 기본적으로 일반 Python 딕셔너리처럼 동작합니다. 즉, GraphState 인스턴스는 일반
딕셔너리와 동일하게 키-값 쌍을 저장하고 접근할 수 있습니다.
2. LangGraph의 상태 업데이트는 "병합(Merge)" 방식입니다.
* LangGraph의 StateGraph는 각 노드 함수가 전체 `GraphState` 객체를 반환하도록 요구하지 않습니다.
* 대신, 각 노드 함수는 현재 상태에 대한 "부분적인 업데이트"를 일반 Python 딕셔너리 형태로 반환합니다.
* StateGraph는 이 반환된 딕셔너리(부분 업데이트)를 받아서, 자신이 내부적으로 관리하고 있는 현재 `GraphState`
객체에 병합(merge)합니다. 이 병합 과정은 Python 딕셔너리의 update() 메서드와 매우 유사하게 작동합니다.
* 즉, 노드 함수가 반환한 딕셔너리에 있는 키-값 쌍만 GraphState에서 업데이트되고, 반환된 딕셔너리에 없는 키들은
GraphState에서 기존 값을 그대로 유지합니다.
# 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

ReAct, CoT, ToT는 모두 대규모 언어 모델(LLM)이 단순한 답변 생성을 넘어, 복잡한 문제를 더 정확하고 논리적으로 해결할 수 있도록 돕는 고급 프롬프팅(Prompting) 또는 추론(Reasoning) 기법입니다.
간단히 요약하면 다음과 같습니다.
각각에 대해 자세히 설명해 드리겠습니다.
생각 → 행동 → 관찰 → 생각...의 순환 구조를 따릅니다. (Source 5.1, 5.4)search("서울 현재 날씨")| 기법 | 핵심 개념 | 비유 | 주요 특징 |
|---|---|---|---|
| CoT | 단계별 순차적 사고 | 수학 풀이 과정 적기 | 모델의 내부 지식을 활용해 논리적 오류를 줄임 |
| ReAct | 사고 + 외부 도구 활용 | 증거를 수집하는 탐정 | 외부 정보(검색, API)에 접근하여 사실성을 높임 |
| ToT | 다중 경로 탐색 및 평가 | 체스 게임 전략 수립 | 여러 해결책을 동시에 탐색하고 최적의 경로를 선택함 |
OpenAI가 말하는 '가드레일(Guardrails)'은 AI 모델(GPT 등)이 안전하고 윤리적인 범위 내에서 작동하도록 제어하는 '안전 장치' 또는 '정책 및 기술적 통제 시스템'을 의미합니다.
https://openai.github.io/openai-agents-python/
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
conda install --yes --file requirements.txt
prompt = ChatPromptTemplate.from_messages([
("system", system_prompt),
("user", "{input}"),
AIMessage(content=""),
("placeholder", "{agent_scratchpad}")
])


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 모델 형식으로 정확히 맞춘 결과를 생성하도록 강제하는 메서드임