Elastic
Jina AI
모델
API
keyboard_arrow_down
Reader
어떤 URL이든 Markdown으로 변환하여 LLM 그라운딩을 개선하세요.
Embeddings
멀티모달 및 다국어 임베딩.
Reranker
검색 관련성을 극대화하는 리랭커.
Elastic Inference Service
Jina 모델을 Elasticsearch에서 네이티브 방식으로 실행하세요.
MCP terminalCLIarticlellms.txtsmart_toy에이전트data_object스키마menu_book문서



로그인
login
긴 콘텐츠에서 스니펫 선택하기
다음 읽을 URL 순위 매기기
결론
기술 블로그
3월 12, 2025

DeepSearch/DeepResearch에서의 스니펫 선택과 URL 랭킹

긴 웹페이지에서 가장 적합한 스니펫을 선택하고 크롤링 전에 URL을 랭킹하는 이 두 가지 세부 사항을 구현하면 당신의 DeepSearch가 평범한 수준에서 최고의 수준으로 변모하게 됩니다.
Han Xiao • 11 분 소요
DeepSearch/DeepResearch 구현을 위한 실용 가이드
QPS는 퇴장하고, 깊이가 들어옵니다. DeepSearch가 새로운 표준입니다. read-search-reason 루프를 통해 답을 찾아보세요. 이것이 무엇이고 어떻게 구축하는지 알아보세요.
Jina AIHan Xiao

이미 DeepSearch/DeepResearch 구현 가이드를 읽으셨다면, 품질을 크게 개선할 수 있는 몇 가지 세부 사항을 더 자세히 살펴보겠습니다. 이 포스트에서는 두 가지 주요 과제에 초점을 맞추겠습니다: 긴 웹페이지에서 스니펫을 선택하기 위한 임베딩 활용과 크롤링할 URL의 우선순위를 정하기 위한 리랭커 사용입니다.

이전에 우리가 "임베딩은 STS 태스크(semantic textual similarity)와 같은 쿼리 중복 제거에만 유용했고, 리랭커는 원래 DeepSearch 구현에 포함되지도 않았다"고 결론 내렸던 것을 기억하실 수 있습니다. 하지만 두 가지 모두 여전히 상당히 가치가 있는 것으로 밝혀졌습니다 - 단지 일반적으로 예상하는 방식과는 다르게 말이죠. 우리는 항상 가능한 한 가장 간단한 경로를 따랐습니다. 임베딩과 리랭커 제공자로서 우리의 가치를 정당화하기 위해 구성 요소를 추가하지는 않았습니다. 우리는 검색이 기본적으로 진정으로 필요로 하는 것에 기반을 두고 있습니다.

몇 주간의 실험과 반복을 거친 후, DeepSearch/DeepResearch 시스템에서 두 가지를 모두 활용할 수 있는 독특하면서도 효과적인 방법을 발견했습니다. 이를 적용함으로써 Jina DeepSearch의 품질을 크게 개선했습니다(직접 사용해보세요). 이 분야에서 일하는 동료들과 이러한 통찰을 공유하고자 합니다.

tag긴 콘텐츠에서 스니펫 선택하기

문제는 이렇습니다: Jina Reader를 사용하여 웹페이지 콘텐츠를 읽은 후, 이를 에이전트의 컨텍스트에 지식 항목으로 추가해야 합니다. 전체 콘텐츠를 LLM의 컨텍스트 윈도우에 덤프하는 것이 가장 간단한 방법이지만, 토큰 비용과 생성 속도를 고려할 때 최적의 방법은 아닙니다. 실제로는 콘텐츠 중 질문과 가장 관련 있는 부분을 식별하여 해당 부분만 선택적으로 에이전트의 컨텍스트에 지식으로 추가해야 합니다.

💡
Jina Reader의 마크다운 정리 후에도 여전히 콘텐츠가 너무 긴 경우를 이야기하는 것입니다. 이는 GitHub 이슈, Reddit 스레드, 포럼 토론, 블로그 포스트(jina.ai/news의 많은 글 포함)와 같은 긴 페이지에서 자주 발생합니다.

