<?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[Peter Straßer - 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[Peter Straßer - 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/peter-straer</link>
    </image>
    <link>https://www.elastic.co/kr/search-labs/author/peter-straer</link>
    <atom:link href="https://www.elastic.co/kr/search-labs/rss/author/peter-straer.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[kr]]></language>
    <lastBuildDate>Tue, 22 Sep 2026 08:35:15 GMT</lastBuildDate>
  <item>
    <title><![CDATA[Elasticsearch에서 지연 상호작용 모델 확장하기 - 2부]]></title>
    <description><![CDATA[이 문서에서는 디스크 공간 사용량을 줄이고 계산 효율성을 개선하는 등 대규모 프로덕션 워크로드에 대비하여 지연 상호작용 벡터를 준비하는 기술을 살펴봅니다.]]></description>
    <content:encoded><![CDATA[<p><a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">ColPali에 대한 이전 블로그</a>에서는 Elasticsearch로 시각적 검색 애플리케이션을 생성하는 방법을 살펴보았습니다. 주로 ColPali와 같은 모델이 애플리케이션에 가져다주는 가치에 초점을 맞췄지만, 이러한 모델은 E5와 같은 바이인코더를 사용하는 벡터 검색에 비해 성능상의 단점이 있습니다.</p><p><a href="https://www.elastic.co/search-labs/blog/elastiacsearch-colpali-document-search">1부</a>의 예시를 바탕으로, 이 블로그는 다양한 기법과 Elasticsearch의 강력한 벡터 검색 도구를 사용하여 대규모 프로덕션 작업에 적합한 지연 상호작용 벡터를 준비하는 방법을 탐구합니다.</p><p>전체 코드 예시는 <a href="https://github.com/elastic/elasticsearch-labs/tree/main/supporting-blog-content/colpali">GitHub</a>에서 확인하실 수 있습니다.</p><h2>후기 상호작용 모델의 과제</h2><p>ColPali는 인덱스에 있는 문서에 대해 페이지당 1000개 이상의 벡터를 생성합니다.</p><p>이로 인해 지연 상호작용 벡터를 사용할 때 두 가지 문제가 발생합니다.</p><ol><li><p>디스크 공간: 이러한 모든 벡터를 디스크에 저장하면 상당한 저장 공간 사용량이 발생하며, 이는 확장 시 비용이 많이 들 수 있습니다.</p></li><li><p>계산: <code>maxSimDotProduct()</code> 비교를 사용하여 문서 순위를 매길 때는 각 문서에 대한 이러한 모든 벡터를 쿼리의 N 벡터와 비교해야 합니다.</p></li></ol><p>이러한 문제를 해결하기 위한 몇 가지 기술을 살펴보겠습니다.</p><h2>지연 상호작용 모델을 최적화하는 기술</h2><h3>비트 벡터</h3><p>디스크 공간을 줄이기 위해 이미지를 비트 벡터로 압축할 수 있습니다. 다음과 같은 간단한 Python 함수를 사용하여 멀티 벡터를 비트 벡터로 변환할 수 있습니다.</p>def to_bit_vectors(embeddings: list) -&gt; list:
    return [
        np.packbits(np.where(np.array(embedding) &gt; 0, 1, 0))
        .astype(np.int8)
        .tobytes()
        .hex()
        for embedding in embeddings
    ]<p>이 함수의 핵심 개념은 간단합니다. 0보다 큰 값은 1이 되고, 0보다 작은 값은 0이 됩니다. 그 결과 0과 1로 이루어진 배열이 생성되며, 이를 16진수 스트링으로 변환하여 비트 벡터를 나타냅니다.</p><p>인덱스 매핑을 위해 <code>element_type</code> 매개변수를 <code>bit</code>로 설정했습니다.</p>mappings = {
    "mappings": {
        "properties": {
            "col_pali_vectors": {
                "type": "rank_vectors",
                "element_type": "bit"
            }
        }
    }
}

es.indices.create(index=INDEX_NAME, body=mappings)<p>인덱스에 새로운 비트 벡터를 모두 작성한 후, 다음 코드를 사용하여 비트 벡터의 순위를 매길 수 있습니다.</p>query = "What do companies use for recruiting?"
query_vector = to_bit_vectors(create_col_pali_query_vectors(query))
es_query = {
    "_source": False,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "maxSimInvHamming(params.query_vector, 'col_pali_vectors')",
                "params": {
                    "query_vector": query_vector
                }
            }
        }
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltcaf0c8f999d68701/6a17f46696142a6f46eb1c56/51b989446e4099745971e1eac27d147a78d13e0a-1600x480.png" alt="" /><p>약간의 정확도를 희생하는 대신 비트 마스크, SIMD 등과 같은 최적화를 활용할 수 있는 해밍 거리(<code>maxSimInvHamming(...)</code>)를 사용할 수 있습니다. <a href="https://www.elastic.co/search-labs/blog/bit-vectors-in-elasticsearch">비트 벡터와 해밍 거리에 대한 자세한 내용은 블로그</a>에서 확인하세요.</p><p>대안으로, 쿼리 벡터를 비트 벡터로 변환하지 않고 완전한 충실도의 지연 상호작용 벡터로 검색할 수 있습니다.</p>query = "What do companies use for recruiting?"
query_vector = create_col_pali_query_vectors(query)
es_query = {
    "_source": False,
    "query": {
        "script_score": {
            "query": {
                "match_all": {}
            },
            "script": {
                "source": "maxSimDotProduct(params.query_vector, 'col_pali_vectors')",
                "params": {
                    "query_vector": query_vector
                }
            }
        }
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2fa6c89fb451b6e0/6a17f468af47b65da9cde0d9/89f3c795c6dc44b2f7d46801320288316b47e1b2-1600x488.png" alt="비트 벡터를 사용하여 지연 상호작용 모델을 최적화한 결과" /><p>이는 비대칭 유사도 함수를 사용하여 벡터를 비교합니다.</p><p></p><p>두 비트 벡터 사이의 일정한 해밍 거리에 대해 생각해 보겠습니다. 문서 벡터 <em>D</em>가 있다고 가정해 봅시다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltd4b6ece1ec4dedac/6a17f4694b055d248143234e/366a70a23e37d403788327b7aefc873fd4482f5e-1235x86.png" alt="" /><p>그리고 쿼리 벡터 <em>Q</em>가 있습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7721df9c8f0d84f1/6a17f46b3e03d77cf54f2dcb/978ec31e0afbc0eaebf548a015b628c0cad84625-1247x84.png" alt="" /><p></p><p>간단한 이진 양자화는 벡터 <em>D</em>를 <code>10101101</code>로, <em>Q</em>를 <code>11111011</code>로 변환합니다. 해밍 거리를 찾으려면 직접적인 비트 연산이 필요하며, 이는 매우 빠릅니다. 이 경우 해밍 거리는 <code>01010110</code>이며 비트 수는 4입니다. 따라서 점수 계산은 해당 해밍 거리의 역수가 됩니다. 유사한 벡터일수록 해밍 거리가 작아지므로 이를 반전시키면 유사한 벡터일수록 더 높은 점수를 받을 수 있습니다. 구체적으로 여기서는 1/4 = <code>0.25</code>가 됩니다.</p><p>그러나 각 차원의 크기가 어떻게 줄어드는지 주목하세요. <code>1</code> 은 <code>1</code>입니다. 그래서 <em>Q</em>의 경우, <code>0.01</code>과 <code>0.79</code> 사이의 차이점이 사라집니다. <code>&gt;0</code>에 따라 단순히 양자화하기 때문에 Q 벡터가 양자화되지 않은 곳에서 작은 트릭을 수행할 수 있습니다. 이렇게 하면 매우 빠른 비트 단위 연산을 할 수는 없지만, D가 여전히 양자화되어 있기 때문에 스토리지 비용을 낮게 유지할 수 있습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blted50315518e2d599/6a17f46c414c6463709452d3/508e8498ba969534d2a0131d431c75735fc27cb9-1399x611.png" alt="" /><p>간단히 말해서, 이는 <em>Q</em>에 제공된 정보를 유지하여 거리 추정 품질을 향상시키고 저장 공간을 최소화합니다.</p><p>비트 벡터를 사용하면 디스크 공간과 쿼리 시 계산 부하를 크게 줄일 수 있습니다. 하지만 할 수 있는 일은 더 많습니다.</p><h3>평균 벡터</h3><p>수십만 개의 문서에 걸쳐 검색을 확장하려면 비트 벡터가 제공하는 성능상의 이점만으로는 충분하지 않습니다. 이러한 유형의 워크로드에 맞게 확장하려면 벡터 검색을 위해 Elasticsearch의 HNSW 인덱스 구조를 활용해야 합니다.</p><p>ColPali는 문서당 약 천 개의 벡터를 생성하는데, 이는 HNSW 그래프에 추가하기에는 너무 많습니다. 따라서 벡터의 수를 줄여야 합니다. 이를 위해 ColPali에 의해 생성된 모든 문서 벡터의 평균을 계산하여 이미지를 임베드할 때 문서의 의미에 대한 단일 표현을 만들 수 있습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc053425fbfcf8de8/6a17f46f148009faf1b488aa/7c3b4dffb70bd95f67deb35f8c01e73c5286c2ab-1476x1102.png" alt="모든 지연 상호작용 벡터에 대한 평균 벡터" /><p>현재로서는 Elastic 자체 내에서 이 작업이 불가능하며, Elasticsearch에서 벡터를 수집하기 전에 벡터를 전처리해야 합니다. </p><p>Logstash 또는 수집 파이프라인으로 이 작업을 수행할 수 있지만 여기서는 간단한 Python 함수를 사용하겠습니다:</p>def to_avg_vector(vectors):
    vectors_array = np.array(vectors)
    
    avg_vector = np.mean(vectors_array, axis=0)
    
    norm = np.linalg.norm(avg_vector)
    if norm &gt; 0:
        normalized_avg_vector = avg_vector / norm
    else:
        normalized_avg_vector = avg_vector

    return normalized_avg_vector.tolist()<p>또한 내적 유사도를 사용할 수 있도록 벡터를 정규화하고 있습니다.</p><p>모든 ColPali 벡터를 평균 벡터로 변환한 후, 이를 dense_vector 필드에 인덱싱할 수 있습니다.</p>mappings = {
    "mappings": {
        "properties": {
            "avg_vector": {
                "type": "dense_vector",
                "dims": 128,
                "index": True,
                "similarity": "dot_product"
            },
            "col_pali_vectors": {
                "type": "rank_vectors",
                "element_type": "bit"
            }
        }
    }
}

es.indices.create(index=INDEX_NAME, body=mappings)<p>이로 인해 지연 상호작용 벡터와 함께 더 많은 정보를 저장하게 되므로 전체 디스크 사용량이 증가할 것이라는 점을 고려해야 합니다. 추가로, 수십억 개의 벡터에 대한 검색을 확장할 수 있도록 HNSW 그래프를 보유하기 위해 추가 RAM을 사용할 것입니다. RAM 사용량을 줄이기 위해 우리는 인기 있는 <a href="https://www.elastic.co/search-labs/blog/optimized-scalar-quantization-elasticsearch">BBQ 기능</a>을 활용할 수 있습니다. 그 결과, 기존 방식으로는 불가능했던 대규모 데이터 세트에 대한 빠른 검색 결과를 얻을 수 있습니다.</p><p>이제 knn 쿼리로 검색하면 가장 관련성 높은 문서를 찾을 수 있습니다.</p>query = "What do companies use for recruiting?"
query_vector = to_avg_vector(create_col_pali_query_vectors(query))
es_query = {
    "_source": False,
    "knn": {
        "field": "avg_vector",
        "query_vector": query_vector,
        "k": 10,
        "num_candidates": 100
    },
    "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltf4ac6b7fd444f935/6a17f471a29299d76ad02dc0/a500f9907020f032c3b1c7a48ed8c759dc2a1dd4-1600x498.png" alt="" /><p>불행히도 이전의 베스트 매칭은 3위로 떨어졌습니다.</p><p>이 문제를 해결하기 위해 다단계 검색을 수행할 수 있습니다. 첫 번째 단계에서는 knn 쿼리를 사용하여 수백만 개의 문서에서 쿼리에 가장 적합한 후보를 검색하고 있습니다. 두 번째 단계에서는 ColPali 지연 상호작용 벡터의 충실도가 높은 상위 k(여기서는 10)만 다시 순위를 매깁니다. </p>query = "What do companies use for recruiting?"
col_pali_vector = create_col_pali_query_vectors(query)
avg_vector = to_avg_vector(col_pali_vector)
es_query = {
  "_source": False,
  "retriever": {
    "rescorer": {
      "retriever": {
        "knn": {
          "field": "avg_vector",
          "query_vector": avg_vector,
          "k": 10,
          "num_candidates": 100
        }
      },
      "rescore": {
        "window_size": 10,
        "query": {
          "rescore_query": {
            "script_score": {
              "query": {
                "match_all": {}
              },
              "script": {
                "source": "maxSimDotProduct(params.query_vector, 'col_pali_vectors')",
                "params": {
                  "query_vector": col_pali_vector
                }
              }
            }
          }
        }
      }
    }
  },
  "size": 5
}<img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt265edd5f37be40b7/6a17f4733e9e45583dba15e6/797f490860af87fcf29f34668a5c4511419c6fd0-1600x501.png" alt="지연 상호작용 모델 최적화를 위해 평균 벡터를 사용한 결과" /><p>여기서는 8.18에서 도입된 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/8.18/retriever.html#rescorer-retriever">재점수 검색기</a>를 사용하여 결과를 다시 순위 지정합니다. 점수를 재지정한 후 다시 가장 좋은 매치가 첫 번째 위치에 있음을 확인합니다. </p><p>참고: 프로덕션 애플리케이션에서는 최대 시뮬레이션 함수가 여전히 비교적 성능이 좋으므로 10보다 훨씬 높은 k를 사용할 수 있습니다.</p><h3>토큰 풀링</h3><p>토큰 풀링은 중복 정보(예: 흰색 배경 패치)를 풀링하여 멀티 벡터 임베딩의 시퀀스 길이를 줄입니다. 이 기법은 페이지의 신호 대부분을 보존하면서 임베딩 수를 줄입니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3d643e6ac908f640/6a17f4754b055d3783432352/09eae0b768f4b450e555d7e53e57561bd52de2c0-1412x1056.png" alt="지연 상호작용 모델 최적화를 위한 토큰 풀링" /><p>토큰 풀링은 클러스터링 알고리즘을 사용하여 문서 내에서 유사한 토큰 임베딩을 클러스터로 그룹화하는 방식으로 작동합니다. 그런 다음, 각 클러스터 내 벡터의 평균을 계산하여 단일한 집계 표현을 생성합니다. 이 집계된 벡터는 그룹 내의 원래 토큰을 대체하여 문서 신호의 상당한 손실 없이 총 벡터 수를 줄입니다.</p><p>ColPali 논문에서는 대부분의 데이터 세트에 대해 초기 풀 팩터 값을 3으로 제안하고 있는데, 이는 원래 성능의 97.8%를 유지하면서 총 벡터 수를 66.7%로 줄입니다. </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2d78a15c6944a1ea/6a17f477414c64a2929452d9/343cc9eaf54af8c7a125d4115838f3c7d5659de0-1600x1007.png" alt="지연 상호작용 모델 최적화를 위한 풀 요소" /><p>그러나 주의해야 합니다. 매우 밀도가 높고 텍스트가 많으며 공백이 거의 없는 문서를 포함하는 "Shift" 데이터 세트는 풀 요소가 증가함에 따라 성능이 급격히 저하됩니다.</p><p>풀링된 벡터를 생성하려면 colpali_engine 라이브러리를 사용할 수 있습니다.</p>from colpali_engine.compression.token_pooling import HierarchicalTokenPooler

pooler = HierarchicalTokenPooler(pool_factor=3) # test on your data for a good pool_factor

def pool_vectors(embedding: list) -&gt; list:
    tensor = torch.tensor(embedding).unsqueeze(0)
    pooled = pooler.pool_embeddings(tensor)
    return pooled.squeeze(0).tolist()<p>이제 차원이 약 66.7% 감소한 벡터를 가지고 있습니다. 평소처럼 인덱싱하고 <code>maxSimDotProduct()</code> 함수로 검색할 수 있습니다.</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc460c14031814ede/6a17f4794202292bf629f72d/2412c5db7d79a590b96d42fe01f140c42f010612-1600x481.png" alt="지연 상호작용 모델 결과" /><p>검색 결과의 정확도가 약간 떨어지는 대신, 우수한 검색 결과를 얻을 수 있습니다.</p><p>힌트: pool_factor 값을 높이면(100~200) 평균 벡터 솔루션과 여기서 논의한 솔루션 사이의 중간 지점을 찾을 수도 있습니다. 문서당 약 5~10개의 벡터가 있을 때, 중첩된 필드에 인덱스를 만들어 HNSW 인덱스를 활용하는 것이 현실적이 됩니다.</p><h2>코스 인코더 vs. 지연 상호작용 vs. 바이 인코더</h2><p>지금까지 배운 바에 따르면, ColPali 또는 ColBERT와 같은 지연 상호작용 모델은 다른 AI 검색 기술과 비교할 때 어떤 위치에 있을까요?</p><p>최대 시뮬레이션 함수는 크로스 인코더에 비해 저렴하지만, 쿼리-문서 쌍마다 두 벡터를 비교하는 바이 인코더를 사용한 벡터 검색보다 여전히 더 많은 비교와 계산이 필요합니다. </p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltbfd97f3bba3e5b17/6a17f47be31791b0052d5943/75e1fc9e601aa7a6e88f137565c1919166c7a71c-1480x458.png" alt="코스 인코더 vs. 지연 상호작용 모델 vs. 바이 인코더" /><p>이러한 이유로, 지연 상호작용 모델은 일반적으로 상위 k 검색 결과의 순위를 재조정하는 데에만 사용하는 것을 권장합니다. 또한 이를 필드 유형 이름인 rank_vectors로 캡처합니다.</p><p>그렇다면 크로스 인코더는 어떨까요? 쿼리 시점에 실행 비용이 저렴하기 때문에 지연 상호작용 모델이 더 나은 것일까요? 종종 그렇듯이 답은 '상황에 따라 다르다'입니다. 크로스 인코더는 일반적으로 더 높은 품질의 결과를 생성하지만, 쿼리 문서 쌍이 트랜스포머 모델을 통해 완전한 패스를 수행해야 하기 때문에 많은 계산 자원이 필요합니다. 또한 벡터 인덱싱이 필요하지 않고 상태 비저장 방식으로 작동할 수 있다는 장점도 있습니다. 그 결과는 다음과 같습니다.</p><ul><li><p>디스크 공간 사용량 감소</p></li><li><p>더욱 간소화된 시스템</p></li><li><p>더 높은 검색 결과 품질</p></li><li><p>더 높은 대기 시간으로 인해 순위 재지정을 깊이 수행할 수 없음</p></li></ul><p>반면, 지연 상호작용 모델은 이 계산 일부를 인덱싱할 때 분산시켜 쿼리 비용을 낮출 수 있습니다. 그 대가로 벡터를 인덱싱해야 하므로 인덱스 파이프라인이 더 복잡해지고 이러한 벡터를 저장하는 데 더 많은 디스크 공간이 필요합니다.</p><p>특히 ColPali의 경우, 이미지에서 정보를 분석하는 것은 많은 데이터를 포함하기 때문에 매우 비용이 많이 듭니다. 이 경우 쿼리 시점에 이 정보를 평가하는 것은 너무 리소스 집약적이고 느리기 때문에 ColPali와 같은 후기 상호 작용 모델을 사용하는 것이 유리합니다. </p><p>ColBERT와 같은 지연 상호작용 모델의 경우, 대부분의 크로스 인코더(예: elastic-rerank-v1)처럼 텍스트 데이터를 기반으로 작동하기 때문에 디스크 공간 절약 및 간편성 측면에서 크로스 인코더를 사용하는 것이 더 유리할 수 있습니다.</p><p>사용 사례에 대한 장단점을 비교하고 Elasticsearch가 제공하는 다양한 도구를 실험하여 최고의 검색 애플리케이션을 구축하는 것이 좋습니다.</p><h2>결론</h2><p>이 블로그에서는 Elasticsearch에서 대규모 벡터 검색을 위한 ColPali와 같은 지연 상호작용 모델을 최적화하는 다양한 기술을 탐구했습니다. 지연 상호작용 모델은 검색 효율성과 순위 품질 사이에서 뛰어난 균형을 제공하지만, 저장 공간 및 계산과 관련된 문제점도 야기합니다.</p><p>이러한 과제를 해결하기 위해 다음을 살펴보았습니다.</p><ul><li><p><strong>비트 벡터</strong>를 사용하여 해밍 거리 또는 비대칭 최대 유사도와 같은 효율적인 유사도 계산을 활용하면서 디스크 공간을 크게 줄일 수 있습니다.</p></li><li><p>여러 임베딩을 하나의 밀집 표현으로 압축하기 위해 <strong>평균 벡터</strong>를 사용하여 HNSW 인덱싱을 통한 효율적인 검색을 가능하게 합니다.</p></li><li><p><strong>토큰 풀링</strong>을 통해 의미적 무결성을 유지관리하면서 중복된 임베딩을 지능적으로 병합하여 쿼리 시 계산 오버헤드를 줄입니다.</p></li></ul><p>Elasticsearch는 사용자의 요구에 따라 검색 애플리케이션을 맞춤 설정하고 최적화할 수 있는 강력한 툴킷을 제공합니다. 검색 속도, 순위 품질 또는 저장 공간 효율성 중 무엇을 우선시하든, 이러한 도구와 기술을 사용하면 실제 응용 분야에 필요한 성능과 품질의 균형을 맞출 수 있습니다.</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/late-interaction-model-colpali-scale</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/late-interaction-model-colpali-scale</guid>
    <category><![CDATA[정확도]]></category>
    <category><![CDATA[벡터 데이터베이스]]></category>
    <dc:creator><![CDATA[Peter Straßer,Benjamin Trent]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt97a536033e6b0a56/6a17f47dfbc5f88c86491c0d/c780b78a07573f2df1cfef8b29a7109f839b0ab3-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 20 Mar 2025 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>