<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Neha Saini - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Neha Saini - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/kr/search-labs/author/neha-saini</link>
    </image>
    <link>https://www.elastic.co/kr/search-labs/author/neha-saini</link>
    <atom:link href="https://www.elastic.co/kr/search-labs/rss/author/neha-saini.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[kr]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 19:53:53 GMT</lastBuildDate>
  <item>
    <title><![CDATA[​​LangGraph와 Elasticsearch를 사용하여 RAG 워크플로우 구축하기]]></title>
    <description><![CDATA[효율적인 데이터 검색과 AI 기반 응답을 위한 RAG 워크플로우를 구축하기 위해 Elasticsearch로 LangGraph 검색 에이전트 템플릿을 구성하고 사용자 정의하는 방법을 알아보세요.]]></description>
    <content:encoded><![CDATA[<p><a href="https://github.com/langchain-ai/retrieval-agent-template">LangGraph 검색 에이전트 템플릿은</a> LangGraph Studio에서 LangGraph를 사용하여 검색 기반 질문 답변 시스템을 쉽게 만들 수 있도록 LangChain에서 개발한 스타터 프로젝트입니다. 이 템플릿은 Elasticsearch와 원활하게 통합되도록 미리 구성되어 있어 개발자가 문서를 효율적으로 색인하고 검색할 수 있는 에이전트를 신속하게 구축할 수 있습니다.</p><p>이 블로그는 LangGraph Studio와 LangGraph CLI를 사용하여 LangChain 검색 에이전트 템플릿을 실행하고 커스터마이징하는 방법에 중점을 두고 있습니다. 이 템플릿은 Elasticsearch와 같은 다양한 검색 백엔드를 활용하여 검색 증강 생성(RAG) 애플리케이션을 구축하기 위한 프레임워크를 제공합니다.</p><p>에이전트 흐름을 사용자 정의하면서 Elastic으로 환경을 설정하고, 구성하고, 템플릿을 효율적으로 실행하는 방법을 안내해드립니다.</p><h2>필수 구성 요소</h2><p>계속 진행하기 전에 다음이 설치되어 있는지 확인하세요:</p><ul><li><p>Elasticsearch Cloud 배포 또는 온프레미스 Elasticsearch 배포(또는 Elastic Cloud에서 14일 <a href="https://www.elastic.co/kr/cloud/cloud-trial-overview">무료 체험판 </a>생성) - 버전 8.0.0 이상</p></li><li><p>Python 3.9+</p></li><li><p><a href="https://cohere.com/">Cohere</a> (이 가이드에서 사용됨), <a href="https://openai.com/">OpenAI</a> 또는 <a href="https://www.anthropic.com/claude">Anthropic/Claude와</a>같은 LLM 제공업체에 대한 액세스</p></li></ul><h2>LangGraph 앱 만들기</h2><h3>1. LangGraph CLI 설치</h3>pip install --upgrade "langgraph-cli[inmem]"<h3>2. 검색 에이전트 템플릿에서 LangGraph 앱 만들기</h3>mkdir lg-agent-demo
cd lg-agent-demo
langgraph new lg-agent-demo <p><em>사용 가능한 템플릿 목록에서 선택할 수 있는 대화형 메뉴가 표시됩니다. </em>아래와 같이 검색 에이전트에는 4개를, 파이썬에는 1개를 선택합니다:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd44177037ea46d45/6a17f86b3e9e45265fba1663/6a41a41f95c2477c67810adc7be46d91faf06878-1600x407.png" alt="대화형 검색 템플릿." /><ul><li><p><strong>문제 해결</strong>: 오류 발생 시: "urllib.error.URLError: &lt;urlopen 오류 [SSL: CERTIFICATE_VERIFY_FAILED] 인증서 확인 실패: 로컬 발급자 인증서(_ssl.c:1000)를 얻을 수 없음&gt; "</p></li></ul><p>아래와 같이 파이썬의 인증서 설치 명령을 실행하여 문제를 해결하세요.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbbe2d1d3a1af75b1/6a17f86d445de97c9c4d02e7/83ec238136c41738457299fd42c83aff32eb5b97-1407x75.png" alt="Python 인증서 설치 명령을 실행합니다." /><h3>3. 설치 종속성</h3><p>새 LangGraph 앱의 루트에서 가상 환경을 만들고 <code>edit</code> 모드에서 종속성을 설치하여 로컬 변경 사항이 서버에서 사용되도록 합니다:</p>#For Mac
python3 -m venv lg-demo
source lg-demo/bin/activate 
pip install -e .

#For Windows
python3 -m venv lg-demo
lg-demo\Scripts\activate 
pip install -e .<h2>환경 설정</h2><h3>1. .environment 만들기 파일</h3><p><code>.env</code> 파일에는 앱이 선택한 LLM 및 검색 제공업체에 연결할 수 있도록 API 키와 구성이 저장되어 있습니다. 예제 구성을 복제하여 새 <code>.env</code> 파일을 생성합니다:</p>cp .env.example .env<h3>2. .env 파일</h3><p><code>.env</code> 파일은 기본 구성 세트와 함께 제공됩니다. 설정에 따라 필요한 API 키와 값을 추가하여 업데이트할 수 있습니다. 사용 사례와 관련이 없는 키는 변경하지 않거나 제거할 수 있습니다.</p># To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent

# LLM choice (set the API key for your selected provider):
ANTHROPIC_API_KEY=your_anthropic_api_key
FIREWORKS_API_KEY=your_fireworks_api_key
OPENAI_API_KEY=your_openai_api_key

# Retrieval provider (configure based on your chosen service):

## Elastic Cloud:
ELASTICSEARCH_URL=https://your_elastic_cloud_url
ELASTICSEARCH_API_KEY=your_elastic_api_key

## Elastic Local:
ELASTICSEARCH_URL=http://host.docker.internal:9200
ELASTICSEARCH_USER=elastic
ELASTICSEARCH_PASSWORD=changeme

## Pinecone:
PINECONE_API_KEY=your_pinecone_api_key
PINECONE_INDEX_NAME=your_pinecone_index_name

## MongoDB Atlas:
MONGODB_URI=your_mongodb_connection_string

# Cohere API key:
COHERE_API_KEY=your_cohere_api_key<ul><li><p>예시 <code>.env</code> 파일(Elastic Cloud 및 Cohere 사용)</p></li></ul><p>아래는 이 블로그에서 설명한 대로 <strong>Elastic Cloud를</strong> 검색 공급자로, <strong>Cohere를</strong> LLM으로 사용하는 샘플 <code>.env</code> 구성입니다:</p># To separate your traces from other applications
LANGSMITH_PROJECT=retrieval-agent
#Retrieval Provider
# Elasticsearch configuration
ELASTICSEARCH_URL=elastic-url:443
ELASTICSEARCH_API_KEY=elastic_api_key
# Cohere API key
COHERE_API_KEY=cohere_api_key<p><em>참고: 이 가이드에서는 응답 생성과 임베딩 모두에 Cohere를 사용하지만 </em>, 사용 사례에 따라<em><strong>OpenAI</strong></em><em>, </em><em><strong>Claude</strong></em><em> 또는 로컬 LLM 모델과 </em>같은 다른 LLM 제공업체를 자유롭게 사용할 수 있습니다.  사용하려는 각 키가<em><code>.env</code></em>파일에 존재하고 올바르게 설정되어 있는지 확인하세요<em>.</em></p><h3>3. 구성 파일 -configuration.py 업데이트 </h3><p>적절한 API 키로 <code>.env</code> 파일을 설정한 후 다음 단계는 애플리케이션의 기본 모델 구성을 업데이트하는 것입니다. 구성을 업데이트하면 시스템에서 <code>.env</code> 파일에 지정한 서비스 및 모델을 사용하도록 합니다.</p><p>구성 파일로 이동합니다:</p> cd src/retrieval_graph<p><code>configuration.py</code> 파일에는 검색 에이전트가 세 가지 주요 작업에 사용하는 기본 모델 설정이 포함되어 있습니다:</p><ul><li><p><strong>임베딩 모델</strong> - 문서를 벡터 표현으로 변환합니다.</p></li><li><p><strong>쿼리 모델</strong> - 사용자의 쿼리를 벡터로 처리합니다.</p></li><li><p><strong>응답 모델</strong> - 최종 응답 생성</p></li></ul><p>기본적으로 이 코드는 <strong>OpenAI</strong> (예: <code>openai/text-embedding-3-small</code>) 및 <strong>Anthropic</strong> (예: <code>anthropic/claude-3-5-sonnet-20240620 and anthropic/claude-3-haiku-20240307</code>)의 모델을 사용합니다.

이 블로그에서는 Cohere 모델을 사용하도록 전환합니다. 이미 OpenAI 또는 Anthropic을 사용 중인 경우 변경할 필요가 없습니다.</p><h4>변경 예시(Cohere 사용):</h4><p><code>configuration.py</code> 을 열고 아래와 같이 모델 기본값을 수정합니다:</p>…
 embedding_model: Annotated[
       str,
       {"__template_metadata__": {"kind": "embeddings"}},
   ] = field(
       default="cohere/embed-english-v3.0",
…
response_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
       default="cohere/command-r-08-2024",
…
query_model: Annotated[str, {"__template_metadata__": {"kind": "llm"}}] = field(
       default="cohere/command-r-08-2024",
       metadata={<h2>LangGraph CLI로 검색 에이전트 실행하기</h2><h3>1. LangGraph 서버를 시작합니다.</h3>cd lg-agent-demo
langgraph dev<p>이렇게 하면 LangGraph API 서버가 로컬에서 시작됩니다. 성공적으로 실행되면 다음과 같은 내용이 표시됩니다:</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt46c7a703e715ef66/6a17f86eb1e113272d79f42e/e3c3344b24651067e2d0892d870feca505b3be35-1494x542.png" alt=" LangGraph API 서버가 성공적으로 실행 중입니다." /><p>Open Studio UI URL.</p><p>두 가지 그래프를 사용할 수 있습니다:</p><ul><li><p><strong>검색 그래프</strong>: Elasticsearch에서 데이터를 검색하고 LLM을 사용하여 쿼리에 응답합니다.</p></li><li><p><strong>인덱서 그래프</strong>: 문서를 Elasticsearch로 색인하고 LLM을 사용하여 임베딩을 생성합니다.</p></li></ul><h3>2. 인덱서 그래프 구성</h3><ul><li><p>인덱서 그래프를 엽니다.</p></li><li><p>어시스턴트 관리를 클릭합니다.</p><ul><li><p><strong>'새 어시스턴트 추가'</strong>를 클릭하고 지정된 대로 사용자 세부 정보를 입력한 다음 창을 닫습니다.</p></li></ul></li></ul>{"user_id": "101"}<h3>3. 샘플 문서 색인 생성</h3><ul><li><p>다음 샘플 문서는 가상의 분기별 보고서인 NoveTech 조직에 대한 색인입니다:</p></li></ul>[
  {    "page_content": "NoveTech Solutions Q1 2025 Report - Revenue: $120.5M, Net Profit: $18.2M, EPS: $2.15. Strong AI software launch and $50M government contract secured."
  },
  {
    "page_content": "NoveTech Solutions Business Highlights - AI-driven analytics software gained 15% market share. Expansion into Southeast Asia with two new offices. Cloud security contract secured."
  },
  {
    "page_content": "NoveTech Solutions Financial Overview - Operating expenses at $85.3M, Gross Margin 29.3%. Stock price rose from $72.5 to $78.3. Market Cap reached $5.2B."
  },
  {
    "page_content": "NoveTech Solutions Challenges - Rising supply chain costs impacting hardware production. Regulatory delays slowing European expansion. Competitive pressure in cybersecurity sector."
  },
  {
    "page_content": "NoveTech Solutions Future Outlook - Expected revenue for Q2 2025: $135M. New AI chatbot and blockchain security platform launch planned. Expansion into Latin America."
  },
  {
    "page_content": "NoveTech Solutions Market Performance - Year-over-Year growth at 12.7%. Stock price increase reflects investor confidence. Cybersecurity and AI sectors remain competitive."
  },
  {
    "page_content": "NoveTech Solutions Strategic Moves - Investing in R&amp;D to enhance AI-driven automation. Strengthening partnerships with enterprise cloud providers. Focusing on data privacy solutions."
  },
  {
    "page_content": "NoveTech Solutions CEO Statement - 'NoveTech Solutions continues to innovate in AI and cybersecurity. Our growth strategy remains strong, and we foresee steady expansion in the coming quarters.'"
  }
]<p>문서가 색인되면 아래와 같이 토론글에 삭제 메시지가 표시됩니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt38715eadffcb62f0/6a17f877faa9135f7393ca4c/fd3a1efd64cb54d54ea56ef5055249dd066d5708-1600x854.png" alt="LangGraph 및 Elasticsearch RAG 워크플로우 문서 색인." /><h3>4. 검색 그래프 실행</h3><ul><li><p>검색 그래프로 전환합니다.</p></li><li><p>다음 검색어를 입력합니다:</p></li></ul>What was NovaTech Solutions total revenue in Q1 2025?<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt5c0d070fca52e512/6a17f879505ac36d37ad8d12/eb4d8ddfe0effd7e1868fba921b8ef13f7baf27a-1600x755.png" alt="LangGraph 및 Elasticsearch 검색 그래프 실행하기" /><p>시스템은 관련 문서를 반환하고 색인된 데이터를 기반으로 정확한 답변을 제공합니다.</p><h2>검색 에이전트 사용자 지정</h2><p>사용자 경험을 개선하기 위해 검색 그래프에 사용자 지정 단계를 도입하여 사용자가 다음 세 가지 질문을 예측할 수 있도록 했습니다. 이 예측은 다음을 기반으로 합니다:</p><ul><li><p>검색된 문서의 컨텍스트</p></li><li><p>이전 사용자 상호 작용</p></li><li><p>마지막 사용자 쿼리</p></li></ul><p>쿼리 예측 기능을 구현하려면 다음과 같은 코드 변경이 필요합니다:</p><h3>1. 그래프.py 업데이트</h3><ul><li><p><code>predict_query</code> 기능을 추가합니다:</p></li></ul>async def predict_query(
   state: State, *, config: RunnableConfig
) -&gt; dict[str, list[BaseMessage]]:
   logger.info(f"predict_query predict_querypredict_query predict_query predict_query predict_query")  # Log the query

   configuration = Configuration.from_runnable_config(config)
   prompt = ChatPromptTemplate.from_messages(
       [
           ("system", configuration.predict_next_question_prompt),
           ("placeholder", "{messages}"),
       ]
   )
   model = load_chat_model(configuration.response_model)
   user_query = state.queries[-1] if state.queries else "No prior query available"
   logger.info(f"user_query: {user_query}")
   logger.info(f"statemessage: {state.messages}")
   #human_messages = [msg for msg in state.message if isinstance(msg, HumanMessage)]

   message_value = await prompt.ainvoke(
       {
           "messages": state.messages,
           "user_query": user_query,  # Use the most recent query as primary input
           "system_time": datetime.now(tz=timezone.utc).isoformat(),
       },
       config,
   )

   next_question = await model.ainvoke(message_value, config)
   return {"next_question": [next_question]}<ul><li><p><code>respond</code> 함수를 수정하여 메시지 대신 <strong><code>response</code></strong> 객체 를 반환하도록 합니다:</p></li></ul>async def respond(
   state: State, *, config: RunnableConfig
) -&gt; dict[str, list[BaseMessage]]:
   """Call the LLM powering our "agent"."""
   configuration = Configuration.from_runnable_config(config)
   # Feel free to customize the prompt, model, and other logic!
   prompt = ChatPromptTemplate.from_messages(
       [
           ("system", configuration.response_system_prompt),
           ("placeholder", "{messages}"),
       ]
   )
   model = load_chat_model(configuration.response_model)

   retrieved_docs = format_docs(state.retrieved_docs)
   message_value = await prompt.ainvoke(
       {
           "messages": state.messages,
           "retrieved_docs": retrieved_docs,
           "system_time": datetime.now(tz=timezone.utc).isoformat(),
       },
       config,
   )
   response = await model.ainvoke(message_value, config)
   # We return a list, because this will get added to the existing list
   return {"response": [response]}<ul><li><p>그래프 구조를 업데이트하여 predict_query에 대한 새 노드와 에지를 추가합니다:</p></li></ul>builder.add_node(generate_query)
builder.add_node(retrieve)
builder.add_node(respond)
builder.add_node(predict_query)
builder.add_edge("__start__", "generate_query")
builder.add_edge("generate_query", "retrieve")
builder.add_edge("retrieve", "respond")
builder.add_edge("respond", "predict_query")<h3>2. prompts.py 업데이트</h3><ul><li><p><code>prompts.py</code> 에서 게리 예측을 위한 프롬프트를 작성합니다:</p></li></ul>PREDICT_NEXT_QUESTION_PROMPT = """Given the user query and the retrieved documents, suggest the most likely next question the user might ask.

**Context:**
- Previous Queries:
{previous_queries}

- Latest User Query: {user_query}

- Retrieved Documents:
{retrieved_docs}

**Guidelines:**
1. Do not suggest a question that has already been asked in previous queries.
2. Consider the retrieved documents when predicting the next logical question.
3. If the user's query is already fully answered, suggest a relevant follow-up question.
4. Keep the suggested question natural and conversational.
5. Suggest at least 3 question

System time: {system_time}"""<h3>3. configuration.py 업데이트</h3><ul><li><p><code>predict_next_question_prompt</code> 을 추가합니다:</p></li></ul>predict_next_question_prompt: str = field(
       default=prompts.PREDICT_NEXT_QUESTION_PROMPT,
       metadata={"description": "The system prompt used for generating responses."},
   )<h3>4. state.py 업데이트</h3><ul><li><p>다음 속성을 추가합니다:</p></li></ul>response: Annotated[Sequence[AnyMessage], add_messages]
next_question : Annotated[Sequence[AnyMessage], add_messages]<h3>5. 검색 그래프 다시 실행</h3><ul><li><p>다음 검색어를 다시 입력합니다:</p></li></ul>What was NovaTech Solutions total revenue in Q1 2025?<p>시스템은 입력을 처리하고 아래와 같이 사용자가 질문할 수 있는 세 가지 관련 질문을 예측합니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd8d4de9396ca4853/6a17f87be31791dc742d59c7/70e855a2e4edc0ba5a147588df0de30eb081d053-1600x777.png" alt="LangGraph와 Elasticsearch를 사용하여 3개의 사용자 질문으로 검색 그래프 실행하기" /><h2>결론</h2><p>LangGraph Studio와 CLI에 검색 에이전트 템플릿을 통합하면 몇 가지 주요 이점이 있습니다:</p><ul><li><p><strong>개발 가속화</strong>: 템플릿 및 시각화 도구는 검색 워크플로우의 생성 및 디버깅을 간소화하여 개발 시간을 단축합니다.</p></li><li><p><strong>원활한 배포</strong>: API 및 자동 확장에 대한 기본 지원으로 여러 환경에 걸쳐 원활한 배포를 보장합니다.</p></li><li><p><strong>간편한 업데이트:</strong> 워크플로우 수정, 새로운 기능 추가, 추가 노드 통합이 간단해 검색 프로세스를 쉽게 확장하고 개선할 수 있습니다.</p></li><li><p><strong>영구 메모리</strong>: 시스템이 상담원 상태와 지식을 유지하여 일관성과 안정성을 향상시킵니다.</p></li><li><p><strong>유연한 워크플로 모델링</strong>: 개발자는 특정 사용 사례에 맞게 검색 로직과 커뮤니케이션 규칙을 사용자 지정할 수 있습니다.</p></li><li><p><strong>실시간 상호작용 및 디버깅</strong>: 실행 중인 에이전트와 상호 작용하는 기능으로 효율적인 테스트 및 문제 해결이 가능합니다.</p></li></ul><p>이러한 기능을 활용하여 조직은 데이터 접근성과 사용자 경험을 향상시키는 강력하고 효율적이며 확장 가능한 검색 시스템을 구축할 수 있습니다.</p><p>이 프로젝트의 전체 소스 코드는 <a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/langraph-retrieval-agent-template-demo">GitHub에서</a> 확인할 수 있습니다.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/build-rag-workflow-langgraph-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/build-rag-workflow-langgraph-elasticsearch</guid>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Neha Saini]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt0c9f03d2c1a9cb4c/6a17f87d0b0bed3781dd377c/17b7e7b336f73e232375d1add582ae5f6c52a279-1440x840.png" length="0" type="image/png"/>
    <pubDate>Fri, 25 Apr 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>