그린랩스
경력근거: LLM, tool calling, MCP를 활용한 AI Agent와 대화형 서비스를 개발하고
※ 실제 산출물이 아닌 AI 예측 시안입니다.
이 에이전트가 보여주는 것은 도구 호출(tool calling)과 MCP로 여러 데이터원을 엮어 근거 있는 답을 만드는 기술이며, 농업 도메인 전문성을 주장하지 않습니다. 다만 이 사슬이 말이 되려면 그린랩스 팜모닝의 장터 시세·영농일지·93만 농민이라는 고유 데이터 맥락이 있어야 합니다. ‘배추를 언제 파느냐’ 는 판단은 그 장터 시세와 그 농민의 일지가 붙어야 의미가 생기고, 다른 회사 데이터로는 같은 사슬을 그대로 만들 수 없습니다. 농산물 수급·가격에 대한 도메인 깊이는 면접에서 모르면 모른다고 말하는 편이 낫습니다.
‘LLM, tool calling, MCP를 활용한 AI Agent와 대화형 서비스’ 가 주요업무이자 우대사항입니다. 답을 지어내는 챗봇이 아니라, 시세·날씨·일지 도구를 실제로 호출해 근거를 물어오는 에이전트가 핵심 보여줄 대상입니다.
장터의 전시·검색·주문·결제와 팜모닝의 영농일지·날씨를 React로 개발하며, 요구사항 구체화부터 출시·운영까지 주도합니다. 에이전트가 물어올 데이터가 이 커머스·영농 도메인에서 나옵니다.
‘해야 할 일을 스스로 발견하고 데이터로 의사결정’ 이 요구 역량입니다. 에이전트도 답을 단정하지 않고 조회한 근거와 확신도를 함께 내, 사람이 판단할 재료를 줍니다.
농민이 ‘이번 주 배추 언제 파는 게 나을까요’ 처럼 자연어로 물으면, 에이전트가 장터 시세 조회·날씨 조회·내 영농일지 조회 도구를 스스로 호출해 필요한 숫자를 모은 뒤, 근거와 확신도를 붙여 답합니다. 어떤 도구를 어떤 인자로 불렀는지 호출 기록이 남아, 답이 어느 데이터에서 나왔는지 되짚을 수 있습니다. 1주차만으로 완성품이고, 답이 실제로 맞았는지 확인(2주차)·여러 도구를 엮는 다단계 질의(3주차)로 키웁니다. (근거는 채용공고 정렬입니다.)
팜모닝 PE. 농민 문의가 올 때마다 시세 화면·날씨 앱·영농일지를 손으로 오가며 답을 만들어주던 상황을 끝내고, 에이전트가 근거까지 붙여 답하되 그 답이 실제로 맞았는지까지 확인하고 싶은 사람입니다.
시세·날씨·영농일지를 각각 도구(함수)로 노출하고 스키마로 호출 형식을 강제하면, LLM 에이전트가 자연어 질문을 받아 (a) 필요한 도구를 골라 인자와 함께 호출하고, (b) 물어온 숫자를 근거로 인용해 답하며, (c) 지어낸 값이 아니라 실제 조회 결과만 답에 쓴다는 걸 도구 호출 기록으로 보여줄 수 있습니다.
농민 질문을 받아 시세·날씨·영농일지 세 도구 중 필요한 것을 골라 호출하고, 물어온 숫자를 근거로 인용해 답하는 동작하는 대화형 에이전트입니다. 도구 호출 기록과 인용 근거가 답마다 남습니다.
지난 답이 인용한 시세·날씨가 실제 다음 값과 맞았는지 대조하고, 농업 상담 페르소나 검토자 2명이 답의 근거가 타당한지 라벨링해 신뢰도를 보여주는 대시보드입니다.
‘지난주 대비 오른 품목 중 내가 재배하는 것만 알려줘’ 처럼 시세 조회와 영농일지 조회를 순서대로 엮어야 답하는 다단계 질문까지 처리하는 단계입니다.
농민 질문 30종을 넣으면, 필요한 도구를 골라 호출하고 물어온 숫자를 근거로 인용해 답하는 걸 몇 초 안에 시연합니다
답에 쓴 숫자가 전부 도구 조회 결과에 실제로 있는지 자동 대조합니다. 조회에 없는 값을 답에 쓰면 100% 차단되는 걸 보여줍니다
일부러 만든 실패 질의(존재하지 않는 품목·결측 시세·엉뚱한 질문) 30종을 넣어도 출력 형식이 안 깨지고 ‘조회 실패’ 로 정직하게 답합니다
내가 만든 정답 30개 중 올바른 도구 선택이 일치한 게 25개(83%). 단, 정답과 데이터를 모두 내가 만든 합성 기준이라 ‘성능 검증’ 이 아니라 ‘데모 조건에서의 동작’ 임을 밝힙니다
위 수치는 전부 작성자가 만든 더미데이터 자가채점이며, 실제 도구 선택 정확도·답변 신뢰도는 그린랩스 실 장터 시세와 실 농민 일지, 실무 검토자가 있어야 측정 가능합니다. 이 도구는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다.
이건 고객·실데이터 없이 혼자 만든 포트폴리오라, 수치는 합성 데이터 자가채점이라 성능 증명이 아닙니다. 면접에서 ‘데모 동작 + 실검증 준비 상태’ 로 솔직히 설명합니다
정답을 작성자가 만들었으니 잘 맞는 것이 당연합니다. 존재하지 않는 품목·결측 시세·다단계 함정 질의를 더미에 일부러 섞어, 쉬운 질문만 푸는 게 아님을 보여줍니다
이 포트폴리오가 보여주는 것은 도구 호출·다단계 오케스트레이션 기술이지 농산물 수급·가격 전망 도메인 전문성이 아닙니다. 시세 판단의 깊이는 실무자 검토가 있어야 하고, 면접에서 모르는 부분은 모른다고 말하는 편이 낫습니다
품목 이름 표기가 제각각입니다(배추·알배추·절임배추). 이름 유사도 + 분류 필터로 같은 품목으로 묶고, 못 묶은 건 추측하지 않고 ‘미매핑’ 으로 알립니다
실제 도입 시 달라지는 것 명시합니다. 실 시세·일지 분포는 더미와 다르므로 도구 인자·확신도 기준을 다시 맞춰야 하고, 검토자도 실무자로 교체해야 합니다(도입 단계 과제로 분리)
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
장터 품목별 일일 시세. 시세 조회 도구가 물어오는 표입니다. 시세 미집계(결측)·미등록 신규 품목(orphan)·별칭 표기·경계값을 일부러 섞어, 도구가 결측·미매핑을 만났을 때도 지어내지 않고 정직하게 답하는지 보여줍니다.
| date | region | crop_raw | crop_id | grade | price_krw_per_kg | volume_kg |
|---|---|---|---|---|---|---|
| 2026-05-11 | 가락시장 | 배추 | c_cabbage | high | 940 | 128,000 |
| 2026-05-11 | 가락시장 | 알배추 | c_cabbage | mid | 780 | 41,000 |
| 2026-05-11 | 대구북부 | 무 | c_radish | high | 620 | 88,000 |
| 2026-05-12 | 가락시장 | 배추 | c_cabbage | high | 1,010 | 119,000 |
| 2026-05-12 | 가락시장 | 대파 | c_greenonion | high | 2,450 | 33,000 |
아래 JSON Schema 에 맞는 한국 농산물 도매 시세 14일치 JSON 배열로 생성합니다. 지역 2~3곳(가락시장·대구북부 등), 품목 6~8종, 등급 분포 포함.
{"type":"object","properties":{"date":{"type":"string"},"region":{"type":"string"},"crop_raw":{"type":"string"},"crop_id":{"type":["string","null"]},"grade":{"type":"string","enum":["special","high","mid","low"]},"price_krw_per_kg":{"type":["integer","null"]},"volume_kg":{"type":["integer","null"]}},"required":["date","region","crop_raw","grade"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라: (1) 같은 품목의 별칭 표기(배추/알배추/절임배추 → crop_id c_cabbage 로 정규화돼야 함), (2) 미등록 신규 품목(crop_id=null) 2~3건, (3) 결측. price_krw_per_kg/volume_kg 가 null 인 미집계 행 1~2건, (4) 경계값 저가 대폭락(low 등급 300원대)·급등(전일 대비 +25% 이상) 각 1~2건. JSON 배열만.{"type":"object","properties":{"date":{"type":"string"},"region":{"type":"string"},"crop_raw":{"type":"string"},"crop_id":{"type":["string","null"]},"grade":{"type":"string","enum":["special","high","mid","low"]},"price_krw_per_kg":{"type":["integer","null"]},"volume_kg":{"type":["integer","null"]}},"required":["date","region","crop_raw","grade"]}농민별 영농일지(재배 품목·파종·수확 예정). ‘내가 재배하는 것만’ 같은 다단계 질의에서 일지 조회 도구가 물어오는 표입니다. 파종일 결측·미등록 품목·중복 표기를 섞어, 일지 조회가 불완전할 때도 정직하게 답하는지 보여줍니다.
| farmer_id | crop_raw | crop_id | region | planted_on | expected_harvest | area_pyeong |
|---|---|---|---|---|---|---|
| f_001 | 배추 | c_cabbage | 강원평창 | 2026-03-20 | 2026-05-25 | 1,200 |
| f_001 | 무 | c_radish | 강원평창 | 2026-03-22 | 2026-05-28 | 600 |
| f_002 | 대파 | c_greenonion | 전남진도 | 2026-02-10 | 2026-05-15 | 900 |
| f_002 | 양파 | c_onion | 전남진도 | — | 2026-06-10 | 1,500 |
| f_003 | 절임용 배추 | c_cabbage | 충북괴산 | 2026-03-18 | 2026-05-24 | 2,000 |
아래 JSON Schema 에 맞는 팜모닝 영농일지 30행 JSON 배열로 생성합니다. farmer_id 10명 내외, 품목은 market_prices 의 crop_id 와 매칭되도록.
{"type":"object","properties":{"farmer_id":{"type":"string"},"crop_raw":{"type":"string"},"crop_id":{"type":["string","null"]},"region":{"type":"string"},"planted_on":{"type":["string","null"]},"expected_harvest":{"type":["string","null"]},"area_pyeong":{"type":["integer","null"]}},"required":["farmer_id","crop_raw","region"]}
쉬운 데이터만 만들지 말 것. 하드 케이스 의도적 혼입: (1) planted_on/expected_harvest/area_pyeong 가 null 인 미입력 행 각 1~2건, (2) market_prices 에 없는 품목(crop_id=null) 1~2건, (3) 같은 품목 별칭 표기(‘절임용 배추’→c_cabbage). JSON 배열만.{"type":"object","properties":{"farmer_id":{"type":"string"},"crop_raw":{"type":"string"},"crop_id":{"type":["string","null"]},"region":{"type":"string"},"planted_on":{"type":["string","null"]},"expected_harvest":{"type":["string","null"]},"area_pyeong":{"type":["integer","null"]}},"required":["farmer_id","crop_raw","region"]}| Python | FastAPI 도구 서버(시세·날씨·일지 조회 함수를 함수 호출 스키마로 노출) + 에이전트 오케스트레이션 |
| TypeScript | React 채팅 UI + 도구 호출 기록·인용 근거 카드 렌더링 |
| React | 농민이 질문하고 답과 근거를 보는 대화형 화면 |
| PostgreSQL | market_prices / weather_daily / farm_journal / tool_call_log 단일 진실원과 조회 뷰 |
| GraphQL | 도구가 조회하는 커머스·영농 데이터 질의 계층 |
| Kafka | 3주차 다단계 질의에서 도구 호출 결과를 이어 붙이는 비동기 이벤트 흐름 |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우려면 2주차(답이 실제로 맞았는지 확인)로 진행합니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우면 3주차(다단계 질의)로 진행합니다.
농민 질문에 대한 에이전트 답변. 어떤 도구를 어떤 인자로 호출했는지(tool_calls), 답에 쓴 숫자가 어느 조회 결과에서 왔는지(citations), 확신도와 완곡 표현을 한 스키마에 담아, 지어낸 값 없이 근거로만 답했는지 객관 검증합니다.
{"type":"object","properties":{"question":{"type":"string"},"tool_calls":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string","enum":["get_market_price","get_weather","get_farm_journal"]},"args":{"type":"object"},"result_ref":{"type":["string","null"]},"status":{"type":"string","enum":["ok","empty","error"]}},"required":["tool","args","status"]},"minItems":1},"answer":{"type":"string","minLength":10},"citations":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"field":{"type":"string"},"value":{"type":["number","string","null"]}},"required":["source","field"]}},"confidence":{"type":"string","enum":["low","mid","high"]},"hedge":{"type":["string","null"]}},"required":["question","tool_calls","answer","citations","confidence"]}[
{
"input_ref": "농민 질문: ‘가락시장 배추 지금 팔면 되나요? 지난주보다 올랐어요?’",
"output": {
"question": "가락시장 배추 지금 팔면 되나요? 지난주보다 올랐어요?",
"tool_calls": [
{
"tool": "get_market_price",
"args": {
"crop": "배추",
"region": "가락시장",
"period": "2026-05-11..2026-05-15"
},
"result_ref": "mp_cabbage_0511_0515",
"status": "ok"
}
],
"answer": "가락시장 배추(상품)는 5월 11일 940원/kg 에서 15일 1,340원/kg 으로 4일간 약 43% 올랐습니다. 지난주보다 오른 흐름은 맞지만, 언제 파는 게 유리한지는 반입량 추세도 함께 봐야 합니다.",
"citations": [
{
"source": "market_prices",
"field": "price_krw_per_kg@2026-05-11",
"value": 940
},
{
"source": "market_prices",
"field": "price_krw_per_kg@2026-05-15",
"value": 1340
}
],
"confidence": "mid",
"hedge": "5일 표본이라 단기 흐름이며, 수급 급변 시 달라질 수 있어 시세 전망 단정은 어렵습니다."
}
},
{
"input_ref": "농민 질문: ‘내가 키우는 품목 중 지난주보다 오른 거 있어?’ (f_001, 다단계)",
"output": {
"question": "내가 키우는 품목 중 지난주보다 오른 거 있어?",
"tool_calls": [
{
"tool": "get_farm_journal",
"args": {
"farmer_id": "f_001"
},
"result_ref": "fj_f001",
"status": "ok"
},
{
"tool": "get_market_price",
"args": {
"crop_ids": [
"c_cabbage",
"c_radish"
],
"period": "2026-05-08..2026-05-15"
},
"result_ref": "mp_multi_f001",
"status": "ok"
}
],
"answer": "재배 중인 배추와 무 중, 배추는 지난주 대비 올랐고(940→1,340원/kg) 무는 오히려 내렸습니다(가락 기준 조회, 무는 대구북부 300원대까지 하락). 배추 쪽이 출하 타이밍을 볼 만합니다.",
"citations": [
{
"source": "farm_journal",
"field": "crop_id[f_001]",
"value": "c_cabbage,c_radish"
},
{
"source": "market_prices",
"field": "price_krw_per_kg[c_cabbage]",
"value": 1340
},
{
"source": "market_prices",
"field": "price_krw_per_kg[c_radish]",
"value": 300
}
],
"confidence": "mid",
"hedge": "무는 지역별 편차가 커 단일 지역 값이라, 실제 출하 지역 시세로 다시 확인이 필요합니다."
}
},
{
"input_ref": "농민 질문: ‘얼갈이 시세 알려줘’ (미등록 품목 → 조회 실패 정직 처리)",
"output": {
"question": "얼갈이 시세 알려줘",
"tool_calls": [
{
"tool": "get_market_price",
"args": {
"crop": "얼갈이",
"region": "가락시장",
"period": "recent"
},
"result_ref": null,
"status": "empty"
}
],
"answer": "얼갈이는 아직 표준 품목으로 등록되지 않아 시세를 정확히 물어오지 못했습니다. 최근 신규로 소량 거래된 기록만 있어 값을 단정하지 않겠습니다. 등록되면 바로 조회해 드립니다.",
"citations": [],
"confidence": "low",
"hedge": "미등록 신규 품목이라 조회 결과가 비어, 지어내지 않고 실패로 알립니다."
}
}
][자동 검증] 1. 출력이 스키마를 통과하는가(형식·필수 필드). 2. answer 에 등장한 숫자가 전부 citations 의 value 이고, 그 value 가 실제 도구 조회 결과(result_ref)에 존재하는가(지어낸 값 차단). 3. status 가 empty/error 인데 answer 가 값을 단정하면 실패로 검출. 4. tool_calls 의 도구·인자가 질문에 필요한 조회와 맞는가(다단계는 순서까지). [수동 검증] 1. 농업 상담 페르소나 검토자 2명이 답 근거의 타당성 라벨링 → bootstrap Cohen’s κ(두 사람 일치도) 하한 ≥ 0.6. 2. 인용 대조 judge 결과 5% 사람 점검.