글

6월, 2026의 게시물 표시

AI 응답을 JSON으로 안전하게 받기 — Output Parser 실전

AI가 만든 답을 화면에 그냥 보여주기만 할 거면 문제가 없습니다. 그런데 그 답을 데이터베이스에 저장하거나 다른 시스템에 넘기려면 이야기가 달라집니다. 자유롭게 쓴 문장은 프로그램이 다루기 나쁘거든요. 이걸 해결하는 게 Output Parser입니다. 신입들이 꼭 한 번 겪는 실수 제가 팀에서 자주 보는 장면이 있습니다. 프롬프트에 "JSON으로 답해"라고만 적고 json.loads() 로 바로 파싱하는 거예요. 데모에선 잘 됩니다. 그러다 어느 순간 모델이 ```json 코드블록으로 감싸거나 "네, 결과입니다:"를 앞에 붙이면서 파싱이 깨집니다. Output Parser는 이 "형식이 들쭉날쭉한 문제"를 표준화해 줍니다. JsonOutputParser 기본 사용 from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import JsonOutputParser from langchain_openai import ChatOpenAI parser = JsonOutputParser() prompt = ChatPromptTemplate.from_template( "다음 상품평에서 감정과 별점을 뽑아줘.\n{format}\n상품평: {review}" ).partial(format=parser.get_format_instructions()) chain = prompt | ChatOpenAI(model="gpt-4o-mini") | parser print(chain.invoke({"review": "배송은 느렸지만 품질은 만족해요"})) # {'sentiment': '긍정', 'rating': 4} 같은 dict로 바로 나옴 핵심은 get_format_instructions()...

프롬프트를 코드에서 분리한 이유 — Prompt Template 실전

프롬프트를 코드 안에 문자열로 박아두면 처음엔 편합니다. 그런데 서비스가 커지면서 저는 프롬프트를 코드에서 아예 분리 하는 쪽으로 방식을 바꿨습니다. 그 계기와, LangChain의 Prompt Template을 실제로 어떻게 쓰는지 정리해 봅니다. 템플릿이 필요해진 순간 같은 형식의 질문을 반복할 때가 문제였습니다. "상품명만 바뀌고 나머지 지시는 똑같은" 프롬프트가 수십 개 생기니, 문구 하나 고치려면 전부 찾아 고쳐야 했어요. Prompt Template은 이 틀을 한 번만 정의하고 값만 바꿔 끼우는 방식입니다. from langchain_core.prompts import PromptTemplate tpl = PromptTemplate.from_template( "너는 쇼핑 카피라이터야.\n상품: {product}\n특징: {feature}\n위 정보로 30자 내 카피를 써줘." ) print(tpl.format(product="가습기", feature="저소음")) 예시를 넣으면 품질이 확 오른다 (Few-shot) 제가 체감한 가장 큰 차이는 예시를 몇 개 넣어주는 것 이었습니다. "이런 식으로 써줘" 하고 샘플을 보여주면 결과 톤이 눈에 띄게 안정됩니다. LangChain에는 이걸 위한 FewShotPromptTemplate 이 있어요. from langchain_core.prompts import FewShotPromptTemplate, PromptTemplate example_tpl = PromptTemplate.from_template("상품: {p}\n카피: {c}") examples = [ {"p": "텀블러", "c": "하루 종일 따뜻하게, 손안의 온기"}, {"p": "우산", ...

컨베이어 벨트로 이해하는 LangChain의 Chain

AI 개발을 배울 때 "Chain"이라는 단어에서 한 번쯤 멈칫하게 됩니다. 저는 이 개념을 후배에게 설명할 때 공장 컨베이어 벨트 에 비유하는데, 그게 가장 빨리 통하더라고요. 오늘은 그 비유로 Chain을 풀어보고, 실제로 어떻게 코드가 되는지까지 짚어보겠습니다. 컨베이어 벨트로 이해하는 Chain 공장 라인을 떠올려 보세요. 원재료가 들어오면 → 1번 기계가 다듬고 → 2번 기계가 조립하고 → 3번 기계가 포장합니다. 각 기계는 앞 기계의 결과물을 받아 자기 일만 하고 다음으로 넘깁니다. LangChain의 Chain이 정확히 이 구조예요. 사용자 입력이 프롬프트 생성 → LLM 호출 → 결과 가공 순서로 흘러가죠. "여러 단계를 한 줄로 연결한 흐름"이라는 정의가 이래서 나옵니다. 가장 단순한 연결 from langchain_core.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI prompt = ChatPromptTemplate.from_template("{keyword} 를 한 문장 광고 카피로 만들어줘") model = ChatOpenAI(model="gpt-4o-mini") chain = prompt | model # 프롬프트 → 모델을 벨트로 연결 print(chain.invoke({"keyword": "무선 이어폰"}).content) | 기호가 컨베이어 벨트라고 보면 됩니다. 왼쪽 결과가 오른쪽 입력으로 자동으로 넘어가죠. 한 단계 더 — 동시에 처리하기 제품 페이지를 만들 때 저는 "카피"와 "해시태그"를 한 번에 뽑고 싶었습니다. 이럴 땐 벨트를 나란히 두 개 놓는 RunnableParallel 이 편합니다. from langchain_core.runnables import...

택배 물류센터로 이해하는 LangChain 실행 흐름

LangChain으로 챗봇을 만들면, 사용자의 질문 한 줄이 답변이 되어 나오기까지 안에서 꽤 여러 단계가 돌아갑니다. 저는 이 흐름을 택배 물류센터 에 비유해 설명하곤 합니다. 물류센터로 보는 실행 흐름 택배가 오면 → 분류 → 상차 → 배송 순서를 밟죠. LangChain도 비슷합니다. 질문이 들어오면 (1) 프롬프트로 포장하고 (2) LLM에 보내고 (3) 결과를 받아 (4) 필요하면 가공해서 내보냅니다. 각 단계가 컨베이어처럼 이어져 있어요. 질문 → [프롬프트 생성] → [LLM 호출] → [출력 파싱] → 답변 검색이 붙으면 (RAG) 사내 문서 기반 답변이 필요하면 중간에 "창고에서 물건 찾기" 단계가 추가됩니다. 질문으로 관련 문서를 먼저 검색하고, 그 문서를 프롬프트에 끼워 LLM에 넘기죠. 질문 → [문서 검색] → [문서+질문으로 프롬프트] → [LLM] → 답변 제가 처음 RAG를 디버깅할 때 답이 이상해서 한참 헤맸는데, 원인은 LLM이 아니라 "검색 단계에서 엉뚱한 문서를 물어온 것"이었어요. 흐름을 단계로 나눠 보면 어디서 틀어졌는지 추적이 쉬워집니다. 실무 팁: 중간 결과를 찍어봐라 흐름이 길어질수록 저는 각 단계의 출력을 로그로 남깁니다. "프롬프트에 뭐가 들어갔는지"만 찍어봐도 문제의 8할은 잡혀요. 블랙박스처럼 전체를 한 번에 보지 말고, 컨베이어 칸마다 열어보는 습관이 중요합니다. 마무리 실행 흐름을 "단계의 연결"로 이해하면 디버깅도, 기능 추가도 쉬워집니다. 다음 글에서는 이 흐름을 더 간결하게 쓰게 해주는 LCEL 문법을 다뤄보겠습니다.

15. Gradio 챗봇 만들기 (파이썬으로 AI 챗봇을 가장 쉽게 구현하는 방법)

이미지
15. Gradio 챗봇 만들기 (파이썬으로 AI 챗봇을 가장 쉽게 구현하는 방법) AI 서비스를 개발할 때 가장 먼저 만들어보는 프로젝트 중 하나가 바로 챗봇입니다. 하지만 웹 프론트엔드 개발 경험이 없다면 챗봇 화면을 만드는 것부터 어려움을 느끼는 경우가 많습니다. 이때 가장 많이 사용하는 도구가 바로 Gradio 입니다. Gradio는 복잡한 웹 개발 없이 파이썬 코드만으로 AI 서비스를 웹 화면에 배포할 수 있는 오픈소스 프레임워크입니다. 이번 글에서는 Gradio가 무엇인지, 왜 많은 AI 개발자들이 사용하는지, 그리고 챗봇 개발에 어떤 장점이 있는지 알아보겠습니다. Gradio란 무엇인가? Gradio는 머신러닝 모델과 AI 서비스를 웹 인터페이스 형태로 쉽게 배포할 수 있도록 만들어진 오픈소스 라이브러리입니다. 복잡한 HTML, CSS, JavaScript를 작성하지 않아도 몇 줄의 파이썬 코드만으로 웹 서비스를 만들 수 있습니다. 특히 AI 모델 테스트와 데모 제작에 매우 많이 활용되고 있습니다. 왜 Gradio를 사용할까? AI 모델을 개발한 후 실제로 테스트하려면 사용자 인터페이스가 필요합니다. 일반적인 웹 개발 방식은 시간이 많이 소요됩니다. 반면 Gradio는 빠르게 결과를 확인할 수 있습니다. 빠른 개발 가능 프론트엔드 지식 최소화 AI 모델 즉시 테스트 쉬운 배포 이러한 장점 때문에 AI 개발 입문자들에게 매우 인기가 높습니다. Gradio 챗봇 기본 구조 Gradio 챗봇은 매우 단순한 구조로 동작합니다. 사용자 입력 ↓ Python 함수 ↓ LLM 호출 ↓ 응답 반환 ↓ 웹 화면 출력 이 구조만 이해해도 기본 챗봇을 구현할 수 있습니다. Gradio와 LangChain의 조합 최근에는 LangChain과 Gradio를 함께 사용하는 경우가 많습니다. LangChain은 AI 로직을 담당하고, Gradio는 사용자 인...

14. LangChain으로 AI 챗봇 만들기 (초보자도 이해하는 챗봇 개발 구조)

이미지
14. LangChain으로 AI 챗봇 만들기 (초보자도 이해하는 챗봇 개발 구조) AI 기술이 발전하면서 가장 많이 만들어지는 서비스 중 하나가 바로 AI 챗봇입니다. 과거에는 챗봇을 개발하려면 복잡한 자연어 처리 기술이 필요했지만, 최근에는 LangChain을 활용하면 훨씬 쉽게 AI 챗봇을 구축할 수 있습니다. 특히 ChatGPT와 같은 대형 언어 모델을 활용하는 경우 LangChain은 챗봇 개발의 핵심 프레임워크로 자리 잡고 있습니다. 이번 글에서는 LangChain을 활용한 AI 챗봇의 구조와 동작 원리를 쉽게 설명해보겠습니다. AI 챗봇이란 무엇인가? AI 챗봇은 사용자의 질문을 이해하고 자연스럽게 답변하는 시스템입니다. 최근에는 단순한 FAQ 수준을 넘어 문서 검색, 업무 자동화, 고객 지원까지 다양한 역할을 수행하고 있습니다. 대표적인 예로 ChatGPT, Claude, Gemini 기반 챗봇이 있습니다. 왜 LangChain을 사용할까? 단순히 OpenAI API만 호출해도 챗봇을 만들 수 있습니다. 하지만 실제 서비스에서는 다양한 기능이 필요합니다. 대화 기억 문서 검색 외부 API 호출 사용자 정보 관리 답변 형식 제어 LangChain은 이러한 기능을 쉽게 연결할 수 있도록 도와줍니다. LangChain 챗봇 기본 구조 사용자 질문 ↓ Prompt 생성 ↓ LLM 호출 ↓ 응답 생성 ↓ 사용자 출력 가장 기본적인 챗봇 구조는 위와 같습니다. 하지만 실제 서비스는 훨씬 복잡한 구조를 사용합니다. 대화 기억(Memory) 기능 챗봇에서 가장 중요한 기능 중 하나는 Memory입니다. 일반적인 AI 모델은 이전 대화를 기억하지 못합니다. 하지만 LangChain Memory를 사용하면 이전 대화 내용을 저장하고 활용할 수 있습니다. 예를 들어 사용자가 자신의 이름을 알려주면 다음 질문에서도 그 이름을 활용할 수 있습니다. ...

LCEL이 편한 진짜 이유 (예전 방식과 비교)

LangChain을 조금 쓰다 보면 | 기호로 연결하는 문법을 자주 만납니다. 이게 LCEL(LangChain Expression Language)인데, 저는 처음엔 "굳이 왜 이런 문법을?" 싶었어요. 그런데 예전 방식과 비교해 보니 이유가 바로 이해됐습니다. 예전 방식 vs LCEL 예전엔 객체를 만들고 함수로 이어 붙였습니다. 단계가 늘면 코드가 장황해졌죠. # 예전 느낌 (개념) result1 = prompt.format(...) result2 = llm.invoke(result1) result3 = parser.parse(result2) LCEL은 이걸 한 줄로 파이프처럼 잇습니다. chain = prompt | llm | parser result = chain.invoke({"q": "벡터 DB"}) | 는 리눅스 파이프와 같은 발상이에요. 왼쪽 출력이 오른쪽 입력으로 자동으로 흘러갑니다. 읽는 순서와 실행 순서가 일치해서 눈에 잘 들어와요. 제가 체감한 진짜 장점 단순히 짧아서가 아니라, 스트리밍·비동기·배치가 공짜로 딸려온다 는 점이 컸습니다. 같은 체인에서 chain.stream(...) 으로 바꾸면 토큰이 실시간으로 흘러나오고, chain.batch([...]) 로 여러 입력을 한 번에 처리할 수 있어요. 예전 방식이라면 이걸 다 직접 짰어야 했죠. for tok in chain.stream({"q": "임베딩"}): print(tok, end="", flush=True) # 실시간 출력 주의: 타입 맞추기 파이프로 이을 때 앞 단계 출력과 뒤 단계 입력 타입이 안 맞으면 조용히 이상하게 동작합니다. 저는 중간에 StrOutputParser() 를 끼워 문자열로 정리하는 걸 습관으로 뒀더니 헷갈림이 줄었어요. 마무리 LCEL은 "체인을 파이프 한 줄로, 그러면서 스트리밍·배치까지" 얻...

12. LangChain 핵심 구조 이해하기 (Model, Prompt, Chain, Memory, Tool 완벽 정리)

이미지
12. LangChain 핵심 구조 이해하기 (Model, Prompt, Chain, Memory, Tool 완벽 정리) LangChain을 처음 공부하면 다양한 용어가 등장합니다. Model, Prompt, Chain, Memory, Tool 등 여러 개념이 동시에 나오기 때문에 처음에는 구조를 이해하기 어렵게 느껴질 수 있습니다. 하지만 실제로는 각 구성 요소가 명확한 역할을 가지고 있으며, 이 구조를 이해하면 LangChain 활용 능력이 크게 향상됩니다. 이번 글에서는 LangChain의 핵심 구조를 구성하는 주요 요소들을 쉽게 설명해보겠습니다. 왜 LangChain 구조를 이해해야 할까? 많은 사람들이 LangChain을 단순히 AI를 호출하는 라이브러리라고 생각합니다. 하지만 LangChain의 진짜 가치는 여러 기능을 조합하여 하나의 AI 애플리케이션을 만드는 데 있습니다. 구조를 이해하면 RAG 시스템, AI Agent, 업무 자동화 시스템을 훨씬 쉽게 설계할 수 있습니다. LangChain 전체 구조 사용자 입력 ↓ Prompt ↓ Model ↓ Chain ↓ Tool ↓ Memory ↓ 최종 응답 실제 프로젝트에서는 위 요소들이 서로 연결되어 동작합니다. Model이란 무엇인가? Model은 실제 AI 모델을 의미합니다. 사용자의 질문을 처리하고 답변을 생성하는 역할을 담당합니다. 대표적으로 다음과 같은 모델을 연결할 수 있습니다. GPT Claude Gemini Llama Qwen LangChain은 특정 모델에 종속되지 않고 여러 AI 모델을 쉽게 교체할 수 있다는 장점이 있습니다. Prompt란 무엇인가? Prompt는 AI에게 전달하는 명령어입니다. 사용자가 입력한 내용을 그대로 전달하는 것이 아니라 원하는 형식으로 가공하여 AI에게 전달합니다. 예를 들어 다음과 같은 Prompt를 만들 수 있습니다. 당신은 AI 전...

레고 블록으로 이해하는 LangChain — 왜 프레임워크를 쓸까

AI 서비스를 처음 만들 때 저는 필요한 기능을 전부 직접 코딩했습니다. 그러다 프로젝트가 커지면서 "이걸 왜 매번 새로 짜지?" 하는 순간이 왔고, 그때 LangChain을 진지하게 보게 됐습니다. 오늘은 LangChain을 레고 블록 에 비유해 풀어보겠습니다. 레고 블록으로 이해하기 레고의 장점은 블록마다 규격(돌기 크기)이 같아서 아무거나 끼워도 맞는다는 점이죠. LangChain이 하는 일이 딱 이거예요. 모델(LLM), 프롬프트, 문서 검색기, 메모리 같은 부품을 같은 규격으로 표준화 해 둬서, 원하는 대로 끼우고 바꿀 수 있게 해줍니다. OpenAI를 쓰다 다른 모델로 바꿔도 블록 하나만 교체하면 되는 식이죠. 직접 짜면 뭐가 힘든가 순수 코드로 챗봇에 "문서 검색 + 대화 기억 + 외부 API 호출"을 다 넣으면, 각 기능이 서로 얽혀서 하나를 고칠 때 다른 게 깨집니다. 저는 임베딩 모델 하나 바꾸려다 코드 절반을 다시 짠 적이 있어요. LangChain은 이 부품들을 느슨하게 연결해, 교체 비용을 크게 줄여줍니다. from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate prompt = ChatPromptTemplate.from_template("{q}에 대해 3줄로 설명해줘") llm = ChatOpenAI(model="gpt-4o-mini") chain = prompt | llm # 블록 두 개를 끼운 셈 print(chain.invoke({"q": "LangChain"}).content) 제 기준: 언제 도입하나 솔직히 LLM을 한 번 부르는 수준이면 LangChain은 과합니다. 저는 "검색·기억·도구 중 두 개 이상이 엮인다" 싶을 때부터 도입해요. 그 전엔 순정 SDK...