LLM 기반 필터링은 동일한 비용과 지연 시간 문제가 있으므로, 더 작은 모델의 솔루션을 찾아보겠습니다: 더 작고 저렴하면서도 다국어를 지원하는 모델이 필요합니다 - 쿼리나 문서가 항상 영어일 것이라고 보장할 수 없기 때문에 이는 매우 중요한 요소입니다.

한쪽에는 질문이 있고(원래 쿼리나 gap 질문), 다른 쪽에는 대부분의 내용이 관련 없는 긴 마크다운 콘텐츠가 있습니다. 우리는 쿼리와 가장 관련 있는 스니펫을 선택해야 합니다. 이는 2023년부터 RAG 커뮤니티가 다뤄온 청킹 문제와 비슷합니다 - 요약을 위한 컨텍스트 윈도우에 배치할 관련 청크만을 retriever 모델을 사용하여 검색하는 것입니다. 하지만 우리의 경우 두 가지 중요한 차이점이 있습니다:

  1. 제한된 문서에서 나온 제한된 청크. 각 청크가 약 500개의 토큰을 포함한다고 가정할 때, 일반적인 긴 웹 문서는 약 200,000 토큰(p50)에서 1,000,000 토큰(p99)을 포함하고, 각 단계에서 Jina Reader로 4-5개의 URL을 가져오면 수백 개의 청크가 생성됩니다 - 즉 수백 개의 임베딩 벡터와 수백 개의 코사인 유사도를 의미합니다. 이는 벡터 데이터베이스 없이 인메모리 JavaScript로 쉽게 관리할 수 있습니다.
  2. 효과적인 지식 스니펫을 형성하기 위해서는 연속적인 청크가 필요합니다. [1-2, 6-7, 9, 14, 17, ...]와 같이 흩어진 문장들을 조합한 스니펫은 받아들일 수 없습니다. 더 유용한 지식 스니펫은 [3-15, 17-24, ...]와 같은 패턴을 따라야 합니다 - 항상 연속적인 텍스트를 유지해야 합니다. 이렇게 하면 LLM이 지식 소스에서 복사하고 인용하기가 더 쉬워지고 환각을 줄일 수 있습니다.

나머지는 실무자들이 불평했던 모든 주의사항입니다: 임베딩 모델이 긴 컨텍스트를 잘 처리하지 못하기 때문에 각 청크가 너무 길 수 없고; 청킹은 컨텍스트 손실을 초래하고 청크 임베딩을 i.i.d로 만들며; 가독성과 의미론을 모두 유지하는 최적의 경계 신호를 어떻게 찾을 것인가? 이러한 문제들에 대해 알고 있다면, RAG 구현에서 이러한 문제들로 고민해보셨을 것입니다.

하지만 긴 이야기를 짧게 하면 - late-chunking과 jina-embeddings-v3가 이 세 가지 문제를 모두 아름답게 해결합니다. Late chunking은 각 청크의 컨텍스트 정보를 유지하고, 경계 신호에 둔감하며, jina-embeddings-v3 자체가 비대칭 다국어 검색 태스크에서 SOTA입니다. 자세한 내용은 우리의 블로그 포스트나 논문을 참고하시면 되지만, 여기 전반적인 구현을 소개합니다.

