정리 & 체크리스트
한 줄 요약
두 번째 에이전트를 완성했고, 에이전트 루프의 내부를 손으로 짜 봤습니다. 5장부터는 이 루프를 라이브러리가 내부에서 처리합니다. 여기까지가 "안이 보이는" 마지막 장입니다.
1. 4장에서 만든 것
code/ch04_web_agent.py — 에이전트 ② 웹검색
연결 대상 : 인터넷 (실시간·외부)
핵심 기술 : 외부 API 도구 + ReAct 루프
대표 질문 : "요즘 스마트워치 시장 어때요?"
| 만든 것 | 하는 일 |
|---|---|
get_product_info(product_name) |
도구 — 자사 상품 조회 (부분 일치) |
search_web(query) |
도구 — DuckDuckGo 검색 |
TOOLS 딕셔너리 |
이름 → 함수 |
run_agent(question) |
ReAct 루프를 직접 도는 에이전트 |
MAX_STEPS |
안전장치 |
2. 이 장의 핵심 내용 — 말로 설명할 수 있어야 할 것들
- LLM에는 지식 컷오프가 있고, 그 이후는 모른다. 위험한 것은 모른다고 말하지 않는 점이다.
ddgs는 API 키 없이 쓸 수 있다. 대신 호출이 몰리면 막힌다.- 검색 결과를 문자열로 다듬는 것이 우리 일이다. 무엇을 넣고 무엇을 자를지가 사람의 판단이다.
- 모델은 도구 명세와 시스템 지시만 보고 도구를 고른다. 독스트링의 경계선이 선택을 좌우한다.
- 도구가 많아지면 정확도가 떨어진다. 그래서 8장에서 나눈다.
- ReAct = 생각 → 행동 → 관찰 → 다시 생각. 코드로는
for문 하나다. - 종료 조건은 "부를 도구가 없다" 이다. 모델이 스스로 판단한다.
- 모델의 결정과 실행 결과를 둘 다
history에 기록해야 한다. 하나라도 빠지면 앞뒤가 안 맞는다. - 도구 실행 결과의
role은user다. 모델 입장에서 "밖에서 온 정보"이기 때문이다. while True는 위험하다. 단계가 늘수록history가 커져 한 단계의 비용도 커진다.MAX_STEPS로 상한을 건다. 정상 질문이 끝나는 단계 수의 두 배쯤이 무난하다.- 도구는 실패할 것을 전제로 만든다. 예외를 던지지 말고 상황을 설명하는 문장을 돌려준다.
- 실패했다는 사실도 정보다. 그래서 모델이 지어내지 않는다.
3. 체크리스트
- [ ]
python code/ch04_web_agent.py가 끝까지 돌아간다 (검색 실패는 괜찮음) - [ ] 단계가 몇 번 돌았는지, 어떤 순서였는지 화면에서 읽을 수 있다
- [ ] 순서를 우리가 정하지 않았다는 것을 설명할 수 있다
- [ ]
history.append두 곳이 각각 무엇을 넣는지 설명할 수 있다 - [ ] 그중 하나를 지우면 무엇이 무너지는지 직접 해 봤다
- [ ]
MAX_STEPS가 왜 필요한지 설명할 수 있다 - [ ] 검색이 실패해도 답변이 나오는 이유를 설명할 수 있다
4. 진행 상황
[1장에서 못 푼 세 질문]
✓ 사내 데이터 "주문 O001203은 어떤 상태인가요?" ← 3장 완료
✓ 최신 정보 "요즘 스마트워치 시장 어때요?" ← 4장 완료
□ 사내 문서 "불량 반품은 며칠 이내인가요?" ← 6장
[에이전트 네 종류]
✓ ① 사내 데이터 조회 3장
✓ ② 웹검색 4장
□ ③ CSV 데이터분석 5장
□ ④ RAG 문서검색 6장
5. 5장 예고 — 30줄이 한 줄이 됩니다
5장에서는 LangChain 을 씁니다. 그러면 이번 장에 손으로 짠 run_agent 30줄이 7절 4번에서 본 create_agent(...) 한 줄로 줄어듭니다. history 관리, 종료 판정, 도구 실행, 결과 기록을 전부 라이브러리가 합니다.
그리고 만드는 에이전트도 새로운 종류입니다 — CSV 데이터분석.
3장 CSV 조회와 무엇이 다른가
[3장] "주문 O001203 상태는?"
→ 정해진 조회. 질문이 바뀌어도 하는 일은 같다
[5장] "카테고리별 매출 상위 3개는?"
→ 매번 다른 계산. 계산식 자체가 달라진다
"카테고리별로 묶어서 합계를 내고 상위 3개를 뽑아라" 같은 계산을 미리 함수로 만들어 둘 수는 없습니다. 질문이 무한히 많으니까요.
그래서 5장의 도구는 이렇게 생겼습니다.
아래는 개념 설명용 코드입니다 — 실습 파일에 넣지 않습니다.
@tool
def run_pandas(expr: str) -> str:
"""승승장구몰 데이터를 pandas 식 한 줄로 계산한다."""
result = eval(expr, ...)
return str(result)
함수 위의
@tool은 표시 한 줄입니다. 파이썬에서 이런 걸 데코레이터라고 부릅니다. 함수 자체는 3장에서 만든 것과 똑같은 평범한 파이썬 함수이고, LangChain이 "이건 도구다"라고 알아볼 수 있게 꼬리표만 붙인 것입니다. 3장 1절에서 "구글 SDK에서는 함수 위에 아무것도 안 붙인다"고 한 그 자리에, LangChain은 이 한 줄을 요구합니다. 5장에서 정식으로 다룹니다.
모델이 pandas 식을 만들고, 우리가 실행합니다. 3장 2절에서 그은 그 경계선이 여기서 진짜 위력을 발휘합니다 — 실행이 우리 쪽 일이므로 위험한 코드를 걸러 낼 수 있습니다.
그리고 이런 질문에 답하게 됩니다.
Q: P0003 스마트워치의 현재 재고와 재주문 기준을 알려주세요.
A: P0003 스마트워치의 현재 재고는 3개이며, 재주문 기준은 30개입니다.
재고 3개, 기준 30개. 이 숫자를 기억해 두세요. 8장에서 다시 만납니다.