5장 · 에이전트 ③ CSV 데이터분석 — 절 목차01. 루프를 매번 손으로 짤 필요가 없다02. LangChain 설치와 모델 가져오기03. tool 데코레이터 함수를 도구로 등록하기04. create_agent 한 줄이 대신해 주는 것05. LLM은 계산기가 아니다 숫자는 코드에게06. 따라하기 pandas 식을 실행하는 도구 만들기07. 남의 코드를 실행한다는 것 안전장치 걸기08. 따라하기 한국어로 묻고 집계 결과 받기09. 4장 코드와 나란히 놓고 보기10. 정리 체크리스트
정리 & 체크리스트
한 줄 요약
세 번째 에이전트를 완성했고, 실무에서 쓰는 방식으로 전환했습니다. 6장에서는 마지막 종류인 RAG 문서검색을 만들고, 1장의 세 번째 질문을 풉니다.
1. 5장에서 만든 것
code/ch05_csv_agent.py — 에이전트 ③ CSV 데이터분석
연결 대상 : 표 데이터 (자유로운 집계)
핵심 기술 : 코드 생성 · 실행
대표 질문 : "카테고리별 매출 상위 3개는?"
| 만든 것 | 하는 일 |
|---|---|
run_pandas(expr) |
도구 — pandas 식을 실행 |
SAFE_BUILTINS |
안전장치 — 허용된 내장 함수만 |
agent |
create_agent 한 줄 |
ask(question) |
묻고 답 받기 |
2. 이 장의 핵심 내용 — 말로 설명할 수 있어야 할 것들
- ReAct 루프는 에이전트마다 거의 같다. 달라지는 건 도구와 시스템 지시뿐이라 라이브러리가 대신 돌린다.
create_agent(모델, tools, system_prompt)한 줄이 4장의 30줄을 대신한다.agent.invoke({"messages": [...]})로 부르고out["messages"][-1].text로 답을 꺼낸다.out["messages"]에는 질문·도구 호출 요청·실행 결과·최종 답변이 다 들어 있다. 4장의history와 같다.@tool데코레이터로 함수를 도구로 등록한다. 부를 때는invoke({"arg": value}).- 독스트링과 타입힌트가 설명서라는 원칙은 3장과 똑같다.
- LLM은 계산기가 아니다. 데이터를 통째로 주고 집계시키면 틀리고, 틀려도 그럴듯하게 나온다.
- 숫자 자체는 절대 LLM이 만들지 않는다. LLM은 계산식을 만들고, pandas가 계산한다.
- 모델이 알 수 없는 규칙(취소·환불 제외)은 사람이 알려 줘야 한다. 안 알려 주면 오류 없이 잘못된 답이 나온다.
eval에__builtins__화이트리스트를 걸어open·__import__를 막는다. 보안은 항상 화이트리스트.- 이 안전장치는 생각보다 훨씬 약하다.
pd.io.common.os.system(...)으로 셸 명령이 실행되고.env의 API 키까지 읽힌다.SAFE_BUILTINS는 공격 방어가 아니라 사고 방지다. - 금지 목록(블랙리스트)은 소용없다. 실서비스라면 격리 실행이 유일하게 확실하다. 유연성과 안전성은 한쪽을 높이면 다른 쪽이 낮아지는 관계다.
- 실행 지점이 우리 쪽이라서 검사를 끼워 넣을 수 있다. 라이브러리를 쓰면 그 자리가 도구 안으로 옮겨 간다.
- 반복 상한(
recursion_limit)은 명시해야 한다. 기본값이10007이라 안 적으면 사실상 무제한이다.MAX_STEPS=5≈recursion_limit=10. - 에이전트가 낸 숫자는 대조해 확인한다. 오류가 안 나는 오답이 가장 위험하다.
3. 체크리스트
- [ ]
python code/ch05_csv_agent.py가 끝까지 돌아간다 - [ ] 숫자 세 개를 대조해 봤다 (제공된 정답 식으로, 또는 같은 것을 다르게 물어서)
- [ ]
out["messages"]를 찍어 모델이 만든 식을 봤다 - [ ] 독스트링에서 규칙을 지우면 숫자가 달라지는 것을 직접 확인했다
- [ ]
__import__와open이 막히는 것을 직접 확인했다 - [ ] 4장
run_agent와 5장create_agent가 같은 일을 한다고 설명할 수 있다 - [ ]
recursion_limit을 왜 명시해야 하는지 설명할 수 있다 (4장MAX_STEPS와 같은 이야기)
4. 진행 상황
[에이전트 네 종류]
✓ ① 사내 데이터 조회 3장 함수 도구
✓ ② 웹검색 4장 외부 API + ReAct 루프
✓ ③ CSV 데이터분석 5장 코드 생성·실행 + LangChain
□ ④ RAG 문서검색 6장 임베딩 · 벡터검색
[1장에서 못 푼 세 질문]
✓ 사내 데이터 · ✓ 최신 정보 · □ 사내 문서 ← 6장
5. 6장 예고 — 표가 아니라 긴 글에 답이 있을 때
지금까지 만든 세 에이전트로 답할 수 없는 질문이 남았습니다.
"승승장구몰에서 불량 상품 반품은 며칠 이내에 신청해야 하나요?"
orders.csv에? 없습니다. 주문 데이터일 뿐입니다.- 웹에? 승승장구몰은 가상의 회사입니다.
- 계산으로? 계산할 게 없습니다.
답은 data/docs/환불교환정책.pdf 안에 문장으로 적혀 있습니다.
5장과 6장의 결정적 차이
[5장] 표에 든 숫자 → 코드로 계산한다
[6장] 문서에 쓰인 문장 → 검색해서 근거로 쓴다
"평균 평점 3.8" 은 계산이고, "수령일로부터 30일 이내" 는 문장입니다. 문장은 계산할 수 없습니다. 찾아서 그대로 인용해야 합니다.
새로 배우는 것
문서를 검색하려면 "의미가 비슷한 것"을 찾는 방법이 필요합니다. 사용자는 "반품 며칠?"이라고 묻는데 문서에는 "청약철회 기간은 수령일로부터..."라고 적혀 있을 수 있으니까요. 단어가 안 겹칩니다.
그래서 임베딩(embedding) 을 씁니다 — 문장을 숫자로 바꿔, 뜻이 비슷하면 숫자도 비슷하게 만드는 기술입니다.
이 방식 전체를 RAG(Retrieval-Augmented Generation, 검색 증강 생성) 라고 부릅니다.
① 로드 PDF를 읽는다
② 청킹 긴 글을 검색하기 좋은 조각으로 자른다
③ 임베딩 조각을 '의미를 담은 숫자'로 바꾼다
④ 저장 벡터를 인덱스에 담아 파일로 보관한다 ← 한 번만
⑤ 검색 질문과 가까운 조각을 찾아 근거로 쓴다
그리고 6장에서 처음으로 답에 출처를 붙입니다.
Q: 불량 상품 반품은 며칠 이내에 신청해야 하나요?
A: 상품 불량·하자로 인한 반품은 상품 수령일로부터 30일 이내에 신청하셔야 합니다.
근거: 환불교환정책.pdf 1쪽, 환불교환정책.pdf 2쪽
1장에서 "3개월 이내"라고 지어냈던 그 질문입니다. 근거와 함께 정확한 답이 나옵니다.