이 다이어그램은 Conv1D와 유사하게 작동하는 스니펫 선택 알고리즘을 보여줍니다. 프로세스는 긴 문서를 고정 길이 청크로 분할하는 것으로 시작하여, late-chunking 토글이 켜진 jina-embeddings-v3로 임베딩합니다. 각 청크와 쿼리 간의 유사도 점수를 계산한 후, 슬라이딩 윈도우가 유사도 점수를 가로질러 이동하며 가장 높은 평균값을 가진 윈도우를 찾습니다.
Late Chunking이 실제로 무엇이고 무엇이 아닌지: 파트 II
Late Chunking에 대한 탐구의 파트 2로, 청크 임베딩과 검색/RAG 성능 향상을 위한 최고의 방법인 이유를 깊이 있게 살펴봅니다.
Jina AIHan Xiao
jina-embeddings-v3: Task LoRA를 사용한 다국어 임베딩
5억 7천만 개의 파라미터를 가진 새로운 텍스트 임베딩 모델인 jina-embeddings-v3를 소개합니다. 이 모델은 다국어 데이터와 긴 컨텍스트 검색 태스크에서 최고 수준의 성능을 달성하며, 최대 8192 토큰의 컨텍스트 길이를 지원합니다. 모델에는 쿼리-문서 검색, 클러스터링, 분류, 텍스트 매칭을 위한 고품질 임베딩을 생성하는 태스크별 Low-Rank Adaptation (LoRA) 어댑터가 포함되어 있습니다. MTEB 벤치마크 평가에서 jina-embeddings-v3는 영어 태스크에서 OpenAI와 Cohere의 최신 독점 임베딩을 능가하는 동시에, 모든 다국어 태스크에서 multilingual-e5-large-instruct보다 우수한 성능을 보여줍니다. 기본 출력 차원이 1024인 이 모델은 Matryoshka Representation Learning을 통해 성능 저하 없이 임베딩 차원을 32까지 유연하게 줄일 수 있습니다.
arXiv.orgSaba Sturua
Late Chunking: 긴 컨텍스트 임베딩 모델을 사용한 컨텍스트 청크 임베딩
많은 사용 사례에서 더 작은 텍스트 부분을 검색해야 하며, 밀집 벡터 기반 검색 시스템은 의미론이 임베딩에서 과도하게 압축될 가능성이 낮기 때문에 더 짧은 텍스트 세그먼트에서 더 나은 성능을 보입니다. 따라서 실무자들은 종종 텍스트 문서를 더 작은 청크로 분할하여 별도로 인코딩합니다. 그러나 이러한 방식으로 생성된 청크 임베딩은 주변 청크의 컨텍스트 정보를 잃을 수 있어 최적의 표현이 되지 못합니다. 이 논문에서는 late chunking이라는 새로운 방법을 소개합니다. 이 방법은 긴 컨텍스트 임베딩 모델을 활용하여 먼저 긴 텍스트의 모든 토큰을 임베딩하고, transformer 모델 이후와 mean pooling 직전에 청킹을 적용합니다 - 이것이 'late'라는 이름의 유래입니다. 결과적으로 생성된 청크 임베딩은 전체 컨텍스트 정보를 포착하여 다양한 검색 태스크에서 우수한 결과를 보여줍니다. 이 방법은 추가 훈련 없이도 광범위한 긴 컨텍스트 임베딩 모델에 적용될 수 있을 만큼 일반적입니다. late chunking의 효과를 더욱 높이기 위해, 임베딩 모델을 위한 전용 미세 조정 접근 방식도 제안합니다.
arXiv.orgMichael Günther
function cherryPick(question, longContext, options) {
  if (longContext.length < options.snippetLength * options.numSnippets)
    return longContext;
  
  const chunks = splitIntoChunks(longContext, options.chunkSize);
  
  const chunkEmbeddings = getEmbeddings(chunks, "retrieval.passage");
  const questionEmbedding = getEmbeddings([question], "retrieval.query")[0];
  
  const similarities = chunkEmbeddings.map(embed => 
    cosineSimilarity(questionEmbedding, embed));
  
  const chunksPerSnippet = Math.ceil(options.snippetLength / options.chunkSize);
  const snippets = [];
  const similaritiesCopy = [...similarities];
  
  for (let i = 0; i < options.numSnippets; i++) {
    let bestStartIndex = 0;
    let bestScore = -Infinity;
    
    for (let j = 0; j <= similarities.length - chunksPerSnippet; j++) {
      const windowScores = similaritiesCopy.slice(j, j + chunksPerSnippet);
      const windowScore = average(windowScores);
      
      if (windowScore > bestScore) {
        bestScore = windowScore;
        bestStartIndex = j;
      }
    }
    
    const startIndex = bestStartIndex * options.chunkSize;
    const endIndex = Math.min(startIndex + options.snippetLength, longContext.length);
    snippets.push(longContext.substring(startIndex, endIndex));
    
    for (let k = bestStartIndex; k < bestStartIndex + chunksPerSnippet; k++)
      similaritiesCopy[k] = -Infinity;
  }
  
  return snippets.join("\n\n");
}

