<?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[Srikanth Manvi - 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[Srikanth Manvi - 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/srikanth-manvi</link>
    </image>
    <link>https://www.elastic.co/kr/search-labs/author/srikanth-manvi</link>
    <atom:link href="https://www.elastic.co/kr/search-labs/rss/author/srikanth-manvi.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[kr]]></language>
    <lastBuildDate>Mon, 28 Sep 2026 19:00:04 GMT</lastBuildDate>
  <item>
    <title><![CDATA[AI 에이전트 개발을 위해 Microsoft 시맨틱 커널용 Elasticsearch 벡터 스토어 커넥터를 사용하는 방법]]></title>
    <description><![CDATA[Microsoft 시맨틱 커널은 가벼운 오픈 소스 개발 키트로, AI 에이전트를 쉽게 빌드하고 최신 AI 모델을 C#, Python 또는 Java 코드베이스에 통합할 수 있습니다. Semantic Kernel Elasticsearch 벡터 스토어 커넥터가 출시됨에 따라, 이제 AI 에이전트 구축에 Semantic Kernel을 사용하는 개발자는 확장 가능한 엔터프라이즈급 벡터 스토어로 Elasticsearch를 플러그인하면서 Semantic Kernel 추상화를 계속 사용할 수 있습니다.]]></description>
    <content:encoded><![CDATA[<p><a href="https://learn.microsoft.com/en-us/semantic-kernel/overview/">Microsoft Semantic Kernel</a> 팀과 협력하여,<a href="https://learn.microsoft.com/en-us/semantic-kernel/overview/">Microsoft Semantic Kernel</a> (.NET) 사용자를 위한 <a href="https://github.com/elastic/semantic-kernel-net/">Semantic Kernel Elasticsearch 벡터 스토어 커넥터의 출시를 발표합니다.</a> 시맨틱 커널은 벡터 스토어의 보다 관련성 높은 데이터 기반 응답으로 대규모 언어 모델(LLM)을 개선하는 기능을 포함하여 엔터프라이즈급 AI 에이전트 구축을 간소화합니다. Semantic Kernel은 Elasticsearch와 같은 벡터 저장소와 상호 작용하기 위한 원활한 추상화 계층을 제공하여 레코드 컬렉션 생성, 나열, 삭제, 개별 레코드 업로드, 검색, 삭제와 같은 필수 기능을 제공합니다.</p><p><a href="https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/out-of-the-box-connectors/elasticsearch-connector?pivots=programming-language-csharp">즉시 사용 가능한 Semantic Kernel Elasticsearch 벡터 저장소 커넥터는</a> 개발자가 AI 에이전트를 구축하는 동안 매우 쉽게 Elasticsearch를 벡터 저장소로 플러그인할 수 있도록 Semantic Kernel <a href="https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/?pivots=programming-language-csharp#the-vector-store-abstraction">벡터 저장소 추상화를</a> 지원합니다.</p><p>Elasticsearch는 오픈 소스 커뮤니티에서 강력한 기반을 가지고 있으며 최근 <a href="https://www.elastic.co/blog/elasticsearch-is-open-source-again">AGPL 라이선스를</a> 채택했습니다. 이러한 도구는 오픈 소스 Microsoft 시맨틱 커널과 결합하여 강력하고 엔터프라이즈급 솔루션을 제공합니다. 다음 명령 <code>curl -fsSL https://elastic.co/start-local | sh </code>(자세한 내용은 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/run-elasticsearch-locally.html">start-local</a> 참조)을 실행하여 몇 분 안에 Elasticsearch를 시작하여 로컬에서 시작할 수 있으며, AI 에이전트를 프로덕션하는 동안 <a href="https://cloud.elastic.co/registration?onboarding_token=vectorsearch&amp;utm_source=semantickernel&amp;utm_content=documentation">클라우드 호스팅</a> 또는 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.16/install-elasticsearch.html">자체 호스팅</a> 버전으로 이동할 수 있습니다.</p><p>이 블로그에서는 시맨틱 커널을 사용할 때 시맨틱 커널 <a href="https://github.com/elastic/semantic-kernel-net/">Elasticsearch 벡터 저장소 커넥터를</a> 사용하는 방법을 살펴봅니다. 향후 파이썬 버전의 커넥터가 제공될 예정입니다.</p><h2>높은 수준의 시나리오: 시맨틱 커널로 RAG 앱 구축하기 &amp; Elasticsearch</h2><p>다음 섹션에서는 예시를 살펴보겠습니다. 저희는 사용자의 질문을 입력으로 받아 답변을 반환하는 RAG(검색 증강 생성) 애플리케이션을 구축하고 있습니다. LLM으로 Azure OpenAI<a href="https://devblogs.microsoft.com/semantic-kernel/introducing-new-ollama-connector-for-local-models/">(로컬 LLM도</a> 사용 가능)를 사용하고, 벡터 저장소로 Elasticsearch를, 모든 구성 요소를 하나로 묶는 프레임워크로 Semantic Kernel(.net)을 사용할 것입니다.</p><p>RAG 아키텍처에 익숙하지 않다면 이 문서 <a href="https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag">(https://www.elastic.co/search-labs/blog/retrieval-augmented-generation-rag)</a>를 통해 간단히 소개할 수 있습니다.</p><p>답변은 질문과 관련된 컨텍스트가 제공된 LLM에 의해 생성되며, 이는 Elasticsearch 벡터스토어에서 검색됩니다. 응답에는 LLM에서 컨텍스트로 사용한 소스도 포함됩니다.</p><h3>RAG 예제</h3><p>이 구체적인 예에서는 사용자가 내부 호텔 데이터베이스에 저장된 호텔에 대해 질문할 수 있는 애플리케이션을 구축합니다. 사용자는 예를 들어 다양한 기준에 따라 특정 호텔을 검색하거나 호텔 목록을 요청할 수 있습니다.</p><p>예제 데이터베이스의 경우, 100개의 항목이 포함된 <a href="https://github.com/elastic/semantic-kernel-net/blob/main/Elastic.SemanticKernel.Playground/hotels.csv">호텔 목록을</a> 생성했습니다. 커넥터 데모를 최대한 쉽게 사용해 볼 수 있도록 샘플 크기는 의도적으로 작게 만들었습니다. 실제 애플리케이션에서 Elasticsearch 커넥터는 특히 매우 많은 양의 데이터로 작업할 때 'InMemory' 벡터 저장소 구현과 같은 다른 옵션에 비해 그 장점을 보여줄 것입니다.</p><p>전체 데모 애플리케이션은 Elasticsearch 벡터 스토어 커넥터 <a href="https://github.com/elastic/semantic-kernel-net/tree/main/Elastic.SemanticKernel.Playground">리포지토리에서</a> 확인할 수 있습니다.</p><p>필요한 NuGet 패키지를 추가하고 프로젝트에 지시문을 사용하는 것부터 시작하겠습니다:</p>dotnet add package "Elastic.Clients.Elasticsearch" -v 8.16.2
dotnet add package "Elastic.SemanticKernel.Connectors.Elasticsearch" -v 0.1.2
dotnet add package "Microsoft.Extensions.Hosting" -v 9.0.0
dotnet add package "Microsoft.SemanticKernel.Connectors.AzureOpenAI" -v 1.30.0
dotnet add package "Microsoft.SemanticKernel.PromptTemplates.Handlebars" -v 1.30.0using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

using Elastic.Clients.Elasticsearch;
using Elastic.Transport;

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel;
using Microsoft.SemanticKernel.Data;
using Microsoft.SemanticKernel.Embeddings;
using Microsoft.SemanticKernel.PromptTemplates.Handlebars;<p>이제 데이터 모델을 생성하고 시맨틱 커널 특정 속성을 제공하여 저장소 모델 스키마를 정의하고 텍스트 검색을 위한 몇 가지 힌트를 제공할 수 있습니다:</p>/// &lt;summary&gt;
/// Data model for storing a "hotel" with a name, a description, a  description embedding and an optional reference link.
/// &lt;/summary&gt;
public sealed record Hotel
{
	[VectorStoreRecordKey]
	public required string HotelId { get; set; }

	[TextSearchResultName]
	[VectorStoreRecordData(IsFilterable = true)]
	public required string HotelName { get; set; }

	[TextSearchResultValue]
	[VectorStoreRecordData(IsFullTextSearchable = true)]
	public required string Description { get; set; }

	[VectorStoreRecordVector(Dimensions: 1536, DistanceFunction.CosineSimilarity, IndexKind.Hnsw)]
	public ReadOnlyMemory&lt;float&gt;? DescriptionEmbedding { get; set; }

	[TextSearchResultLink]
	[VectorStoreRecordData]
	public string? ReferenceLink { get; set; }
}<p>저장 모델 스키마 속성(`VectorStore*`)은 Elasticsearch 벡터 스토어 커넥터의 실제 사용과 가장 관련이 있습니다:</p><p></p><ul><li><p><code>VectorStoreRecordKey</code> 를 사용하여 레코드 클래스의 속성을 벡터 저장소에 레코드가 저장되는 키로 표시할 수 있습니다.</p></li><li><p><code>VectorStoreRecordData</code> 를 사용하여 레코드 클래스의 프로퍼티를 '데이터'로 표시할 수 있습니다.</p></li><li><p><code>VectorStoreRecordVector</code> 를 사용하여 레코드 클래스의 속성을 벡터로 표시할 수 있습니다.</p></li></ul><p>이러한 모든 속성은 스토리지 모델을 추가로 사용자 지정하는 데 사용할 수 있는 다양한 선택적 매개변수를 허용합니다. 예를 들어 <code>VectorStoreRecordKey </code> 의 경우 다른 거리 함수 또는 다른 인덱스 유형을 지정할 수 있습니다.</p><p>이 예제의 마지막 단계에서는 텍스트 검색 속성(<code>TextSearch*</code>)이 중요합니다. 나중에 다시 설명하겠습니다.</p><p>다음 단계에서는 시맨틱 커널 엔진을 초기화하고 핵심 서비스에 대한 참조를 얻습니다. 실제 애플리케이션에서는 서비스 컬렉션에 직접 액세스하는 대신 종속성 <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection">주입을</a> 사용해야 합니다. 하드코딩된 구성 및 비밀도 마찬가지이며, 대신 <a href="https://learn.microsoft.com/en-us/dotnet/core/extensions/configuration">구성 공급자를</a> 사용하여 읽어야 합니다:</p>var builder = Host.CreateApplicationBuilder(args);

// Register AI services.
var kernelBuilder = builder.Services.AddKernel();

kernelBuilder.AddAzureOpenAIChatCompletion("gpt-4o", "https://my-service.openai.azure.com", "my_token");

kernelBuilder.AddAzureOpenAITextEmbeddingGeneration("ada-002", "https://my-service.openai.azure.com", "my_token");

// Register text search service.
kernelBuilder.AddVectorStoreTextSearch&lt;Hotel&gt;();

// Register Elasticsearch vector store.
var elasticsearchClientSettings = new ElasticsearchClientSettings(new Uri("https://my-elasticsearch-instance.cloud"))
    .Authentication(new BasicAuthentication("elastic", "my_password"));

kernelBuilder.AddElasticsearchVectorStoreRecordCollection&lt;string, Hotel&gt;("skhotels", elasticsearchClientSettings);

// Build the host.
using var host = builder.Build();

// For demo purposes, we access the services directly without using a DI context.

var kernel = host.Services.GetService&lt;Kernel&gt;()!;
var embeddings = host.Services.GetService&lt;ITextEmbeddingGenerationService&gt;()!;
var vectorStoreCollection = host.Services.GetService&lt;IVectorStoreRecordCollection&lt;string, Hotel&gt;&gt;()!;

// Register search plugin.
var textSearch = host.Services.GetService&lt;VectorStoreTextSearch&lt;Hotel&gt;&gt;()!;
kernel.Plugins.Add(textSearch.CreateWithGetTextSearchResults("SearchPlugin"));<p>이제 <code>vectorStoreCollection</code> 서비스를 사용하여 컬렉션을 생성하고 몇 가지 <a href="https://github.com/elastic/semantic-kernel-net/blob/main/Elastic.SemanticKernel.Playground/hotels.csv">데모 레코드를</a> 수집할 수 있습니다:</p>await vectorStoreCollection.CreateCollectionIfNotExistsAsync();

// CSV format: ID;Hotel Name;Description;Reference Link
var hotels = (await File.ReadAllLinesAsync("hotels.csv"))
    .Select(x =&gt; x.Split(';'));

foreach (var chunk in hotels.Chunk(25))
{
    var descriptionEmbeddings = await embeddings.GenerateEmbeddingsAsync(chunk.Select(x =&gt; x[2]).ToArray());
    
    for (var i = 0; i &lt; chunk.Length; ++i)
    {
        var hotel = chunk[i];
        await vectorStoreCollection.UpsertAsync(new Hotel
        {
            HotelId = hotel[0],
            HotelName = hotel[1],
            Description = hotel[2],
            DescriptionEmbedding = descriptionEmbeddings[i],
            ReferenceLink = hotel[3]
        });
    }
}<p>이는 시맨틱 커널이 어떻게 복잡한 벡터 저장소 사용을 몇 가지 간단한 메서드 호출로 줄이는지 보여줍니다.</p><p>내부적으로는 Elasticsearch에서 새 인덱스가 생성되고 필요한 모든 속성 매핑이 만들어집니다. 그런 다음 데이터 세트가 완전히 투명하게 스토리지 모델에 매핑되고 최종적으로 인덱스에 저장됩니다. 아래는 Elasticsearch에서 매핑이 어떻게 표시되는지 보여줍니다.</p>{
  "mappings": {
    "properties": {
      "descriptionEmbedding": {
        "dims": 1536,
        "index": true,
        "index_options": {
          "type": "hnsw"
        },
        "similarity": "cosine",
        "type": "dense_vector"
      },
      "hotelName": {
        "type": "keyword"
      },
      "description": {
        "type": "text"
      }
    }
  }
}<p><code>embeddings.GenerateEmbeddingsAsync()</code> 호출은 구성된 Azure AI 임베딩 생성 서비스를 투명하게 호출합니다.</p><p>이 데모의 마지막 단계에서는 더 많은 마법을 볼 수 있습니다.</p><p>사용자가 데이터에 대해 질문할 때 <code>InvokePromptAsync</code> 으로 한 번만 호출하면 다음 작업이 모두 수행됩니다:</p><p>1. 사용자의 질문에 대한 임베딩이 생성됩니다.</p><p>2. 벡터 스토어에서 관련 항목을 검색합니다.</p><p>3. 쿼리 결과가 프롬프트 템플릿에 삽입됩니다.</p><p>4. 최종 프롬프트 형태의 실제 쿼리가 AI 채팅 완성 서비스로 전송됩니다.</p>// Invoke the LLM with a template that uses the search plugin to
// 1. get related information to the user query from the vector store
// 2. add the information to the LLM prompt.
var response = await kernel.InvokePromptAsync(
    promptTemplate: """
                    Please use this information to answer the question:
                    {{#with (SearchPlugin-GetTextSearchResults question)}}
                      {{#each this}}
                        Name: {{Name}}
                        Value: {{Value}}
                        Source: {{Link}}
                        -----------------
                      {{/each}}
                    {{/with}}
                    
                    Include the source of relevant information in the response.

                    Question: {{question}}
                    """,
    arguments: new KernelArguments
    {
        { "question", "Please show me all hotels that have a rooftop bar." },
    },
    templateFormat: "handlebars",
    promptTemplateFactory: new HandlebarsPromptTemplateFactory());<p>이전에 데이터 모델에 정의했던 <code>TextSearch*</code> 속성을 기억하시나요? 이러한 속성을 사용하면 벡터 스토어에 있는 항목의 정보로 자동으로 채워지는 프롬프트 템플릿에서 해당 자리 표시자를 사용할 수 있습니다.</p><p>질문 "에 대한 최종 답변은 다음과 같습니다." 루프톱 바가 있는 호텔을 모두 보여주세요:</p>Console.WriteLine(response.ToString());

// &gt; The hotel that has a rooftop bar is Skyline Suites. You can find more information about this hotel [here](https://example.com/yz567).<p>정답은 hotels.csv의 다음 항목을 참조합니다.</p>9;
Skyline Suites;
Offering panoramic city views from every suite, this hotel is perfect for those who love the urban landscape. Enjoy luxurious amenities, a rooftop bar, and close proximity to attractions. Luxurious and contemporary.;
https://example.com/yz567<p>이 예는 Microsoft 시맨틱 커널을 사용하면 잘 고안된 추상화를 통해 복잡성을 크게 줄일 수 있을 뿐만 아니라 매우 높은 수준의 유연성을 구현할 수 있다는 것을 잘 보여줍니다. 예를 들어 코드 한 줄만 변경하면 코드의 다른 부분을 리팩터링하지 않고도 벡터 저장소나 사용되는 AI 서비스를 교체할 수 있습니다.</p><p>동시에 이 프레임워크는 '인보크프롬프트' 기능이나 템플릿 또는 검색 플러그인 시스템과 같은 방대한 고급 기능 세트를 제공합니다.</p><p>전체 데모 애플리케이션은 Elasticsearch 벡터 스토어 커넥터 리포지토리에서 확인할 수 있습니다.</p><h2>Elasticsearch로 가능한 다른 기능</h2><ul><li><p><a href="https://www.elastic.co/search-labs/blog/semantic-search-simplified-semantic-text">Elasticsearch의 새로운 의미론적 텍스트 매핑: 시맨틱 검색 간소화</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/semantic-reranking-with-retrievers">검색기를 사용한 Elasticsearch의 시맨틱 재랭크</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-1">고급 RAG 기술 1부: 데이터 처리</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/advanced-rag-techniques-part-2">고급 RAG 기술 2부: 쿼리 및 테스트</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/elasticsearch-rag-with-llama3-opensource-and-elastic">Llama 3 오픈 소스 및 Elastic으로 RAG 구축하기</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/local-rag-agent-elasticsearch-langgraph-llama3">LangGraph, LLaMA3 및 Elasticsearch 벡터 저장소를 사용하여 로컬 에이전트를 처음부터 구축하는 튜토리얼</a></p></li></ul><h2>Elasticsearch &amp; 시맨틱 커널: 다음 단계는 무엇인가요?</h2><ul><li><p>.NET에서 GenAI 애플리케이션을 구축하는 동안 Elasticsearch 벡터 저장소를 Semantic Kernel에 쉽게 연결할 수 있는 방법을 보여드렸습니다. 다음 파이썬 통합을 기대해 주세요.</p></li><li><p>Semantic Kernel은 <a href="https://www.elastic.co/search-labs/tutorials/search-tutorial/vector-search/hybrid-search">하이브리드 검색</a>과 같은 고급 검색 기능에 대한 추상화를 구축하므로, .NET 개발자는 Elasticsearch 연결을 통해 Semantic Kernel을 사용하면서 이를 쉽게 구현할 수 있습니다.</p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/elasticsearch-connector-microsoft-semantic-kernel</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/elasticsearch-connector-microsoft-semantic-kernel</guid>
    <category><![CDATA[AI]]></category>
    <category><![CDATA[.NET]]></category>
    <category><![CDATA[벡터 데이터베이스]]></category>
    <dc:creator><![CDATA[Florian Bernd,Srikanth Manvi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d8725035e86f8a8/6a17fe447f6f1564f8c09d74/0564fe794e4c66d0507317822d7aa71826183d20-1311x762.jpg" length="0" type="image/jpeg"/>
    <pubDate>Fri, 06 Dec 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[Elasticsearch와 LlamaIndex로 RAG에서 민감 정보 및 PII 정보 보호하기]]></title>
    <description><![CDATA[Elasticsearch와 LlamaIndex를 사용하여 RAG 애플리케이션에서 민감한 데이터와 개인 식별 정보(PII) 데이터를 보호하는 방법.]]></description>
    <content:encoded><![CDATA[<p></p><p></p><p>이 글에서는 RAG(검색 증강 생성) 흐름에서 공개 LLM을 사용할 때 개인 식별 정보(PII)와 민감한 데이터를 보호하는 방법을 살펴봅니다. 오픈 소스 라이브러리와 정규식을 사용하여 PII 및 민감한 데이터를 마스킹하는 방법과 공개 LLM을 호출하기 전에 로컬 LLM을 사용하여 데이터를 마스킹하는 방법을 살펴봅니다.</p><p>시작하기 전에 이 게시물에서 사용하는 몇 가지 용어를 살펴보겠습니다.</p><h2>용어</h2><p><a href="https://www.llamaindex.ai/">LlamaIndex는</a> LLM(대규모 언어 모델) 애플리케이션을 구축하기 위한 선도적인 데이터 프레임워크입니다. LlamaIndex는 검색 증강 생성(RAG) 애플리케이션 구축의 다양한 단계에 대한 추상화를 제공합니다. 라마인덱스나 랭체인과 같은 프레임워크는 애플리케이션이 특정 LLM의 API에 밀접하게 연결되지 않도록 추상화를 제공합니다.</p><p><a href="https://www.elastic.co/enterprise-search">Elasticsearch는</a> <a href="https://elastic.co/">Elastic에서</a> 제공합니다. Elastic은 정밀도를 위한 전체 텍스트 검색, 의미 이해를 위한 벡터 검색, 두 가지 장점을 모두 갖춘 하이브리드 검색을 지원하는 확장 가능한 데이터 저장소이자 벡터 데이터베이스인 Elasticsearch를 개발한 업계 리더입니다. Elasticsearch는 분산형 RESTful 검색 및 분석 엔진, 확장 가능한 데이터 저장소, 벡터 데이터베이스입니다. 이 블로그에서 사용하는 Elasticsearch 기능은 무료 및 오픈 버전의 Elasticsearch에서 사용할 수 있습니다.</p><p><a href="https://www.promptingguide.ai/techniques/rag">검색 증강 생성(RAG)</a> 은 LLM에 외부 지식을 제공하여 사용자 쿼리에 대한 응답을 생성하는 AI 기술/패턴입니다. 이를 통해 LLM 응답을 특정 컨텍스트에 맞게 조정하고 일반적이지 않게 만들 수 있습니다.</p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.13/semantic-search.html">임베딩은</a> 텍스트/미디어의 의미를 숫자로 표현한 것입니다. 이는 고차원적 정보를 저차원적으로 표현한 것입니다.</p><h2>RAG 및 데이터 보호</h2><p>일반적으로 대규모 언어 모델(LLM)은 인터넷 데이터로 학습된 모델에서 사용할 수 있는 정보를 기반으로 응답을 생성하는 데 능숙합니다. 그러나 모델에서 정보를 사용할 수 없는 쿼리의 경우 LLM은 모델에 포함되지 않은 외부 지식이나 특정 세부 정보를 제공해야 합니다. 이러한 정보는 데이터베이스나 내부 지식 시스템에 있을 수 있습니다. 검색 증강 생성(RAG)은 주어진 사용자 쿼리에 대해 먼저 외부 시스템(예: 데이터베이스)에서 관련 컨텍스트/정보를 검색하고 해당 컨텍스트를 사용자 쿼리와 함께 LLM으로 전송하여 보다 구체적이고 관련성 높은 응답을 생성하는 기술입니다.</p><p>따라서 RAG 기술은 질문 답변, 콘텐츠 제작 등 맥락과 세부 사항에 대한 깊은 이해가 필요한 모든 분야에 매우 효과적으로 활용될 수 있습니다.</p><p>결과적으로 RAG 파이프라인에서는 PII(개인 식별 정보)와 같은 내부 정보와 민감한 정보(예: 이름, 생년월일, 계좌 번호 등)가 공개 LLM에 노출될 위험이 있습니다.</p><p><a href="https://www.elastic.co/guide/en/cloud-enterprise/current/ece-configure-rbac.html">역할 기반 액세스 제어</a>, <a href="https://www.elastic.co/search-labs/blog/dls-internal-knowledge-search">문서 수준 보안</a> 등과 같은 다양한 수단을 통해 Elasticsearch와 같은 벡터 데이터베이스를 사용할 때는 데이터가 안전하지만, 데이터를 외부의 공용 LLM으로 전송할 때는 주의해야 합니다.</p><p>대규모 언어 모델(LLM)을 사용할 때는 여러 가지 이유로 개인 식별 정보(PII)와 민감한 데이터를 보호하는 것이 중요합니다:</p><ul><li><p><strong>개인정보 보호 규정 준수</strong>: 많은 지역에서는 개인 데이터 보호를 의무화하는 유럽의 GDPR(일반 개인정보 보호 규정) 또는 미국의 CCPA(캘리포니아 소비자 개인정보 보호법)와 같은 엄격한 규정을 시행하고 있습니다. 이러한 법률을 준수해야 법적 처벌과 벌금을 피할 수 있습니다.</p></li><li><p><strong>사용자 신뢰</strong>: 민감한 정보의 기밀성과 무결성을 보장하면 사용자 신뢰가 쌓입니다. 사용자는 자신의 개인정보를 보호할 수 있다고 믿는 시스템을 사용하고 상호작용할 가능성이 더 높습니다.</p></li><li><p><strong>데이터 보안</strong>: 데이터 유출에 대한 보호는 필수입니다. 적절한 보호 장치 없이 LLM에 노출된 민감한 데이터는 도난이나 오용에 취약하여 신원 도용이나 금융 사기와 같은 잠재적 피해를 초래할 수 있습니다.</p></li><li><p><strong>윤리적 고려 사항</strong>: 윤리적으로 사용자의 개인정보를 존중하고 데이터를 책임감 있게 처리하는 것이 중요합니다. PII를 잘못 처리하면 차별, 낙인 또는 기타 부정적인 사회적 영향을 초래할 수 있습니다.</p></li><li><p><strong>비즈니스 평판</strong>: 민감한 데이터를 보호하지 못하는 기업은 평판이 손상되어 고객 및 매출 손실 등 비즈니스에 장기적으로 부정적인 영향을 미칠 수 있습니다.</p></li><li><p><strong>남용 위험 감소</strong>: 민감한 데이터를 안전하게 처리하면 편향된 데이터로 모델을 학습시키거나 개인을 조작하거나 해를 입히는 데 데이터를 사용하는 등 데이터 또는 모델의 악의적인 사용을 방지하는 데 도움이 됩니다.</p></li></ul><p>전반적으로 법률 준수, 사용자 신뢰 유지, 데이터 보안 보장, 윤리적 기준 유지, 비즈니스 평판 보호, 남용 위험 감소를 위해서는 PII 및 민감한 데이터를 강력하게 보호해야 합니다.</p><h2>빠른 요약</h2><p><a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch">이전 게시물에서는</a> LlamaIndex와 로컬에서 실행 중인 Mistral LLM을 사용하면서 벡터 데이터베이스로 Elasticsearch와 함께 RAG 기법을 사용하는 Q&amp;A 경험을 구현하는 방법에 대해 설명했습니다. 여기서는 이를 기반으로 구축합니다.</p><p>이제 이전 게시물에서 수행한 작업을 빠르게 논의하고 요약할 것이므로 이전 게시물을 읽는 것은 선택 사항입니다.</p><p>가상의 주택 보험 회사의 상담원과 고객 간의 콜센터 대화 샘플 데이터 세트가 있었습니다. "고객이 어떤 종류의 물 관련 문제에 대해 클레임을 제기하는가?"와 같은 질문에 답하는 간단한 RAG 애플리케이션을 만들었습니다.</p><p>대략적인 흐름은 다음과 같습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" alt="RAG 흐름" /><p>인덱싱 단계에서는 LlamaIndex 파이프라인을 사용하여 문서를 로드하고 인덱싱했습니다. 문서들은 청크로 묶여 임베딩과 함께 Elasticsearch 벡터 데이터베이스에 저장되었습니다.</p><p>사용자가 질문을 하는 쿼리 단계에서 LlamaIndex는 쿼리와 관련된 상위 K개의 유사한 문서를 검색했습니다. 이러한 상위 K 관련 문서는 쿼리와 함께 로컬에서 실행 중인 Mistral LLM으로 전송되어 사용자에게 다시 전송할 응답을 생성했습니다. 이전 게시물을 살펴보거나 <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/tree/main">코드를 살펴보세요</a>.</p><p>이전 게시물에서는 로컬에서 LLM을 실행했습니다. 그러나 프로덕션 환경에서는 <a href="https://openai.com/">OpenAI</a>, <a href="https://mistral.ai/">Mistral</a>, <a href="https://www.anthropic.com/claude">Anthropic</a> 등 다양한 회사에서 제공하는 외부 LLM을 사용할 수 있습니다. 사용 사례에 더 큰 기본 모델이 필요하거나 확장성, 가용성, 성능 등과 같은 엔터프라이즈 프로덕션 요구 사항으로 인해 로컬에서 실행하는 것이 옵션이 아니기 때문일 수 있습니다.</p><p>RAG 파이프라인에 외부 LLM을 도입하면 실수로 민감한 정보 및 PII가 LLM에 유출될 위험에 노출됩니다. 이 게시물에서는 외부 LLM으로 문서를 보내기 전에 RAG 파이프라인의 일부로 PII 정보를 마스킹하는 방법에 대한 옵션을 살펴봅니다.</p><h2>공개 LLM이 있는 RAG</h2><p>RAG 파이프라인에서 PII와 민감한 정보를 보호하는 방법에 대해 논의하기 전에 먼저 LlamaIndex, Elasticsearch Vector 데이터베이스 및 OpenAI LLM을 사용하여 간단한 RAG 애플리케이션을 구축해 보겠습니다.</p><h3>필수 구성 요소</h3><p>다음이 필요합니다.</p><ul><li><p>임베딩을 저장하기 위한 벡터 데이터베이스로 <strong>Elasticsearch를</strong> 가동하고 실행합니다. 이전 게시물 <a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch#install-elasticsearch">Elasticsearch 설치하기의</a> 지침을 따르세요.</p></li><li><p>AI API 키를 엽니다.</p></li></ul><h3>간단한 RAG 애플리케이션</h3><p>참고로 전체 코드는 이 <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/tree/protecting-pii">Github 리포지토리</a>(branch:protecting-pii)에서 찾을 수 있습니다. 아래 코드를 살펴볼 때 리포지토리 복제는 선택 사항입니다.</p><p>즐겨 사용하는 IDE에서 아래 3개의 파일을 사용하여 새 Python 애플리케이션을 만듭니다.</p><ul><li><p><code>index.py</code> 데이터 인덱싱과 관련된 코드가 있는 곳입니다.</p></li><li><p><code>query.py</code> 쿼리 및 LLM 상호 작용과 관련된 코드가 있는 곳입니다.</p></li><li><p><code>.env</code> API 키와 같은 구성 속성이 있는 곳입니다.</p></li></ul><p>몇 가지 패키지를 설치해야 합니다. 애플리케이션의 루트 폴더에 새 파이썬 <a href="https://docs.python.org/3/library/venv.html">가상 환경을</a> 만드는 것으로 시작합니다.</p>python3 -m venv .venv
<p>가상 환경을 활성화하고 아래 필수 패키지를 설치합니다.</p>source .venv/bin/activate
pip install llama-index 
pip install llama-index-embeddings-openai
pip install llama-index-vector-stores-elasticsearch
pip install sentence-transformers
pip install python-dotenv
pip install openai
<p>.env에서 OpenAI 및 Elasticsearch 연결 속성을 구성합니다. 파일입니다.</p>OPENAI_API_KEY="REPLACEME"
ELASTIC_CLOUD_ID="REPLACEME"
ELASTIC_API_KEY="REPLACEME"
<h4>데이터 인덱싱</h4><p>가상의 주택 보험 회사의 고객과 콜센터 상담원 <em>간의 대화가</em> 포함된 <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/blob/main/conversations.json">conversations.json</a> 파일을 다운로드하세요. 이 파일을 애플리케이션의 루트 디렉터리에 2개의 파이썬 파일 및 .env 파일과 함께 배치합니다. 파일을 생성합니다. 다음은 파일 내용의 예시입니다.</p>{
"conversation_id": 103,
"customer_name": "Sophia Jones",
"agent_name": "Emily Wilson",
"policy_number": "JKL0123",
"conversation": "Customer: Hi, I'm Sophia Jones. My Date of Birth is November 15th, 1985, Address is 303 Cedar St, Miami, FL 33101, and my Policy Number is JKL0123.\nAgent: Hello, Sophia. How may I assist you today?\nCustomer: Hello, Emily. I have a question about my policy.\nCustomer: There's been a break-in at my home, and some valuable items are missing. Are they covered?\nAgent: Let me check your policy for coverage related to theft.\nAgent: Yes, theft of personal belongings is covered under your policy.\nCustomer: That's a relief. I'll need to file a claim for the stolen items.\nAgent: We'll assist you with the claim process, Sophia. Is there anything else I can help you with?\nCustomer: No, that's all for now. Thank you for your assistance, Emily.\nAgent: You're welcome, Sophia. Please feel free to reach out if you have any further questions or concerns.\nCustomer: I will. Have a great day!\nAgent: You too, Sophia. Take care.",
"summary": "A customer inquires about coverage for stolen items after a break-in at home, and the agent confirms that theft of personal belongings is covered under the policy. The agent offers assistance with the claim process, resulting in the customer expressing relief and gratitude."
}
<p>아래 코드를 <code>index.py</code> 에서 데이터 인덱싱을 처리합니다.</p># index.py
# pip install sentence-transformers
# pip install llama-index-embeddings-openai
# pip install llama-index-embeddings-huggingface

import json
import os
from dotenv import load_dotenv
from llama_index.core import Document
from llama_index.core import Settings
from llama_index.core.ingestion import IngestionPipeline
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore


def get_documents_from_file(file):
   """Reads a json file and returns list of Documents"""

   with open(file=file, mode='rt') as f:
       conversations_dict = json.loads(f.read())

   # Build Document objects using fields of interest.
   documents = [Document(text=item['conversation'],
                         metadata={"conversation_id": item['conversation_id']})
                for
                item in conversations_dict]
   return documents

# Load .env file contents into env
load_dotenv('.env')
Settings.embed_model = HuggingFaceEmbedding(
   model_name="BAAI/bge-small-en-v1.5"
)

def main():
   # ElasticsearchStore is a VectorStore that
   # takes care of Elasticsearch Index and Data management.
   es_vector_store = ElasticsearchStore(index_name="convo_index",
                                        vector_field='conversation_vector',
                                        text_field='conversation',
                                        es_cloud_id=os.getenv("ELASTIC_CLOUD_ID"),
                                        es_api_key=os.getenv("ELASTIC_API_KEY"))

   # LlamaIndex Pipeline configured to take care of chunking, embedding
   # and storing the embeddings in the vector store.
   llamaindex_pipeline = IngestionPipeline(
       transformations=[
           SentenceSplitter(chunk_size=350, chunk_overlap=50),
           Settings.embed_model
       ],
       vector_store=es_vector_store
   )

   # Load data from a json file into a list of LlamaIndex Documents
   documents = get_documents_from_file(file="conversations.json")
   llamaindex_pipeline.run(documents=documents)
   print(".....Indexing Data Completed.....\n")

if __name__ == "__main__":
   main()
<p>위의 코드를 실행하여 확인하면 Elasticsearch에 인덱스가 생성되고 <code>convo_index</code> 이라는 이름의 Elasticsearch 인덱스에 임베딩이 저장됩니다.</p><p>LlamaIndex 수집 파이프라인에 대한 설명이 필요한 경우 이전 게시물인 <a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch#indexing-data">수집 파이프라인 만들기</a> 섹션을 참조하세요.</p><h4>쿼리하기</h4><p>이전 게시물에서는 <a href="https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch#querying">쿼리를</a> 위해 로컬 LLM을 사용했습니다.</p><p>이 게시물에서는 아래와 같이 퍼블릭 LLM인 OpenAI를 사용합니다.</p># query.py
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.llms.openai import OpenAI
from index import es_vector_store

# Public LLM where we send user query and Related Documents
llm = OpenAI()

index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are sent as-is. So any PII/Sensitive data is sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10)

query="Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)
<p>위의 코드는 OpenAI의 응답을 아래와 같이 출력합니다.</p><p>고객들은 지하실의 침수, 파이프 파열, 지붕의 우박 피해, 적시 통지 부족, 유지보수 문제, 점진적인 마모, 기존 피해 등의 이유로 인한 클레임 거부 등 다양한 물 관련 문제를 제기하고 있습니다. 각 사례에서 고객들은 보험금 청구 거부에 대해 불만을 표출하고 보험금 청구에 대한 공정한 평가와 결정을 요구했습니다.</p><h2>RAG에서 PII 마스킹</h2><p>지금까지 살펴본 것은 사용자 쿼리와 함께 문서를 있는 그대로 OpenAI로 보내는 것입니다.</p><p>벡터 스토어에서 관련 컨텍스트를 검색한 후 RAG 파이프라인에서 쿼리와 컨텍스트를 LLM으로 보내기 전에 PII와 민감한 정보를 마스킹할 수 있습니다.</p><p>PII 정보를 외부 LLM으로 전송하기 전에 마스킹하는 방법에는 여러 가지가 있으며, 각 방법에는 고유한 장점이 있습니다. 아래에서 몇 가지 옵션을 살펴봅니다.</p><ol><li><p>spacy.io 또는 <a href="https://microsoft.github.io/presidio/">Presidio</a> (Microsoft에서 유지 관리하는 오픈 소스 라이브러리)와 같은 NLP 라이브러리 사용.</p></li><li><p>즉시 사용 가능한 라마인덱스 사용 <code>NERPIINodePostprocessor.</code></p></li><li><p>다음을 통해 로컬 LLM 사용 <code>PIINodePostprocessor</code></p></li></ol><p>위의 방법 중 하나를 사용하여 마스킹 로직을 구현한 후에는 포스트프로세서(사용자 정의 포스트프로세서 또는 LlamaIndex의 기본 제공 포스트프로세서)를 사용하여 LlamaIndex 수집 파이프라인을 구성할 수 있습니다.</p><h3>NLP 라이브러리 사용</h3><p>RAG 파이프라인의 일부로 NLP 라이브러리를 사용하여 민감한 데이터를 마스킹할 수 있습니다. 이 데모에서는 spacy.io 패키지를 사용하겠습니다.</p><p><code>query_masking_nlp.py</code> 파일을 새로 만들고 아래 코드를 추가합니다.</p># query_masking_nlp.py

# pip install spacy
# python3 - m spacy download en_core_web_sm
import re
from typing import List, Optional

import spacy
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor.types import BaseNodePostprocessor
from llama_index.core.schema import NodeWithScore
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store

# Load the spaCy model
nlp = spacy.load("en_core_web_sm")

# Compile regex patterns for performance
phone_pattern = re.compile(r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b')
email_pattern = re.compile(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b')
date_pattern = re.compile(r'\b(\d{1,2}[-/]\d{1,2}[-/]\d{2,4}|\d{2,4}[-/]\d{1,2}[-/]\d{1,2})\b')
dob_pattern = re.compile(
r"(January|February|March|April|May|June|July|August|September|October|November|December)\s(\d{1,2})(st|nd|rd|th),\s(\d{4})")
address_pattern = re.compile(r'\d+\s+[\w\s]+\,\s+[A-Za-z]+\,\s+[A-Z]{2}\s+\d{5}(-\d{4})?')
zip_code_pattern =  re.compile(r'\b\d{5}(?:-\d{4})?\b')
policy_number_pattern = re.compile(r"[A-Z]{3}\d{4}\.$")  # 3 characters followed by 4 digits, in our case e.g XYZ9876

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# match = re.match(policy_number_pattern, "XYZ9876")
# print(match)


def mask_pii(text):
   """
   Masks Personally Identifiable Information (PII) in the given
   text using pre-defined regex patterns and spaCy's named entity recognition.
   Args:
       text (str): The input text containing potential PII.
   Returns:
       str: The text with PII masked.
   """

   # Process the text with spaCy for NER
   doc = nlp(text)

   # Mask entities identified by spaCy NER (e.g First/Last Names etc)
   for ent in doc.ents:
       if ent.label_ in ["PERSON", "ORG", "GPE"]:
           text = text.replace(ent.text, '[MASKED]')

   # Apply regex patterns after NER to avoid overlapping issues
   text = phone_pattern.sub('[PHONE MASKED]', text)
   text = email_pattern.sub('[EMAIL MASKED]', text)
   text = date_pattern.sub('[DATE MASKED]', text)
   text = address_pattern.sub('[ADDRESS MASKED]', text)
   text = dob_pattern.sub('[DOB MASKED]', text)
   text = zip_code_pattern.sub('[ZIP MASKED]', text)
   text = policy_number_pattern.sub('[POLICY MASKED]', text)

   return text


class CustomPostProcessor(BaseNodePostprocessor):
   """
   Custom Postprocessor which masks Personally Identifiable Information (PII).
   PostProcessor is called on the Documents before they are sent to the LLM.
   """
   def _postprocess_nodes(
           self, nodes: List[NodeWithScore], query_bundle: Optional[QueryBundle]
   ) -&gt; List[NodeWithScore]:
       # Masks PII
       for n in nodes:
          n.node.set_content(mask_pii(n.text))
       return nodes

   
# Use Public LLM to send user query and Related Documents
llm = OpenAI()
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents are masked based on custom logic defined in CustomPostProcessor._postprocess_nodes.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[CustomPostProcessor()])



query = "Give me summary of water related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)

<p>LLM의 응답은 아래와 같습니다.</p>고객들은 지하실의 침수, 파이프 파열, 지붕의 우박 피해, 폭우 시 침수 등 다양한 물 관련 문제를 제기해 왔습니다. 이러한 청구는 적시 통지 부족, 유지 관리 문제, 점진적인 마모, 기존 손상 등의 이유로 청구가 거부되어 불만을 야기했습니다. 고객들은 이러한 청구 거부에 따른 실망, 스트레스, 재정적 부담을 호소하며 청구에 대한 공정한 평가와 철저한 검토를 요구하고 있습니다. 일부 고객은 보험금 청구 처리가 지연되어 보험사가 제공하는 서비스에 대한 불만이 더욱 커졌습니다.<p>위의 코드에서 라마 인덱스 쿼리 엔진을 생성할 때 사용자 지정 포스트 프로세서를 제공합니다.</p><p><code>CustomPostProcessor</code> 의 <code>_postprocess_nodes</code> 메서드에 정의된 QueryEngine에 의해 호출되는 로직입니다. 우리는 SpaCy.io 라이브러리를 사용하여 명명된 엔티티를 감지한 다음 몇 가지 정규식을 사용하여 해당 이름과 민감한 정보를 대체한 후 문서를 LLM으로 전송하고 있습니다.</p><p>아래는 원본 대화의 일부와 CustomPostProcessor로 만든 마스크된 대화의 예입니다.</p><p>원본 텍스트:</p>고객님 안녕하세요: 안녕하세요, 저는 매튜 로페즈이고 생년월일은 1984년 10월 12일이며, 뉴욕 스몰타운 456 Cedar St, 34567에 거주하고 있습니다. 내 정책 번호는 TUV8901입니다. 상담원입니다: 안녕하세요, 매튜. 오늘 무엇을 도와드릴까요? 고객님 안녕하세요, 제 청구를 거부한 귀사의 결정에 매우 실망했습니다.<p>마스킹된 텍스트는 커스텀포스트프로세서에 의해 가려집니다.</p>고객님: 안녕하세요, 저는 [마스크됨], [마스크됨]은 [DOB 마스크됨]이며 456 Cedar St, [마스크됨], [마스크됨] 34567에 살고 있습니다. 내 정책 번호가 [마스킹됨]입니다. 상담원입니다: 안녕하세요, [MASKED]. 오늘 무엇을 도와드릴까요? 고객님 안녕하세요, 제 청구를 거부한 귀사의 결정에 매우 실망했습니다.<p>참고:</p><p><em>PII 및 민감한 정보를 식별하고 마스킹하는 것은 간단한 작업이 아닙니다. 민감한 정보의 다양한 형식과 의미를 다루려면 도메인과 데이터에 대한 충분한 이해가 필요합니다. 위에 제시된 코드는 일부 사용 사례에 적합할 수 있지만, 요구 사항과 테스트에 따라 수정해야 할 수도 있습니다.</em></p><h3>즉시 사용 가능한 라마 인덱스 사용 <code>NERPIINodePostprocessor</code></h3><p>LlamaIndex는 다음을 도입하여 RAG 파이프라인에서 PII 정보를 더 쉽게 보호할 수 있도록 했습니다. <code>NERPIINodePostprocessor.</code></p>from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import NERPIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.openai import OpenAI
from index import es_vector_store

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# Use Public LLM to send user query and Related Documents
llm = OpenAI()

ner_processor = NERPIINodePostprocessor()
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the LLM.
# Note that documents masked using the NERPIINodePostprocessor so that PII/Sensitive data is not sent to the LLM.
query_engine = index.as_query_engine(llm, similarity_top_k=10, node_postprocessors=[ner_processor])

query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
response = query_engine.query(bundle)
print(response)
<p>응답은 다음과 같습니다.</p>고객이 재산 피해와 관련하여 화재 관련 클레임을 제기했습니다. 한 사례에서는 방화는 보상 대상에서 제외된다는 이유로 차고 화재 피해에 대한 보험금 청구가 거부된 적이 있습니다. 또 다른 고객은 보험으로 보장되는 주택 화재 피해에 대해 보험금을 청구했습니다. 또한 한 고객은 주방 화재를 신고했고 화재 피해에 대한 보상을 받을 수 있었습니다.<h3>다음을 통해 로컬 LLM 사용 <code>PIINodePostprocessor</code></h3><p>또한 로컬 또는 프라이빗 네트워크에서 실행 중인 LLM을 활용하여 데이터를 퍼블릭 LLM으로 보내기 전에 마스킹 작업을 수행할 수도 있습니다.</p><p>마스킹을 위해 로컬 머신의 Ollama에서 실행 중인 Mistral을 사용합니다.</p><h4>로컬에서 미스트랄 실행</h4><p><a href="https://ollama.com/">Ollama를</a> 다운로드하여 설치합니다. Ollama를 설치한 후 다음 명령을 실행하여 <a href="https://ollama.com/library/mistral">미스트랄을</a>다운로드하고 실행합니다.</p>ollama run mistral
<p>모델을 로컬에서 처음 다운로드하고 실행하는 데 몇 분 정도 걸릴 수 있습니다. 아래 "구름에 대한 시를 써주세요"와 같은 질문을 통해 미스트랄이 실행 중인지 확인하고 마음에 드는 시가 있는지 확인합니다. 나중에 코드를 통해 미스트랄 모델과 상호 작용해야 하므로 올라마를 계속 실행하세요.</p><p><code>query_masking_local_LLM.py</code> 이라는 새 파일을 만들고 아래 코드를 추가합니다.</p># pip install llama-index-llms-ollama
from llama_index.core import VectorStoreIndex, QueryBundle, Settings
from llama_index.core.postprocessor import PIINodePostprocessor
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama
from llama_index.llms.openai import OpenAI
from index import es_vector_store

Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")

# Use Public LLM to send user query and Related Documents and Local LLM to mask
public_llm = OpenAI()
local_llm = Ollama(model="mistral")

pii_processor = PIINodePostprocessor(llm=local_llm)
index = VectorStoreIndex.from_vector_store(es_vector_store)

# This query_engine, for a given user query retrieves top 10 similar documents from
# Elasticsearch vector database and sends the documents along with the user query to the public LLM.
# Note that documents are masked using the local llm via PIINodePostprocessor
# so that PII/Sensitive data is not sent to the public LLM.
query_engine = index.as_query_engine(public_llm, similarity_top_k=10, node_postprocessors=[pii_processor])


query = "Give me summary of fire related claims that customers raised."
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)
<p>응답은 아래와 같습니다.</p>고객이 재산 피해와 관련하여 화재 관련 클레임을 제기했습니다. 한 사례에서는 방화는 보상 대상에서 제외된다는 이유로 차고 화재 피해에 대한 보험금 청구가 거부된 적이 있습니다. 또 다른 고객은 보험으로 보장되는 주택 화재 피해에 대해 보험금을 청구했습니다. 또한 한 고객은 주방 화재를 신고했고 화재 피해에 대한 보상을 받을 수 있었습니다.<h3>결론</h3><p>이 게시물에서는 RAG 흐름에서 공개 LLM을 사용할 때 PII 및 민감한 데이터를 보호하는 방법을 보여드렸습니다. 이를 달성하기 위한 다양한 방법을 시연했습니다. 이러한 접근 방식을 채택하기 전에 사용 사례와 요구 사항에 따라 테스트해 보는 것이 좋습니다.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/rag-security-masking-pii</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/rag-security-masking-pii</guid>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Srikanth Manvi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" length="0" type="image/png"/>
    <pubDate>Thu, 25 Jul 2024 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[라마인덱스, 엘라스틱서치, 미스트랄을 이용한 검색 증강 생성(RAG)]]></title>
    <description><![CDATA[LlamaIndex, Elasticsearch, 로컬에서 실행 중인 Mistral을 사용해 RAG(검색 증강 생성) 시스템을 구현하는 방법을 알아보세요.]]></description>
    <content:encoded><![CDATA[<p>이 블로그에서는 벡터 데이터베이스로서 Elasticsearch와 함께 RAG(검색 증강 생성) 기법을 사용하여 Q&amp;A 환경을 구현하는 방법에 대해 설명합니다. LlamaIndex와 로컬에서 실행되는 Mistral LLM을 사용합니다.</p><p>시작하기 전에 몇 가지 용어를 살펴보겠습니다.</p><h3>용어</h3><p><a href="https://www.llamaindex.ai/">LlamaIndex는</a> LLM(대규모 언어 모델) 애플리케이션을 구축하기 위한 선도적인 데이터 프레임워크입니다. LlamaIndex는 검색 증강 생성(RAG) 애플리케이션 구축의 다양한 단계에 대한 추상화를 제공합니다. 라마인덱스나 랭체인과 같은 프레임워크는 애플리케이션이 특정 LLM의 API에 밀접하게 연결되지 않도록 추상화를 제공합니다.</p><p><a href="https://www.elastic.co/enterprise-search">Elasticsearch는</a> <a href="https://elastic.co/">Elastic에서</a> 제공합니다. Elastic은 정밀도를 위한 전체 텍스트 검색, 의미 이해를 위한 벡터 검색, 두 가지 장점을 모두 갖춘 하이브리드 검색을 지원하는 검색 및 분석 엔진인 Elasticsearch를 개발한 업계 리더입니다. Elasticsearch는 확장 가능한 데이터 저장소이자 벡터 데이터베이스입니다. 이 블로그에서 사용하는 Elasticsearch 기능은 무료 및 오픈 버전의 Elasticsearch에서 사용할 수 있습니다.</p><p><a href="https://www.promptingguide.ai/techniques/rag">검색 증강 생성(RAG)</a> 은 사용자 쿼리에 대한 응답을 생성하기 위해 LLM에 외부 지식을 제공하는 AI 기술/패턴입니다. 이를 통해 특정 상황에 맞게 LLM 응답을 조정할 수 있으며 응답이 더욱 구체화됩니다.</p><p><a href="https://docs.mistral.ai/">미스트랄은</a> 오픈 소스 및 최적화된 엔터프라이즈급 LLM 모델을 모두 제공합니다. 이 튜토리얼에서는 노트북에서 실행되는 오픈 소스 모델 <a href="https://docs.mistral.ai/models/#mistral-7b">mistral-7b를</a> 사용합니다. 노트북에서 모델을 실행하고 싶지 않다면 클라우드 버전을 사용할 수도 있는데, 이 경우 올바른 API 키와 패키지를 사용하도록 이 블로그의 코드를 수정해야 합니다.</p><p><a href="https://ollama.com/">Ollama는</a> 노트북에서 로컬로 LLM을 실행하는 데 도움이 됩니다. Ollama를 사용하여 오픈 소스 Mistral-7b 모델을 로컬에서 실행할 것입니다.</p><p><a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.13/semantic-search.html">임베딩은</a> 텍스트/미디어의 의미를 숫자로 표현한 것입니다. 이는 고차원적 정보를 저차원적으로 표현한 것입니다.</p><h3>LlamaIndex, Elasticsearch로 RAG 애플리케이션 구축하기 &amp; Mistral: 시나리오 개요</h3><p><strong>시나리오:</strong></p><p>가상의 주택 보험 회사의 상담원과 고객 간의 콜센터 대화에 대한 샘플 데이터 세트(JSON 파일)가 있습니다. 다음과 같은 질문에 답할 수 있는 간단한 RAG 애플리케이션을 구축합니다.</p><p><code>Give me summary of water related issues.</code></p><h3>높은 수준의 흐름</h3><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" alt="RAG 흐름" /><p>저희는 Ollama를 사용하여 로컬에서 Mistral LLM을 실행하고 있습니다.</p><p>다음으로, JSON 파일( <code>Documents</code> )의 <em>대화를</em> <a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">ElasticsearchStore</a> (Elasticsearch가 지원하는 VectorStore)로 로드합니다. 문서를 로드하는 동안 로컬에서 실행되는 Mistral 모델을 사용하여 임베딩을 생성합니다. 우리는 이러한 임베딩을 <em>대화와</em> 함께 LlamaIndex Elasticsearch 벡터 저장소<a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">(ElasticsearchStore)</a>에 저장합니다.</p><p>LlamaIndex 수집 파이프라인을 구성하고 여기에 우리가 사용하는 로컬 LLM(이 경우 Ollama를 통해 실행되는 Mistral)을 제공합니다.</p><p>"물 관련 이슈를 요약해 주세요."와 같은 질문을 할 때, Elasticsearch는 시맨틱 검색을 수행하여 물 문제와 관련된 <em>대화를</em> 반환합니다. 이러한 <em>대화는</em> 원래 질문과 함께 로컬에서 실행 중인 LLM으로 전송되어 답변을 생성합니다.</p><h3>RAG 애플리케이션 구축 단계</h3><h4>로컬에서 미스트랄 실행</h4><p><a href="https://ollama.com/">Ollama를</a> 다운로드하여 설치합니다. Ollama를 설치한 후 다음 명령을 실행하여 <a href="https://ollama.com/library/mistral">미스트랄을</a>다운로드하고 실행합니다.</p>ollama run mistral
<p>모델을 로컬에서 처음 다운로드하고 실행하는 데 몇 분 정도 걸릴 수 있습니다. 아래 "구름에 대한 시를 써주세요"와 같은 질문을 통해 미스트랄이 실행 중인지 확인하고 마음에 드는 시가 있는지 확인합니다. 나중에 코드를 통해 미스트랄 모델과 상호 작용해야 하므로 올라마를 계속 실행하세요.</p><h4>Elasticsearch 설치</h4><p>클라우드 배포<a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/elastic-cloud">(여기 지침)를</a> 생성하거나 Docker에서 실행<a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/docker">(여기 지침)</a>하여 Elasticsearch를 시작하고 실행하세요. <a href="https://www.elastic.co/search-labs/tutorials/install-elasticsearch/docker#self-hosted-production-deployments">여기에서</a> 시작하여 프로덕션 등급 자체 호스팅 Elasticsearch 배포를 생성할 수도 있습니다.</p><p>클라우드 배포를 사용 중이라고 가정하고 지침에 언급된 대로 배포를 위한 API 키와 클라우드 ID를 가져옵니다. 나중에 사용하겠습니다.</p><h4>RAG 애플리케이션</h4><p>참고로 전체 코드는 이 <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany">깃허브 리포지토리에서</a> 확인할 수 있습니다. 아래 코드를 통해 진행하므로 리포지토리를 복제하는 것은 선택 사항입니다.</p><p>즐겨 사용하는 IDE에서 아래 3개의 파일을 사용하여 새 Python 애플리케이션을 만듭니다.</p><ul><li><p><code>index.py</code> 데이터 인덱싱과 관련된 코드가 있는 곳입니다.</p></li><li><p><code>query.py</code> 쿼리 및 LLM 상호 작용과 관련된 코드가 있는 곳입니다.</p></li><li><p><code>.env</code> API 키와 같은 구성 속성이 있는 곳입니다.</p></li></ul><p>몇 가지 패키지를 설치해야 합니다. 애플리케이션의 루트 폴더에 새 파이썬 <a href="https://docs.python.org/3/library/venv.html">가상 환경을</a> 만드는 것으로 시작합니다.</p>python3 -m venv .venv
<p>가상 환경을 활성화하고 아래 필수 패키지를 설치합니다.</p>source .venv/bin/activate
pip install llama-index 
pip install llama-index-embeddings-ollama
pip install llama-index-llms-ollama
pip install llama-index-vector-stores-elasticsearch
pip install sentence-transformers
pip install python-dotenv
<h4>데이터 인덱싱</h4><p>가상의 주택 보험 회사의 고객과 콜센터 상담원 <em>간의 대화가</em> 포함된 <a href="https://github.com/srikanthmanvi/RAG-InsuranceCompany/blob/main/conversations.json">conversations.json</a> 파일을 다운로드하세요. 이 파일을 애플리케이션의 루트 디렉터리에 2개의 파이썬 파일 및 .env 파일과 함께 배치합니다. 파일을 생성합니다. 다음은 파일 내용의 예시입니다.</p>{
    "conversation_id": 103,
    "customer_name": "Sophia Jones",
    "agent_name": "Emily Wilson",
    "policy_number": "JKL0123",
    "conversation": "Customer: Hi, I'm Sophia Jones. My Date of Birth is November 15th, 1985, Address is 303 Cedar St, Miami, FL 33101, and my Policy Number is JKL0123.\nAgent: Hello, Sophia. How may I assist you today?\nCustomer: Hello, Emily. I have a question about my policy.\nCustomer: There's been a break-in at my home, and some valuable items are missing. Are they covered?\nAgent: Let me check your policy for coverage related to theft.\nAgent: Yes, theft of personal belongings is covered under your policy.\nCustomer: That's a relief. I'll need to file a claim for the stolen items.\nAgent: We'll assist you with the claim process, Sophia. Is there anything else I can help you with?\nCustomer: No, that's all for now. Thank you for your assistance, Emily.\nAgent: You're welcome, Sophia. Please feel free to reach out if you have any further questions or concerns.\nCustomer: I will. Have a great day!\nAgent: You too, Sophia. Take care.",
    "summary": "A customer inquires about coverage for stolen items after a break-in at home, and the agent confirms that theft of personal belongings is covered under the policy. The agent offers assistance with the claim process, resulting in the customer expressing relief and gratitude."
}
<p><code>index.py</code> 에서 <code>get_documents_from_file</code> 라는 함수를 정의하여 json 파일을 읽고 문서 목록을 생성합니다. <a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/documents_and_nodes/">문서</a> 객체는 LlamaIndex가 작동하는 기본 정보 단위입니다.</p># index.py
import json, os
from llama_index.core import Document, Settings
from llama_index.core.node_parser import SentenceSplitter
from llama_index.core.ingestion import IngestionPipeline
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore
from dotenv import load_dotenv

def get_documents_from_file(file):
   """Reads a json file and returns list of Documents"""

   with open(file=file, mode='rt') as f:
       conversations_dict = json.loads(f.read())
      
   # Build Document objects using fields of interest.
   documents = [Document(text=item['conversation'],
                         metadata={"conversation_id": item['conversation_id']})
                for
                item in conversations_dict]
   return documents
<p>수집 파이프라인 생성</p><p>먼저, <code>Install Elasticsearch</code> 섹션에서 얻은 Elasticsearch CloudID와 API 키를 <code>.env</code> 파일에 추가합니다. <code>.env</code> 파일은 아래와 같이 표시되어야 합니다(실제 값 포함).</p>ELASTIC_CLOUD_ID=&lt;REPLACE WITH YOUR CLOUD ID&gt;
ELASTIC_API_KEY=&lt;REPLACE WITH YOUR API_KEY&gt;
<p>LlamaIndex <a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/ingestion_pipeline/">수집 파이프라인을</a> 사용하면 여러 구성 요소를 사용하여 파이프라인을 구성할 수 있습니다. <code>index.py</code> 파일에 아래 코드를 추가합니다.</p># index.py

# Load .env file contents into env
# ELASTIC_CLOUD_ID and ELASTIC_API_KEY are expected to be in the .env file.
load_dotenv('.env')

# ElasticsearchStore is a VectorStore that
# takes care of ES Index and Data management.
es_vector_store = ElasticsearchStore(index_name="calls",
                                     vector_field='conversation_vector',
                                     text_field='conversation',
                                     es_cloud_id=os.getenv("ELASTIC_CLOUD_ID"),
                                     es_api_key=os.getenv("ELASTIC_API_KEY"))


def main():
    # Embedding Model to do local embedding using Ollama.
    ollama_embedding = OllamaEmbedding("mistral")

    # LlamaIndex Pipeline configured to take care of chunking, embedding
    # and storing the embeddings in the vector store.
    pipeline = IngestionPipeline(
        transformations=[
            SentenceSplitter(chunk_size=350, chunk_overlap=50),
            ollama_embedding,
        ],
        vector_store=es_vector_store
    )

    # Load data from a json file into a list of LlamaIndex Documents
    documents = get_documents_from_file(file="conversations.json")

    pipeline.run(documents=documents)
    print(".....Done running pipeline.....\n")


if __name__ == "__main__":
    main()

<p>앞서 언급했듯이 LlamaIndex 수집 파이프라인은 여러 구성 요소로 구성될 수 있습니다. <code>pipeline = IngestionPipeline(...</code> 라인의 파이프라인에 3개의 컴포넌트를 추가하고 있습니다.</p><ul><li><p><a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/node_parsers/modules/?h=sentencesp#sentencesplitter">SentenceSplitter</a>: <code>get_documents_from_file()</code> 의 정의에서 볼 수 있듯이 각 문서에는 json 파일에서 찾은 대화를 저장하는 텍스트 필드가 있습니다. 이 텍스트 필드는 긴 텍스트입니다. 시맨틱 검색이 제대로 작동하려면 텍스트를 작은 텍스트 덩어리로 잘게 쪼개야 합니다. <a href="https://docs.llamaindex.ai/en/stable/module_guides/loading/node_parsers/modules/?h=sentencesp#sentencesplitter">SentenceSplitter</a> 클래스가 이 작업을 수행합니다. 이러한 청크를 라마인덱스 용어로는 노드라고 합니다. 노드에는 해당 노드가 속한 문서를 가리키는 메타데이터가 있습니다. 또는 이 <a href="https://www.elastic.co/search-labs/blog/chunking-via-ingest-pipelines">블로그에</a> 나와 있는 것처럼 청킹을 위해 Elasticsearch Ingestpipeline을 사용할 수도 있습니다.</p></li><li><p><a href="https://docs.llamaindex.ai/en/stable/module_guides/models/embeddings/">올라마 임베딩</a>: 임베딩 모델은 텍스트를 숫자(벡터라고도 함)로 변환합니다. 숫자로 표현하면 단순한 텍스트 검색이 아닌 단어의 의미와 일치하는 검색 결과를 얻을 수 있는 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/semantic-search.html">의미론적 검색을</a> 실행할 수 있습니다. 당사는 섭취 파이프라인에 <code>OllamaEmbedding("mistral")</code> 을 제공합니다. SentenceSplitter를 사용하여 분할한 청크는 Ollama를 통해 로컬 머신에서 실행 중인 Mistral 모델로 전송되고, Mistral은 청크에 대한 임베딩을 생성합니다.</p></li><li><p><a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">엘라스틱서치스토어</a>: LlamaIndex ElasticsearchStore 벡터 스토어는 생성 중인 임베딩을 Elasticsearch 인덱스로 백업합니다. ElasticsearchStore는 지정된 Elasticsearch 인덱스의 콘텐츠를 생성하고 채우는 작업을 처리합니다. ElasticsearchStore( <code>es_vector_store</code> 참조)를 생성할 때 생성하려는 Elasticsearch 인덱스의 이름(이 경우<code>calls</code> ), 임베딩을 저장할 인덱스의 필드(이 경우<code>conversation_vector</code> ), 텍스트를 저장할 필드(이 경우<code>conversation</code> )를 지정합니다. 요약하면, 구성에 따라 <code>ElasticsearchStore</code> 은 (자동 생성된 다른 필드 중에서) <code>conversation_vector</code> 및 <code>conversation</code> 을 필드로 사용하여 Elasticsearch에 새 인덱스를 생성합니다.</p></li></ul><p>이 모든 것을 하나로 묶어 <code>pipeline.run(documents=documents)</code> 를 호출하여 파이프라인을 실행합니다.</p><p>index.py 스크립트를 실행하여 수집 파이프라인을 실행합니다:</p>python index.py
<p>파이프라인 실행이 완료되면, Elasticsearch에 <code>calls</code> 이라는 새 인덱스가 표시됩니다. 개발자 콘솔을 사용하여 간단한 Elasticsearch 쿼리를 실행하면 임베딩과 함께 로드된 데이터를 볼 수 있어야 합니다.</p>GET calls/_search?size=1
<p>지금까지 한 일을 요약하자면, JSON 파일에서 문서를 생성하고, 이를 청크로 분할하고, 해당 청크에 대한 임베딩을 생성하고, 임베딩(및 텍스트 대화)을 벡터 저장소(ElasticsearchStore)에 저장했습니다.</p><h4>쿼리하기</h4><p>llamaIndex <a href="https://docs.llamaindex.ai/en/stable/module_guides/indexing/vector_store_guide/">벡터스토어인덱스를</a> 사용하면 관련 문서를 검색하고 데이터를 쿼리할 수 있습니다. 기본적으로 VectorStoreIndex는 임베딩을 <a href="https://docs.llamaindex.ai/en/stable/module_guides/indexing/vector_store_guide/">SimpleVectorStore에</a> 인메모리로 저장합니다. 그러나 외부 벡터 저장소(예: <a href="https://developers.llamaindex.ai/python/examples/vector_stores/elasticsearchindexdemo/">ElasticsearchStore</a>)를 대신 사용하여 임베딩을 영구적으로 만들 수 있습니다.</p><p><code>query.py</code> 을 열고 아래 코드를 붙여넣습니다.</p># query.py
from llama_index.core import VectorStoreIndex, QueryBundle, Response, Settings
from llama_index.embeddings.ollama import OllamaEmbedding
from llama_index.llms.ollama import Ollama
from index import es_vector_store

# Local LLM to send user query to
local_llm = Ollama(model="mistral")
Settings.embed_model= OllamaEmbedding("mistral")

index = VectorStoreIndex.from_vector_store(es_vector_store)
query_engine = index.as_query_engine(local_llm, similarity_top_k=10)

query="Give me summary of water related issues"
bundle = QueryBundle(query, embedding=Settings.embed_model.get_query_embedding(query))
result = query_engine.query(bundle)
print(result)
<p>로컬 LLM(<code>local_llm</code>)을 정의하여 Ollama에서 실행되는 미스트랄 모델을 가리키도록 합니다. 다음으로, 앞서 생성한 ElasticsearchStore 벡터 스토어에서 VectorStoreIndex(<code>index</code>)를 생성한 다음 이 인덱스에서 쿼리 엔진을 가져옵니다. 쿼리 엔진을 만드는 동안 응답에 사용해야 하는 로컬 LLM을 참조하고, 벡터 스토어에서 검색하여 응답을 받기 위해 LLM으로 보내야 하는 문서 수를 구성하기 위해 (<code>similarity_top_k=10</code>)도 제공합니다.</p><p><code>query.py</code> 스크립트를 실행하여 RAG 흐름을 실행합니다:</p>python query.py
<p><code>Give me summary of water related issues</code> ( <code>query</code>)으로 쿼리를 보내면 관련 문서와 함께 제공되는 LLM의 응답은 아래와 같아야 합니다.</p>제공된 맥락에서 고객이 물과 관련된 피해에 대한 보상에 대해 문의한 사례를 몇 가지 확인할 수 있습니다. 두 사례에서는 홍수로 인한 지하실 피해, 또 다른 사례에서는 지붕 누수가 문제였습니다. 상담원은 두 가지 유형의 수해가 각 보험에 따라 보장된다는 사실을 확인했습니다. 따라서 홍수 및 지붕 누수를 포함한 물 관련 문제는 일반적으로 주택 보험에서 보장됩니다.<h4>몇 가지 주의 사항:</h4><p>이 블로그 게시물은 Elasticsearch를 사용한 RAG 기술에 대한 초보자 소개이므로 이 시작점을 프로덕션으로 가져갈 수 있는 기능 구성은 생략되어 있습니다. 프로덕션 사용 사례를 위해 구축할 때는 <a href="https://www.elastic.co/search-labs/blog/dls-internal-knowledge-search">문서 수준 보안으로</a> 데이터를 보호할 수 있는지, Elasticsearch <a href="https://www.elastic.co/search-labs/blog/chunking-via-ingest-pipelines">수집 파이프라인의</a> 일부로 데이터를 청크화하는지, 심지어 GenAI/Chat/Q에 사용되는 동일한 데이터에서 다른 <a href="https://www.elastic.co/guide/en/machine-learning/current/ml-nlp-overview.html">ML 작업을</a> 실행하는지 등 보다 정교한 측면을 고려해야 합니다.&amp;A 사용 사례.</p><p>또한 <a href="https://www.elastic.co/guide/en/enterprise-search/current/connectors.html">Elastic 커넥터를</a> 사용하여 다양한 외부 소스(예: Azure Blob Storage, Dropbox, Gmail 등)에서 데이터를 소싱하고 임베딩을 생성하는 것도 고려할 수 있습니다.</p><p>Elastic은 위의 모든 것을 가능하게 하며, GenAI 사용 사례와 그 이상을 위한 포괄적인 엔터프라이즈급 솔루션을 제공합니다.</p><h4>이제 그 다음은?</h4><ul><li><p>사용자 질문과 함께 10개의 관련 대화를 LLM으로 보내 답변을 작성하는 것을 보셨을 것입니다. 이러한 대화에는 이름, 생년월일, 주소 등과 같은 PII(개인 식별 정보)가 포함될 수 있습니다. 저희의 경우 LLM이 로컬에 있으므로 데이터 유출은 문제가 되지 않습니다. 그러나 클라우드에서 실행되는 LLM(예: OpenAI)을 사용하려는 경우 PII 정보가 포함된 문자를 보내는 것은 바람직하지 않습니다. 후속 블로그에서는 RAG 흐름에서 외부 LLM으로 전송하기 전에 PII 정보를 마스킹하는 방법을 살펴보겠습니다.</p></li><li><p>이 글에서는 로컬 LLM을 사용했으며, 다음 글인 RAG의 PII 데이터 마스킹에서는 로컬 LLM에서 퍼블릭 LLM으로 쉽게 전환하는 방법을 살펴볼 예정입니다.</p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/rag-with-llamaIndex-and-elasticsearch</guid>
    <category><![CDATA[AI]]></category>
    <dc:creator><![CDATA[Srikanth Manvi]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt9d3882da43bfdac0/6a17050867045bd5fe45c0e9/9d51295472f8bcca3d1973248acb724f8b94767e-1054x555.png" length="0" type="image/png"/>
    <pubDate>Fri, 12 Apr 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>