<!DOCTYPE html>
    <html lang="vi" xmlns="http://www.w3.org/1999/xhtml" prefix="og: http://ogp.me/ns#">
    <head>
<title>Cách xây dựng Knowledge Base hiệu quả cho AI Models</title>
<meta name="description" content="Cách xây dựng Knowledge Base hiệu quả cho AI Models - Savefile - Tin Tức -...">
<meta name="author" content=".: Nguoicodonvn2008.info - Cõi lòng người cô đơn :.">
<meta name="copyright" content=".: Nguoicodonvn2008.info - Cõi lòng người cô đơn :. [admin@nguoicodonvn2008.info]">
<meta name="robots" content="index, archive, follow, noodp">
<meta name="googlebot" content="index,archive,follow,noodp">
<meta name="msnbot" content="all,index,follow">
<meta name="generator" content="NukeViet v4.5">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta property="og:title" content="Cách xây dựng Knowledge Base hiệu quả cho AI Models">
<meta property="og:type" content="website">
<meta property="og:description" content="Savefile - Tin Tức - https&#x3A;&#x002F;&#x002F;www.nguoicodonvn2008.info&#x002F;vi&#x002F;news&#x002F;savefile&#x002F;kien-thuc-may-tinh&#x002F;cach-xay-dung-knowledge-base-hieu-qua-cho-ai-models-12848.html">
<meta property="og:site_name" content=".&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.">
<meta property="og:url" content="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-xay-dung-knowledge-base-hieu-qua-cho-ai-models-12848.html">
<link rel="shortcut icon" href="https://nguoicodonvn2008.info/favicon.ico">
<link rel="canonical" href="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-xay-dung-knowledge-base-hieu-qua-cho-ai-models-12848.html">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/" title="Tin Tức" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/karaoke-dual/" title="Tin Tức - Karaoke Dual" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/nhac-tre/" title="Tin Tức - Nhạc trẻ" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tru-tinh/" title="Tin Tức - Trữ tình" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/nuoc-ngoai/" title="Tin Tức - Nước ngoài" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/remix/" title="Tin Tức - Remix" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tam-su-tinh-yeu/" title="Tin Tức - Tâm sự tình yêu" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tho-suu-tam/" title="Tin Tức - Thơ sưu tầm" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/cuoc-song/" title="Tin Tức - Cuộc sống" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/phan-mem/" title="Tin Tức - Phần mềm" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/kien-thuc-may-tinh/" title="Tin Tức - Kiến thức máy tính" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/hoc-tap/" title="Tin Tức - Học tập" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/tai-lieu/" title="Tin Tức - Tài liệu" type="application/rss+xml">
<link rel="alternate" href="https://nguoicodonvn2008.info/vi/news/rss/de-thi/" title="Tin Tức - Đề thi" type="application/rss+xml">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/assets/css/font-awesome.min.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/bootstrap.non-responsive.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/style.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/style.non-responsive.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/news.css" type="text/css">
<link rel="preload" as="style" href="https://nguoicodonvn2008.info/themes/default/css/custom.css" type="text/css">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/jquery/jquery.min.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/language/vi.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/DOMPurify/purify3.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/global.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/assets/js/site.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/news.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/main.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/custom.js" type="text/javascript">
<link rel="preload" as="script" href="https://nguoicodonvn2008.info/themes/default/js/bootstrap.min.js" type="text/javascript">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/assets/css/font-awesome.min.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/bootstrap.non-responsive.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/style.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/style.non-responsive.css">
<link rel="StyleSheet" href="https://nguoicodonvn2008.info/themes/default/css/news.css">
<link rel="stylesheet" href="https://nguoicodonvn2008.info/themes/default/css/custom.css">
<style type="text/css">
	body{background: #fff;}
</style>
    </head>
    <body>
<div id="print">
	<div id="hd_print">
		<h2 class="pull-left">.&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.</h2>
		<p class="pull-right"><a title=".&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;." href="https://nguoicodonvn2008.info/">https://nguoicodonvn2008.info</a></p>
	</div>
	<div class="clear"></div>
	<hr />
	<div id="content">
		<h1>Cách xây dựng Knowledge Base hiệu quả cho AI Models</h1>
		<ul class="list-inline">
			<li>Thứ năm - 14/05/2026 23:08</li>
			<li class="hidden-print txtrequired"><em class="fa fa-print">&nbsp;</em><a title="In ra" href="javascript:;" onclick="window.print()">In ra</a></li>
			<li class="hidden-print txtrequired"><em class="fa fa-power-off">&nbsp;</em><a title="Đóng cửa sổ này" href="javascript:;" onclick="window.close()">Đóng cửa sổ này</a></li>
		</ul>
		<div class="clear"></div>
		<div id="hometext">
		</div>
				<div class="imghome">
			<img alt="Cách xây dựng Knowledge Base hiệu quả cho AI Models" src="https://st.quantrimang.com/photos/image/2026/05/08/meo-bien-openai-codex-thanh-ai-coding-agent-manh-me200-size-80x80-znd.jpg" width="460" class="img-thumbnail" />
		</div>
		<div class="clear"></div>
		<div id="bodytext" class="clearfix">
			<p style="text-align:justify;">AI chỉ mạnh khi nền tảng tri thức phía sau đủ tốt. Một knowledge base được xây dựng bài bản không chỉ giúp mô hình trả lời chính xác hơn mà còn cải thiện đáng kể tốc độ phản hồi — hai điểm yếu mà nhiều AI hiện nay vẫn gặp phải. Theo một nghiên cứu gần đây, nhiều chatbot AI lớn hiện vẫn trả lời sai gần một nửa số truy vấn người dùng đưa ra.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Chính vì vậy, việc xây dựng knowledge base không còn là một phần “phụ trợ”, mà gần như là yếu tố quyết định chất lượng của toàn bộ hệ thống AI.</p><h2 style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:20px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;letter-spacing:normal;line-height:32px;margin:10px 0px;orphans:2;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><strong>1. Bắt đầu từ dữ liệu phù hợp, không phải dữ liệu thật nhiều</strong></h2><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Một trong những sai lầm phổ biến nhất khi xây knowledge base là cho rằng càng nhiều dữ liệu thì AI càng thông minh. Thực tế, điều này rất dễ dẫn tới tình trạng “garbage in, garbage out” — dữ liệu kém chất lượng sẽ tạo ra kết quả kém chất lượng.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Điều quan trọng không phải số lượng, mà là độ liên quan của dữ liệu với mục tiêu hệ thống. Một knowledge base tốt thường chỉ tập trung vào những nội dung AI thực sự cần để trả lời đúng.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Ví dụ, nếu đang xây chatbot hỗ trợ khách hàng, hệ thống có thể chỉ cần tài liệu chính sách công ty, quy trình xử lý sự cố hoặc hướng dẫn sử dụng sản phẩm. Điều này giúp AI không “bịa” thêm thông tin ngoài phạm vi cho phép.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Lưu ý rằng hiện có xu hướng dùng dữ liệu do AI tạo ra để xây knowledge base cho AI khác. Cách này giúp tăng tốc rất nhanh, nhưng cũng tiềm ẩn rủi ro vì nội dung có thể chứa lỗi, thông tin thừa hoặc diễn đạt quá dài dòng. Vì vậy, mọi dữ liệu AI-generated đều nên được kiểm tra lại trước khi đưa vào hệ thống.</p><h2 style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:20px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;letter-spacing:normal;line-height:32px;margin:10px 0px;orphans:2;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><strong>2. Làm sạch và chia nhỏ dữ liệu là bước cực kỳ quan trọng</strong></h2><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Sau khi thu thập dữ liệu, bước tiếp theo là làm sạch nội dung. Quá trình này thường bao gồm việc xóa dữ liệu trùng lặp, loại bỏ thông tin lỗi thời, đồng thời chuẩn hóa thuật ngữ và định dạng để toàn bộ knowledge base có tính nhất quán.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Sau đó, dữ liệu sẽ được chia thành các “chunk” nhỏ. Mỗi chunk chỉ nên chứa một ý hoặc một chủ đề rõ ràng để AI dễ tìm kiếm và truy xuất hơn.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Bạn nên chia chunk theo kiểu câu hỏi người dùng thực tế thay vì chia theo cấu trúc tài liệu truyền thống. Ví dụ, thay vì chia theo “Chương quản lý tài khoản”, có thể tách thành các nội dung như:<br />“Làm sao đổi mật khẩu?” hoặc “Chính sách mật khẩu là gì?”.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Cách tiếp cận này giúp AI phản hồi gần với nhu cầu thật của người dùng hơn rất nhiều.</p><h2 style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:20px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;letter-spacing:normal;line-height:32px;margin:10px 0px;orphans:2;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><strong>3. Metadata và vector hóa giúp AI “hiểu” dữ liệu nhanh hơn</strong></h2><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Sau khi dữ liệu được chia nhỏ, mỗi chunk thường sẽ được gắn thêm metadata như nguồn dữ liệu, chủ đề, ngày cập nhật hoặc quyền truy cập. Metadata giúp hệ thống lọc và tìm đúng nội dung nhanh hơn thay vì phải quét toàn bộ knowledge base.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Tiếp theo, văn bản sẽ được chuyển thành vector thông qua embedding model như OpenAI v3-Large hoặc BGE-M3. Đây là bước rất quan trọng vì AI xử lý vector nhanh hơn nhiều so với văn bản thô.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Một chunk hoàn chỉnh thường sẽ bao gồm:</p><ul style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;clear:both;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:inherit;list-style:disc;margin-bottom:0px;margin-right:0px;margin-top:0px;orphans:2;padding:0px;text-align:start;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><li style="border-width:0px;font:inherit;margin:0px 0px 0px 30px;padding:0px;" data-list-item-id="ee2473785800650d76596da591c57ad15"><p style="margin-left:0px;text-align:justify;">Vector embedding</p></li><li style="border-width:0px;font:inherit;margin:0px 0px 0px 30px;padding:0px;" data-list-item-id="ea837d652b46269b9febba39f4e0d1ca5"><p style="margin-left:0px;text-align:justify;">Nội dung gốc</p></li><li style="border-width:0px;font:inherit;margin:0px 0px 0px 30px;padding:0px;" data-list-item-id="e2abfd457bb54322e0b322162df7fffbf"><p style="margin-left:0px;text-align:justify;">Metadata đi kèm</p></li></ul><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Đây cũng là nền tảng của hầu hết hệ thống RAG hiện nay.</p><h2 style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:20px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;letter-spacing:normal;line-height:32px;margin:10px 0px;orphans:2;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><strong>4. Chọn đúng vector database và tối ưu retrieval</strong></h2><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Sau khi vector hóa, dữ liệu thường được lưu trong các vector database như Pinecone, Milvus hoặc Weaviate. Những hệ thống này được thiết kế riêng để truy xuất vector theo ngữ nghĩa. Bạn có thể tải lên dữ liệu vector bằng cách viết một đoạn mã Python đơn giản.</p><div class="codebar" style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:inherit;margin:0px;orphans:2;padding:0px;position:relative;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">&nbsp;</div><pre class="language-python prettyprint hljs" style="-webkit-text-stroke-width:0px;background-color:rgb(254, 255, 239);border-radius:5px;border:1px solid !important;color:rgba(0, 0, 0, 0.87);display:block;font-family:Consolas, Monaco, monospace;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:14px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:inherit;margin:0px 0px 16px;max-height:600px;max-width:100%;orphans:2;overflow:auto;padding:8px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;widows:2;word-spacing:0px;" id="pre0">  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> math
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> time
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> json
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> dataclasses <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> dataclass, field
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> typing <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> <span class="hljs-type" style="border-width:0px;font:inherit;margin:0px;padding:0px;">Any</span>

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> numpy <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">as</span> np
  <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Vector Normalization + Metadata</span>

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">normalize_l2</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">vector: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>&#93;:
    <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
    Return an L2-normalized copy of `vec`.
    Many vector stores use dot-product similarity. If you normalize vectors to
    unit length, dot-product becomes equivalent to cosine similarity.
    &quot;&quot;&quot;</span>
      arr = np.array(vector, dtype=np.float32)
      norm = np.linalg.norm(arr)
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> norm == <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>:
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> vector
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> (arr / norm).tolist()
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">prepare_record</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
      doc_id: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      embedding: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;,
      text: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      source: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      extra_metadata: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, </span><span class="hljs-params hljs-type" style="border-width:0px;font:inherit;margin:0px;padding:0px;">Any</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93; | </span><span class="hljs-params hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">None</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">None</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
  </span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
      Prepare a single record for vector DB upsert.
      Metadata serves two purposes:
      - Filtering: narrow down search to a subset
      &quot;&quot;&quot;</span>
      metadata = {
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;source&quot;</span>: source,
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;text_preview&quot;</span>: text&#91;:<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">500</span>&#93;,
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;char_count&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(text),
      }
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> extra_metadata:
          metadata.update(extra_metadata)

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> {
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;id&quot;</span>: doc_id,
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;values&quot;</span>: normalize_l2(embedding),
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;metadata&quot;</span>: metadata,
      }
<span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Vector Quantization</span>

  <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Scalar Quantization / SQ</span>

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">scalar_quantization</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">input_vec</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
      This funtion demonstrates 
        how to compress float32 input_vec to uint8
      &quot;&quot;&quot;</span>
      input_arr = np.array(input_vec, dtype=np.float32)
      <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">min</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">max</span> = input_arr.<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">min</span>(), input_arr.<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">max</span>()
      <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">range</span> = (<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">max</span> - <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">min</span>)
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">range</span> == <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>:
          quantized = np.zeros_like(arr, dtype=np.uint8)
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">else</span>:
          quantized = ((input_arr - <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">min</span>) / <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">range</span> * <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">255</span>).astype(np.uint8)

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> {
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;quantized&quot;</span>: quantized.tolist(),
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;min&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>(<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">min</span>),
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;max&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>(<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">max</span>),
      }
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">scalar_dequantization</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">record: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>&#93;:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
      You can Reconstruct the original vector 
        by approximate float32 vector from uint8.
      &quot;&quot;&quot;</span>
      arr = np.array(record&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;quantized&quot;</span>&#93;, dtype=np.float32)
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> (arr / <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">255</span> * (record&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;max&quot;</span>&#93; - record&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;min&quot;</span>&#93;) + record&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;min&quot;</span>&#93;).tolist()
  <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Product Quantization / PQ</span>

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">train_product_quantizer</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> vectors, num_subvectors: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">8</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, num_centroids: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">256</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, max_iterations: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">20</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
      This function demonstrates 
        split vector into subvectors, cluster each independently
      &quot;&quot;&quot;</span>
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> sklearn.cluster <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> KMeans

      dim = vectors.shape&#91;<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>&#93;
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">assert</span> dim % num_subvectors == <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>, <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;dim must be divisible by num_subvectors&quot;</span>
      sub_dim = dim // num_subvectors

      codebooks = &#91;&#93;
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> i <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">range</span>(num_subvectors):
          sub_vectors = vectors&#91;:, i * sub_dim : (i + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>) * sub_dim&#93;
          kmeans = KMeans(n_clusters=num_centroids, max_iter=max_iterations, n_init=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>)
          kmeans.fit(sub_vectors)
          codebooks.append(kmeans.cluster_centers_)

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> codebooks
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">pq_encode</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">vector: np.ndarray, codebooks: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;np.ndarray&#93;</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span>&#93;:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
      Encode a single vector into PQ codes (one uint8 per subvector)
      &quot;&quot;&quot;</span>
      num_subvectors = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(codebooks)
      sub_dim = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(vector) // num_subvectors
      codes = &#91;&#93;

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> i, codebook <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">enumerate</span>(codebooks):
          sub_vec = vector&#91;i * sub_dim : (i + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>) * sub_dim&#93;
          distances = np.linalg.norm(codebook - sub_vec, axis=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>)
          codes.append(<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span>(np.argmin(distances)))

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> codes
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">pq_decode</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">codes: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;, codebooks: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;np.ndarray&#93;</span>) -&gt; np.ndarray:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
      Reconstruct approximate vector from PQ codes
      &quot;&quot;&quot;</span>
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> np.concatenate(
        &#91;codebook&#91;code&#93; <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> code, codebook <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">zip</span>(codes, codebooks)&#93;
      )</pre><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Nhiều developer thường chỉ tập trung “làm cho chạy được” mà quên tối ưu retrieval. Trong khi thực tế, người dùng không chỉ muốn AI trả lời đúng mà còn muốn phản hồi gần như ngay lập tức.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Để truy xuất dữ liệu từ cơ sở dữ liệu vector, bạn có thể sử dụng các framework điều phối như LlamaIndex và LangChain.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">LlamaIndex có thể duyệt qua cơ sở dữ liệu vector nhanh hơn và tìm đến chính xác đoạn dữ liệu chứa nội dung liên quan đến truy vấn của người dùng.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Sau đó, LangChain sẽ lấy dữ liệu từ đoạn đó và chuyển đổi nó theo truy vấn của người dùng. Ví dụ: tóm tắt văn bản hoặc viết email từ dữ liệu đó.</p><div class="codebar" style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:inherit;margin:0px;orphans:2;padding:0px;position:relative;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">&nbsp;</div><pre class="language-python prettyprint hljs" style="-webkit-text-stroke-width:0px;background-color:rgb(254, 255, 239);border-radius:5px;border:1px solid !important;color:rgba(0, 0, 0, 0.87);display:block;font-family:Consolas, Monaco, monospace;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:14px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:inherit;margin:0px 0px 16px;max-height:600px;max-width:100%;orphans:2;overflow:auto;padding:8px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;widows:2;word-spacing:0px;" id="pre1"><span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;                                                                                                                             
  Hybrid Retrieval: Take benefits from both keyword search and vector similarity                                                     
  Where each approach shines:                                                                                  
  - Keywords: looks for exact matches, but will miss searches with synonym
  - Embeddings: has advantage of capturing the meaning, but there is possibility of missing exact keyword
  Hybrid is a combination of both to get the best of each.
  &quot;&quot;&quot;</span>

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> math
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> collections <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> defaultdict
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> dataclasses <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> dataclass
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> numpy <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">as</span> np

<span class="hljs-meta" style="border-width:0px;font:inherit;margin:0px;padding:0px;">  @dataclass</span>
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">class</span> <span class="hljs-title class_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">Document</span>:
      <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">id</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>
      text: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>
      embedding: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>&#93;
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">class</span> <span class="hljs-title class_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">BestMatching25Index</span>:
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">__init__</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, k1: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1.5</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, b: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.75</span>):
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Here k1 is the term frequency saturation limit </span>
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># and b is length of normalization</span>
          self.k1 = k1
          self.b = b
          self.doc_lengths: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span>&#93; = {}
          self.avg_doc_length: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span> = <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>
          self.doc_freqs: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span>&#93; = {} 
          self.term_freqs: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span>&#93;&#93; = {} 
          self.corpus_size: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span> = <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">_tokenize</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, text: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>&#93;:
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> text.lower().split()

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">index</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, documents: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;Document&#93;</span>) -&gt; <span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">None</span>:
          self.corpus_size = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(documents)

          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> documents:
              tokens = self._tokenize(doc.text)
              self.doc_lengths&#91;doc.<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">id</span>&#93; = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(tokens)
              self.term_freqs&#91;doc.<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">id</span>&#93; = {}

              seen_terms: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">set</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>&#93; = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">set</span>()
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> token <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> tokens:
                  self.term_freqs&#91;doc.<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">id</span>&#93;&#91;token&#93; = self.term_freqs&#91;doc.<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">id</span>&#93;.get(token, <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>) + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>
                  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> token <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">not</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> seen_terms:
                      self.doc_freqs&#91;token&#93; = self.doc_freqs.get(token, <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>) + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>
                      seen_terms.add(token)

          self.avg_doc_length = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">sum</span>(self.doc_lengths.values()) / self.corpus_size

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">score</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, query: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, doc_id: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>:
          query_terms = self._tokenize(query)
          doc_len = self.doc_lengths&#91;doc_id&#93;
          score = <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.0</span>

          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> term <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> query_terms:
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> term <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">not</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> self.doc_freqs <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">or</span> term <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">not</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> self.term_freqs.get(doc_id, {}):
                  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">continue</span>

              tf = self.term_freqs&#91;doc_id&#93;&#91;term&#93;
              df = self.doc_freqs&#91;term&#93;
              idf = math.log((self.corpus_size - df + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.5</span>) / (df + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.5</span>) + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>)
              tf_norm = (tf * (self.k1 + <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>)) / (
                  tf + self.k1 * (<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span> - self.b + self.b * doc_len / self.avg_doc_length)
              )
              score += idf * tf_norm

          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> score

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">search</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, query: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, top_k: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">10</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">tuple</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>&#93;&#93;:
          scores = &#91;
              (doc_id, self.score(query, doc_id))
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> self.doc_lengths
          &#93;
          scores.sort(key=<span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">lambda</span> x: x&#91;<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>&#93;, reverse=<span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">True</span>)
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> scores&#91;:top_k&#93;
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">class</span> <span class="hljs-title class_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">VectorIndex</span>:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;This class implements the smart search using the hybrid search.
         The index function normalize and stores the document
         search implements a cosine similarity search
        hybrid_search_weighted merges BM25 index and vector index using weighted average
       Reciprocal_rank_fusion Combines the results in an efficient way
     &quot;&quot;&quot;</span>

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">__init__</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self</span>):
          self.documents: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, np.ndarray&#93; = {}

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">index</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, documents: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;Document&#93;</span>) -&gt; <span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">None</span>:
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> documents:
              arr = np.array(doc.embedding, dtype=np.float32)
              norm = np.linalg.norm(arr)
              self.documents&#91;doc.<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">id</span>&#93; = arr / norm <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> norm &gt; <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">else</span> arr

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">search</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, query_embedding: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;, top_k: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">10</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">tuple</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>&#93;&#93;:
          q = np.array(query_embedding, dtype=np.float32)
          q = q / np.linalg.norm(q)

          scores = &#91;
              (doc_id, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>(np.dot(q, emb)))
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id, emb <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> self.documents.items()
          &#93;
          scores.sort(key=<span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">lambda</span> x: x&#91;<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>&#93;, reverse=<span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">True</span>)
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> scores&#91;:top_k&#93;

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">hybrid_search_weighted</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
      query: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      query_embedding: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;,
      bm25_index: BestMatching25Index,
      vector_index: VectorIndex,
      alpha: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.5</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      top_k: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">10</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
  </span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#93;:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Combine keyword and vector scores with a tunable weight.

      alpha = 1.0 → pure vector search
      alpha = 0.0 → pure keyword search
      alpha = 0.5 → equal weight (good starting point)
      &quot;&quot;&quot;</span>
      keyword_results = bm25_index.search(query, top_k=top_k * <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">2</span>)
      vector_results = vector_index.search(query_embedding, top_k=top_k * <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">2</span>)

      <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Normalize (min-max) each score list to &#91;0, 1&#93;</span>
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">normalize_scores</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">results: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">tuple</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;&#93;</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>&#93;:
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">not</span> results:
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> {}
          scores = &#91;s <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> _, s <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> results&#93;
          min_s, max_s = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">min</span>(scores), <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">max</span>(scores)
          rng = max_s - min_s
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> rng == <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0</span>:
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> {doc_id: <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1.0</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id, _ <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> results}
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> {doc_id: (s - min_s) / rng <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id, s <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> results}

      keyword_scores = normalize_scores(keyword_results)
      vector_scores = normalize_scores(vector_results)

      <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Merge</span>
      all_doc_ids = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">set</span>(keyword_scores) | <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">set</span>(vector_scores)
      combined = &#91;&#93;
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> all_doc_ids:
          ks = keyword_scores.get(doc_id, <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.0</span>)
          vs = vector_scores.get(doc_id, <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.0</span>)
          combined.append({
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;id&quot;</span>: doc_id,
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;score&quot;</span>: alpha * vs + (<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span> - alpha) * ks,
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;keyword_score&quot;</span>: ks,
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;vector_score&quot;</span>: vs,
          })

      combined.sort(key=<span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">lambda</span> x: x&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;score&quot;</span>&#93;, reverse=<span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">True</span>)
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> combined&#91;:top_k&#93;

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">reciprocal_rank_fusion</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
      *ranked_lists: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">tuple</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;&#93;,
      k: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">60</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      top_n: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">10</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
  </span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#93;:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;
     Merge multiple ranked lists,  uses RRF (Reciprocal Rank Fusion)

      RRF score = sum over all lists of: 1 / (k + rank)

      Why RRF over weighted combination?
      - No score normalization needed (works on ranks, not raw scores)
      - No alpha tuning needed
      - Robust across different score distributions
      - Used by Elasticsearch, Pinecone, Weaviate under the hood
      &quot;&quot;&quot;</span>
      rrf_scores: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>&#93; = defaultdict(<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>)
      doc_details: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#93; = {}

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> list_idx, ranked_list <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">enumerate</span>(ranked_lists):
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> rank, (doc_id, raw_score) <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">enumerate</span>(ranked_list, start=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span>):
              rrf_scores&#91;doc_id&#93; += <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1.0</span> / (k + rank)
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> doc_id <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">not</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> doc_details:
                  doc_details&#91;doc_id&#93; = {}
              doc_details&#91;doc_id&#93;&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">f&quot;list_</span><span class="hljs-string hljs-subst" style="border-width:0px;font:inherit;margin:0px;padding:0px;">{list_idx}</span><span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">_rank&quot;</span>&#93; = rank
              doc_details&#91;doc_id&#93;&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">f&quot;list_</span><span class="hljs-string hljs-subst" style="border-width:0px;font:inherit;margin:0px;padding:0px;">{list_idx}</span><span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">_score&quot;</span>&#93; = raw_score

      results = &#91;&#93;
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id, rrf_score <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> rrf_scores.items():
          results.append({
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;id&quot;</span>: doc_id,
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;rrf_score&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">round</span>(rrf_score, <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">6</span>),
              **doc_details&#91;doc_id&#93;,
          })

      results.sort(key=<span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">lambda</span> x: x&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;rrf_score&quot;</span>&#93;, reverse=<span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">True</span>)
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> results&#91;:top_n&#93;
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">hybrid_search_rrf</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
      query: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      query_embedding: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;,
      bm25_index: BestMatching25Index,
      vector_index: VectorIndex,
      top_k: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">10</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
  </span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#93;:
      keyword_results = bm25_index.search(query, top_k=top_k * <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">2</span>)
      vector_results = vector_index.search(query_embedding, top_k=top_k * <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">2</span>)

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> reciprocal_rank_fusion(keyword_results, vector_results, top_n=top_k)</pre><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Một trong những cách retrieval hiệu quả nhất hiện nay là hybrid retrieval — kết hợp giữa keyword search và semantic vector search. Keyword search mạnh ở các truy vấn chính xác như “password policy”, trong khi embedding search lại giỏi hơn ở việc hiểu ý nghĩa và ngữ cảnh câu hỏi.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Khi kết hợp cả hai, hệ thống sẽ vừa chính xác vừa linh hoạt hơn rất nhiều. Các framework như LlamaIndex và LangChain hiện là lựa chọn phổ biến để xây dựng pipeline retrieval theo hướng này.</p><h2 style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:20px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;letter-spacing:normal;line-height:32px;margin:10px 0px;orphans:2;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><strong>5. Knowledge base phải được cập nhật liên tục</strong></h2><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Một knowledge base tốt không phải thứ “xây xong rồi để đó”.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Theo thời gian, dữ liệu có thể lỗi thời, chính sách thay đổi hoặc embedding model được cập nhật. Nếu không refresh định kỳ, AI sẽ bắt đầu đưa ra các phản hồi không còn chính xác.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Có một khái niệm gọi là selective forgetting — tức chủ động xóa hoặc cập nhật những dữ liệu không còn phù hợp. Các công cụ như DeepEval hoặc TruLens có thể giúp theo dõi chất lượng retrieval và xác định chunk nào đang gây ra câu trả lời sai.</p><div class="codebar" style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:inherit;margin:0px;orphans:2;padding:0px;position:relative;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">&nbsp;</div><pre class="language-python prettyprint hljs" style="-webkit-text-stroke-width:0px;background-color:rgb(254, 255, 239);border-radius:5px;border:1px solid !important;color:rgba(0, 0, 0, 0.87);display:block;font-family:Consolas, Monaco, monospace;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:14px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:inherit;margin:0px 0px 16px;max-height:600px;max-width:100%;orphans:2;overflow:auto;padding:8px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;widows:2;word-spacing:0px;" id="pre2"> <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;                                                                                                                             
  Knowledge Base Quality Monitoring                                                                                               
  Knowledge base health with the help of automated checks:                                                                                     
  1. Retrieval quality — is it finding the right documents?
  2. Freshness detection — Are documents stale or embeddings drifting?
  3. Unified pipeline — Scheduled monitoring with alerts
  &quot;&quot;&quot;</span>

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> time
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> json
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> logging
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> datetime <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> datetime, timedelta
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> dataclasses <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> dataclass, field
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> typing <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> <span class="hljs-type" style="border-width:0px;font:inherit;margin:0px;padding:0px;">Any</span>, <span class="hljs-type" style="border-width:0px;font:inherit;margin:0px;padding:0px;">Callable</span>

  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> numpy <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">as</span> np

  logging.basicConfig(level=logging.INFO)
  logger = logging.getLogger(<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;kb_monitor&quot;</span>)
    <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">setup_deepeval_metrics</span>():
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Define retrieval quality metrics using DeepEval.

      DeepEval provides LLM-evaluated metrics — it uses a judge LLM to score
      whether retrieved context actually helps answer the question.
      &quot;&quot;&quot;</span>
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> deepeval.metrics <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> (
          AnswerRelevancyMetric,
          FaithfulnessMetric,
          ContextualPrecisionMetric,
          ContextualRecallMetric,
      )
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> deepeval.test_case <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> LLMTestCase

      metrics = {
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Does the answer address the question?</span>
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;relevancy&quot;</span>: AnswerRelevancyMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Is the answer grounded in the retrieved context (no hallucination)?</span>
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;faithfulness&quot;</span>: FaithfulnessMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Are the top-ranked retrieved docs actually relevant?</span>
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;context_precision&quot;</span>: ContextualPrecisionMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Did we retrieve all the docs needed to answer?</span>
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;context_recall&quot;</span>: ContextualRecallMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
      }

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> metrics, LLMTestCase
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">evaluate_retrieval_quality</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
      rag_pipeline: </span><span class="hljs-params hljs-type" style="border-width:0px;font:inherit;margin:0px;padding:0px;">Callable</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
      test_cases: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;,
  </span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#93;:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Run a set of test queries through your RAG pipeline and score them.

      Each test case should have:
      - query: the user question
      - expected_answer: ground truth answer (for recall/relevancy)
      &quot;&quot;&quot;</span>
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> deepeval <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> evaluate
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> deepeval.test_case <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> LLMTestCase
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> deepeval.metrics <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> (
          AnswerRelevancyMetric,
          FaithfulnessMetric,
          ContextualPrecisionMetric,
          ContextualRecallMetric,
      )

      results = &#91;&#93;

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> tc <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> test_cases:
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Run your actual RAG pipeline</span>
          response = rag_pipeline(tc&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;query&quot;</span>&#93;)

          test_case = LLMTestCase(
              <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">input</span>=tc&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;query&quot;</span>&#93;,
              actual_output=response&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;answer&quot;</span>&#93;,
              expected_output=tc&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;expected_answer&quot;</span>&#93;,
              retrieval_context=response&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;retrieved_contexts&quot;</span>&#93;,
          )

          metrics = &#91;
              AnswerRelevancyMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
              FaithfulnessMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
              ContextualPrecisionMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
              ContextualRecallMetric(threshold=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.7</span>),
          &#93;

          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> metric <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> metrics:
              metric.measure(test_case)

          results.append({
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;query&quot;</span>: tc&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;query&quot;</span>&#93;,
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;scores&quot;</span>: {m.__class__.__name__: m.score <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> m <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> metrics},
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;passed&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">all</span>(m.is_successful() <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> m <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> metrics),
          })

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> results
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">setup_trulens_monitoring</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">rag_pipeline: </span><span class="hljs-params hljs-type" style="border-width:0px;font:inherit;margin:0px;padding:0px;">Callable</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, app_name: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;my_kb&quot;</span>):
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Wrap your RAG pipeline with TruLens for continuous feedback logging.

      TruLens records every query + response + retrieved context, then
      runs feedback functions asynchronously to score each interaction.
      &quot;&quot;&quot;</span>
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> trulens.core <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> TruSession, Feedback, Select
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> trulens.providers.openai <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> OpenAI <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">as</span> TruLensOpenAI
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">from</span> trulens.apps.custom <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">import</span> TruCustomApp, instrument

      session = TruSession()

      <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Feedback provider (uses an LLM to judge quality)</span>
      provider = TruLensOpenAI()

      feedbacks = &#91;
          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Is the response relevant to the query?</span>
          Feedback(provider.relevance)
          .on_input()
          .on_output(),

          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Is the response grounded in retrieved context?</span>
          Feedback(provider.groundedness_measure_with_cot_reasons)
          .on(Select.RecordCalls.retrieve.rets)
          .on_output(),

          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Is the retrieved context relevant to the query?</span>
          Feedback(provider.context_relevance)
          .on_input()
          .on(Select.RecordCalls.retrieve.rets),
      &#93;

      <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># Wrap your pipeline — every call is now logged and scored</span>
<span class="hljs-meta" style="border-width:0px;font:inherit;margin:0px;padding:0px;">      @instrument</span>
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">class</span> <span class="hljs-title class_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">InstrumentedRAG</span>:
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">__init__</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, pipeline</span>):
              self._pipeline = pipeline

<span class="hljs-meta" style="border-width:0px;font:inherit;margin:0px;padding:0px;">          @instrument</span>
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">retrieve</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, query: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>&#93;:
              result = self._pipeline(query)
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> result&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;retrieved_contexts&quot;</span>&#93;

<span class="hljs-meta" style="border-width:0px;font:inherit;margin:0px;padding:0px;">          @instrument</span>
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">query</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, query: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>:
              result = self._pipeline(query)
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> result&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;answer&quot;</span>&#93;

      instrumented = InstrumentedRAG(rag_pipeline)

      tru_app = TruCustomApp(
          instrumented,
          app_name=app_name,
          feedbacks=feedbacks,
      )

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> tru_app, session
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">get_trulens_dashboard_url</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">session</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Launch the TruLens dashboard to visualize quality over time.&quot;&quot;&quot;</span>
      session.run_dashboard(port=<span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">8501</span>)
      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;http://localhost:8501&quot;</span>

<span class="hljs-meta" style="border-width:0px;font:inherit;margin:0px;padding:0px;">  @dataclass</span>
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">class</span> <span class="hljs-title class_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">DocumentFreshness</span>:
      doc_id: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>
      last_updated: datetime
      last_embedded: datetime
      source_hash: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>  <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># hash of source content at embedding time</span>
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">class</span> <span class="hljs-title class_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">FreshnessMonitor</span>:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Detect stale documents and embedding drift.&quot;&quot;&quot;</span>

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">__init__</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, staleness_threshold_days: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">int</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">30</span>):
          self.threshold = timedelta(days=staleness_threshold_days)
          self.freshness_records: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>&#91;<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>, DocumentFreshness&#93; = {}

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">register</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self, doc_id: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, source_hash: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span>) -&gt; <span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">None</span>:
          now = datetime.utcnow()
          self.freshness_records&#91;doc_id&#93; = DocumentFreshness(
              doc_id=doc_id,
              last_updated=now,
              last_embedded=now,
              source_hash=source_hash,
          )

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">check_staleness</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">self</span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>:
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Find documents that haven&#039;t been re-embedded recently.&quot;&quot;&quot;</span>
          now = datetime.utcnow()
          stale, fresh = &#91;&#93;, &#91;&#93;

          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id, record <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> self.freshness_records.items():
              age = now - record.last_embedded
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> age &gt; self.threshold:
                  stale.append({<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;id&quot;</span>: doc_id, <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;days_stale&quot;</span>: age.days})
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">else</span>:
                  fresh.append(doc_id)

          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> {
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;total&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(self.freshness_records),
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;fresh&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(fresh),
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;stale&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(stale),
              <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;stale_documents&quot;</span>: stale,
          }

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">check_content_drift</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
          self, doc_id: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, current_source_hash: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
      </span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">bool</span>:
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Check if source content changed since last embedding.&quot;&quot;&quot;</span>
          record = self.freshness_records.get(doc_id)
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">not</span> record:
              <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> <span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">True</span>  <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># unknown doc, treat as drifted</span>
          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> record.source_hash != current_source_hash
  <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">def</span> <span class="hljs-title function_" style="border-width:0px;font:inherit;margin:0px;padding:0px;">detect_embedding_drift</span>(<span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">
      old_embeddings: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;&#93;,
      new_embeddings: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">str</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">, </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">list</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#91;</span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&#93;&#93;,
      drift_threshold: </span><span class="hljs-params hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;"> = </span><span class="hljs-params hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">0.1</span><span class="hljs-params" style="border-width:0px;font:inherit;margin:0px;padding:0px;">,
  </span>) -&gt; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">dict</span>:
      <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;&quot;&quot;Compare old vs new embeddings for the same documents.

      If your embedding model gets updated (or you switch models),
      existing vectors may no longer be compatible. This detects that.
      &quot;&quot;&quot;</span>
      drifted = &#91;&#93;
      common_ids = <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">set</span>(old_embeddings) &amp; <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">set</span>(new_embeddings)

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">for</span> doc_id <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">in</span> common_ids:
          old = np.array(old_embeddings&#91;doc_id&#93;)
          new = np.array(new_embeddings&#91;doc_id&#93;)

          <span class="hljs-comment" style="border-width:0px;font:inherit;margin:0px;padding:0px;"># cosine distance: 0 = identical, 2 = opposite</span>
          cos_sim = np.dot(old, new) / (np.linalg.norm(old) * np.linalg.norm(new))
          cos_dist = <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">1</span> - cos_sim

          <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">if</span> cos_dist &gt; drift_threshold:
              drifted.append({
                  <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;id&quot;</span>: doc_id,
                  <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;cosine_distance&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">round</span>(<span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">float</span>(cos_dist), <span class="hljs-number" style="border-width:0px;font:inherit;margin:0px;padding:0px;">4</span>),
              })

      <span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">return</span> {
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;documents_compared&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(common_ids),
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;drifted&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">len</span>(drifted),
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;drift_threshold&quot;</span>: drift_threshold,
          <span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;drifted_documents&quot;</span>: <span class="hljs-built_in" style="border-width:0px;font:inherit;margin:0px;padding:0px;">sorted</span>(drifted, key=<span class="hljs-keyword" style="border-width:0px;font:inherit;margin:0px;padding:0px;">lambda</span> x: x&#91;<span class="hljs-string" style="border-width:0px;font:inherit;margin:0px;padding:0px;">&quot;cosine_distance&quot;</span>&#93;, reverse=<span class="hljs-literal" style="border-width:0px;font:inherit;margin:0px;padding:0px;">True</span>),
      }</pre><h2 style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:20px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;letter-spacing:normal;line-height:32px;margin:10px 0px;orphans:2;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><strong>6. Ba vấn đề lớn nhất khi xây knowledge base</strong></h2><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Vấn đề phổ biến nhất là dữ liệu chất lượng kém. Đây cũng là nguyên nhân khiến AI hallucinate. Ví dụ nổi tiếng là chatbot của Air Canada từng tự “bịa” ra chính sách hoàn tiền không tồn tại.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Một vấn đề khác là retrieval chậm. Nhiều hệ thống AI trả lời đúng nhưng quá lag vì developer chưa tối ưu index hoặc vector storage. Tác giả khuyến nghị nên dùng HNSW hoặc IVF index thay vì flat index để tăng tốc truy xuất.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Ngoài ra, scalability cũng là bài toán lớn. Nhiều đội ngũ ban đầu chọn monolithic architecture để triển khai nhanh, nhưng khi lượng truy vấn tăng mạnh thì CPU và RAM bị quá tải. Theo tác giả, horizontal sharding là hướng phù hợp hơn để scale knowledge base trong dài hạn.</p><h2 style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:20px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;letter-spacing:normal;line-height:32px;margin:10px 0px;orphans:2;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;"><strong>7. Knowledge base không phải nơi “dump dữ liệu”</strong></h2><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Cuối cùng, cần lưu ý rằng knowledge base không phải nơi ném toàn bộ dữ liệu vào rồi hy vọng AI tự hiểu mọi thứ. Nó là một tài sản cần được curate và tối ưu liên tục.</p><p style="-webkit-text-stroke-width:0px;background-color:rgb(255, 255, 255);border-width:0px;color:rgba(0, 0, 0, 0.87);font-family:Arial, sans-serif;font-feature-settings:inherit;font-kerning:inherit;font-language-override:inherit;font-optical-sizing:inherit;font-size-adjust:inherit;font-size:16px;font-stretch:inherit;font-style:normal;font-variant-alternates:inherit;font-variant-caps:normal;font-variant-east-asian:inherit;font-variant-emoji:inherit;font-variant-ligatures:normal;font-variant-numeric:inherit;font-variant-position:inherit;font-variation-settings:inherit;font-weight:400;letter-spacing:normal;line-height:26px;margin:10px 0px;orphans:2;overflow-wrap:break-word;padding:0px;text-align:justify;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:normal;widows:2;word-spacing:0px;">Bạn nên bắt đầu từ những tác vụ nhỏ, chẳng hạn chỉ tập trung vào 10 câu hỏi phổ biến nhất trước. Sau khi AI trả lời ổn định và chính xác, mới tiếp tục mở rộng hệ thống. Khác biệt giữa một AI “đoán mò” và một AI “thực sự biết” nằm ở chính quá trình curate dữ liệu có chủ đích này.</p>
		</div>
				<div id="author">
						<p>
				<strong>Nguồn tin:</strong>
				Quantrimang.com
			</p>
		</div>
	</div>
	<div id="footer" class="clearfix">
		<div id="url">
			<strong>URL của bản tin này: </strong><a href="https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-xay-dung-knowledge-base-hieu-qua-cho-ai-models-12848.html" title="Cách xây dựng Knowledge Base hiệu quả cho AI Models">https://www.nguoicodonvn2008.info/vi/news/savefile/kien-thuc-may-tinh/cach-xay-dung-knowledge-base-hieu-qua-cho-ai-models-12848.html</a>

		</div>
		<div class="clear"></div>
		<div class="copyright">
			&copy; .&#x3A; Nguoicodonvn2008.info - Cõi lòng người cô đơn &#x3A;.
		</div>
		<div id="contact">
			<a href="mailto:admin@nguoicodonvn2008.info">admin@nguoicodonvn2008.info</a>
		</div>
	</div>
</div>
        <div id="timeoutsess" class="chromeframe">
            Bạn đã không sử dụng Site, <a onclick="timeoutsesscancel();" href="https://nguoicodonvn2008.info/#">Bấm vào đây để duy trì trạng thái đăng nhập</a>. Thời gian chờ: <span id="secField"> 60 </span> giây
        </div>
        <div id="openidResult" class="nv-alert" style="display:none"></div>
        <div id="openidBt" data-result="" data-redirect=""></div>
		</script>
		<div class="car-top">
  <span><img src="https://nguoicodonvn2008.info/themes/default/images/car.png" alt=""></span>
</div>
<script src="https://nguoicodonvn2008.info/assets/js/jquery/jquery.min.js"></script>
<script>var nv_base_siteurl="/",nv_lang_data="vi",nv_lang_interface="vi",nv_name_variable="nv",nv_fc_variable="op",nv_lang_variable="language",nv_module_name="news",nv_func_name="savefile",nv_is_user=0, nv_my_ofs=-4,nv_my_abbr="EDT",nv_cookie_prefix="nv4c_e856T",nv_check_pass_mstime=1738000,nv_area_admin=0,nv_safemode=0,theme_responsive=0,nv_recaptcha_ver=2,nv_recaptcha_sitekey="",nv_recaptcha_type="image",XSSsanitize=1;</script>
<script src="https://nguoicodonvn2008.info/assets/js/language/vi.js"></script>
<script src="https://nguoicodonvn2008.info/assets/js/DOMPurify/purify3.js"></script>
<script src="https://nguoicodonvn2008.info/assets/js/global.js"></script>
<script src="https://nguoicodonvn2008.info/assets/js/site.js"></script>
<script src="https://nguoicodonvn2008.info/themes/default/js/news.js"></script>
<script src="https://nguoicodonvn2008.info/themes/default/js/main.js"></script>
<script src="https://nguoicodonvn2008.info/themes/default/js/custom.js"></script>
<script type="application/ld+json">
        {
            "@context": "https://schema.org",
            "@type": "Organization",
            "url": "https://nguoicodonvn2008.info",
            "logo": "https://nguoicodonvn2008.info/uploads/angel.gif"
        }
        </script>
<script src="https://nguoicodonvn2008.info/themes/default/js/bootstrap.min.js"></script>
<script type="text/javascript">
var $scrolltop = $('.car-top');
$scrolltop.on('click', function () {
    $('html,body').animate({
        scrollTop: 0
    }, 800);
    $(this).addClass("car-run");
    setTimeout(function(){ $scrolltop.removeClass('car-run');}, 1000);
    return false;
});
$(window).on('scroll', function ()
{ 
    if($(window).scrollTop() >= 200)
    {
        $scrolltop.addClass("show");
        $scrolltop.addClass("car-down");
    }
    else
    {
       $scrolltop.removeClass("show");
       setTimeout(function(){ $scrolltop.removeClass('car-down');}, 300);
    }
});
</script>
</body>
</html>