질문에 대한 최적의 스니펫을 선택하기 위해 late chunking과 Conv1D와 유사한 평균 풀링을 사용합니다.

Jina Embeddings API를 호출할 때 retrieval task,late_chunking 및 truncate를 아래와 같이 설정하세요:

await axios.post(
  'https://api.jina.ai/v1/embeddings',
  {
    model: "jina-embeddings-v3",
    task: "retrieval.passage",
    late_chunking: true,
    input: chunks,
    truncate: true
  }, 
  { headers }); 

질문 임베딩의 경우 task를 retrieval.query로 변경하고 late_chunking을 비활성화하세요

전체 구현은 Github에서 확인할 수 있습니다:

node-DeepResearch/src/tools/jina-latechunk.ts at main · jina-ai/node-DeepResearch
답을 찾을 때까지(또는 토큰 예산을 초과할 때까지) 계속 검색하고, 웹페이지를 읽고, 추론합니다 - jina-ai/node-DeepResearch
GitHubjina-ai

tag다음 읽을 URL 순위 매기기

문제는 다음과 같습니다: DeepSearch 세션 동안 검색 엔진 결과 페이지(SERP)에서 많은 URL을 수집하고 개별 웹페이지를 읽을 때마다 더 많은 URL을 발견하게 됩니다(페이지 내 링크들). 고유 URL의 총 개수는 쉽게 수백 개에 도달할 수 있습니다. 다시 말하지만, 모든 URL을 직접 LLM의 컨텍스트에 덤프하는 것은 비효율적입니다 - 귀중한 컨텍스트 윈도우 공간을 낭비하고 더 문제가 되는 것은, LLM이 본질적으로 무작위로 URL을 선택한다는 것을 발견했습니다. 필요한 답변을 포함할 가능성이 가장 높은 URL로 LLM을 안내하는 것이 중요합니다.

curl https://r.jina.ai/https://example.com \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -H "X-Retain-Images: none" \
  -H "X-Md-Link-Style: discarded" \
  -H "X-Timeout: 20" \
  -H "X-With-Links-Summary: all"

DeepSearch에서 Jina Reader를 사용하여 페이지를 크롤링하는 최선의 옵션입니다. 이는 모든 페이지 내 링크를 별도의 links 필드에 수집하고, content 필드에서 제거합니다.

이 문제를 세션 중에 수백 개의 URL의 가중치를 매겨야 하는 컨텍스트 내 PageRank로 생각해보세요. 우리는 마지막 업데이트 시간, 도메인 빈도, 경로 구조, 그리고 가장 중요하게는 쿼리에 대한 의미적 관련성을 결합하여 복합 점수를 만들어 URL의 순위를 매깁니다. URL을 실제로 방문하기 전에 사용할 수 있는 정보만 사용할 수 있다는 것을 기억하세요:

빈도 신호: 여러 소스에서 여러 번 나타나는 URL은 추가 가중치를 받습니다. 검색 결과에서 자주 나타나는 도메인의 URL은 부스트를 받습니다. 인기 있는 도메인은 종종 권위 있는 콘텐츠를 포함하기 때문입니다.

경로 구조: URL 경로를 분석하여 콘텐츠 클러스터를 식별합니다. 공통 경로 계층 구조 내의 URL은 더 높은 점수를 받으며, 더 깊은 경로에는 감쇠 요소가 적용됩니다.

의미적 관련성: jina-reranker-v2-base-multilingual를 사용하여 질문과 각 URL의 텍스트 정보 간의 의미적 관련성을 평가합니다. 이는 전형적인 재순위화 문제입니다. 각 URL의 텍스트 정보는 다음에서 가져옵니다:

  • SERP API 결과의 제목 및 스니펫 (https://s.jina.ai/에 'X-Respond-With': 'no-content' 사용)
  • 페이지 내 URL의 앵커 텍스트 (https://r.jina.ai에 'X-With-Links-Summary': 'all' 사용)

마지막 업데이트 시간: 일부 DeepSearch 쿼리는 시간에 민감하므로, 최근에 업데이트된 URL이 오래된 URL보다 더 가치가 있습니다. Google과 같은 주요 검색 엔진이 아닌 경우, 마지막 업데이트 시간을 신뢰성 있게 결정하는 것은 어렵습니다. 다음 신호를 결합하여 필요할 때 최신 콘텐츠를 우선시하는 신뢰도가 있는 타임스탬프를 제공하는 다층적 접근 방식을 구현했습니다.

  • SERP API 필터 (s.jina.ai의 최신성 필터링을 위한 tbs 파라미터와 같은)
  • HTTP 헤더 분석 (Last-Modified, ETag)
  • 메타데이터 추출 (메타 태그, Schema.org 타임스탬프)
  • 콘텐츠 패턴 인식 (HTML의 가시적 날짜)
  • WordPress, Drupal, Ghost와 같은 플랫폼의 CMS 특정 지표

제한된 콘텐츠: 소셜 미디어 플랫폼의 일부 콘텐츠는 제한되어 있거나 단순히 유료 콘텐츠이며, 로그인하거나 ToS를 위반하지 않고는 이 콘텐츠에 접근할 정당한 방법이 없습니다. 접근할 수 없는 콘텐츠에 시간을 낭비하는 것을 방지하기 위해 문제가 있는 URL과 호스트 이름 목록을 적극적으로 유지하여 순위를 낮춰야 합니다.

도메인 다양성: 일부 경우에는 가장 높은 가중치의 URL이 모두 동일한 호스트 이름에서 나옵니다. 이는 DeepSearch를 지역 최적점에 가두고 결과의 최종 품질을 저하시킬 수 있습니다. 위의 예시에서 모든 상위 URL이 StackOverflow에서 나온 것을 확인하세요. 다양성을 개선하기 위해 각 호스트 이름에서 상위 k개의 높은 순위 URL을 선택하는 탐색-활용 접근 방식을 구현할 수 있습니다.

URL 순위 매기기의 전체 구현은 우리의 Github에서 찾을 수 있습니다.

node-DeepResearch/src/utils/url-tools.ts at main · jina-ai/node-DeepResearch
답을 찾을 때까지(또는 토큰 예산을 초과할 때까지) 계속 검색하고, 웹페이지를 읽고, 추론합니다 - jina-ai/node-DeepResearch
GitHubjina-ai
<action-visit>
- Crawl and read full content from URLs, you can get the fulltext, last updated datetime etc of any URL.  
- Must check URLs mentioned in <question> if any
- Choose and visit relevant URLs below for more knowledge. higher weight suggests more relevant:
<url-list>
  + weight: 0.20 "https://huggingface.co/docs/datasets/en/loading": "Load - Hugging FaceThis saves time because instead of waiting for the Dataset builder download to time out, Datasets will look directly in the cache. Set the environment ...Some datasets may have more than one version based on Git tags, branches, or commits. Use the revision parameter to specify the dataset version you want to load ..."
  + weight: 0.20 "https://huggingface.co/docs/datasets/en/index": "Datasets - Hugging Face🤗 Datasets is a library for easily accessing and sharing datasets for Audio, Computer Vision, and Natural Language Processing (NLP) tasks. Load a dataset in a ..."
  + weight: 0.17 "https://github.com/huggingface/datasets/issues/7175": "[FSTimeoutError] load_dataset · Issue #7175 · huggingface/datasetsWhen using load_dataset to load HuggingFaceM4/VQAv2, I am getting FSTimeoutError. Error TimeoutError: The above exception was the direct cause of the following ..."
  + weight: 0.15 "https://github.com/huggingface/datasets/issues/6465": "`load_dataset` uses out-of-date cache instead of re-downloading a ...When a dataset is updated on the hub, using load_dataset will load the locally cached dataset instead of re-downloading the updated dataset."
  + weight: 0.12 "https://stackoverflow.com/questions/76923802/hugging-face-http-request-on-data-from-parquet-format-when-the-only-way-to-get-i": "Hugging face HTTP request on data from parquet format when the ...I've had to get the data from their data viewer using the parquet option. But when I try to run it, there is some sort of HTTP error. I've tried downloading ..."
</url-list>
</action-visit>

URL 가중치를 에이전트의 컨텍스트에 포함시키고 LLM이 가중치를 준수하도록 지시하는 것을 잊지 마세요.

tag결론

2025년 2월 2일 DeepSearch 시스템 출시 이후,우리는 품질을 크게 향상시킨 두 가지 구현 세부사항을 발견했습니다. 놀랍게도,두 가지 모두 다국어 임베딩과 리랭커를 "인-컨텍스트" 방식으로 활용합니다 - 이러한 모델들이 일반적으로 필요로 하는 기존의 사전 계산된 인덱스보다 훨씬 작은 규모로 작동합니다. 이것이 우리가 처음에 간과했던 이유를 설명합니다.

이는 검색 기술의 미래가 흥미롭게 양극화될 것임을 시사합니다. Kahneman의 이중 프로세스 이론과 유사한 프레임워크를 고려해보세요:

  • Fast-think (grep,BM25,SQL): 최소한의 계산 요구사항으로 빠르고 규칙에 기반한 패턴 매칭.
  • Slow-think (LLM): 상당한 계산이 필요한 깊은 맥락 이해를 통한 포괄적 추론.
  • Mid-think (임베딩,리랭커): 중간 단계에 갇혀있나요? 단순 패턴 매칭에는 너무 "고급스럽고" 의미론적이지만 진정한 추론 능력은 부족합니다.

우리는 경량화되고 효율적인 SQL/BM25가 초기 콘텐츠 검색을 처리하고 이를 깊은 처리를 위해 강력한 LLM에 직접 전달하는 이분화된 아키텍처의 인기를 목격하고 있을 수 있습니다. 이러한 LLM들은 이전에 특수한 중간 수준 모델을 필요로 했던 의미론적 기능들을 점점 더 통합하고 있습니다. Mid-think 모델의 남은 역할은 필터링,중복 제거,그리고 완전한 추론이 비효율적일 수 있는 제한된 범위의 작업과 같은 특수한 인-컨텍스트 작업으로 이동하고 있습니다.

그럼에도 불구하고,중요한 스니펫을 선택하고 URL을 순위 매기는 것은 DeepSearch/DeepResearch 시스템 품질에 직접적인 영향을 미치는 기본 구성 요소로 남아 있습니다. 우리의 통찰이 여러분의 구현에도 개선을 가져오기를 바랍니다.

쿼리 확장은 계속해서 또 다른 중요한 품질 결정 요소입니다. 우리는 기본적인 프롬프트 기반 재작성부터 작은 언어 모델과 추론 기반 방법에 이르기까지 다양한 접근 방식을 적극적으로 평가하고 있습니다. 이에 대한 향후 연구 결과를 곧 확인하실 수 있습니다. 계속 지켜봐 주세요.

범주:
기술 블로그
rss_feed

자세히 보기
3월 11, 2026 • 7 분 소요
멀티모달 LLM 을 활용한 오디오 임베딩 부트스트래핑
Han Xiao
Abstract illustration of a sound wave or heartbeat, formed by blue, orange, and gray dots on a white background.
3월 06, 2026 • 6 분 소요
원시 수치 값에서 임베딩 모델 식별하기
Han Xiao
Fingerprint illustration made from numbers, showcasing digital and high-tech design on a light background.
9월 09, 2025 • 11 분 소요
Llama.cpp 및 GGUF의 멀티모달 向量模型
Andrei Ungureanu
Alex C-G
Cartoon llama in the center of a white background, emitting laser-like beams from its eyes. The illustration creates a playfu
현재 언어 / 테마
Search Foundation
Reader
Embeddings
Reranker
Jina API 키 받기
속도 제한
회사 소개
소식
Jina 로고 다운로드
open_in_new
Elastic 로고 다운로드
open_in_new
API 상태
Elastic © 2026.보안이용약관개인정보 보호쿠키 관리제 개인 정보를 판매하거나 공유하지 마세요.
본 웹사이트 및 관련 콘텐츠, 소프트웨어, 제품, 서비스는 전문가용으로만 제작되었습니다. 일반 소비자를 위한 것이 아니며, 소비자의 사용을 권장하지 않습니다.