{"id":69368,"date":"2026-01-31T15:16:53","date_gmt":"2026-01-31T07:16:53","guid":{"rendered":"https:\/\/www.wsisp.com\/helps\/69368.html"},"modified":"2026-01-31T15:16:53","modified_gmt":"2026-01-31T07:16:53","slug":"%e3%80%90%e5%85%ab%e8%82%a1%e6%96%87%e3%80%91java%e9%9d%a2%e8%af%95%e7%aa%81%e5%87%bb%e6%b7%b1%e5%ba%a6%e8%a7%a3%e6%9e%90%ef%bc%88rag%e7%af%87%ef%bc%89","status":"publish","type":"post","link":"https:\/\/www.wsisp.com\/helps\/69368.html","title":{"rendered":"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09"},"content":{"rendered":"<li>RAG\u7cfb\u7edf\u6982\u8ff0<\/li>\n<p>RAG&#xff08;Retrieval-Augmented Generation&#xff09;\u7cfb\u7edf\u7ed3\u5408\u4e86\u68c0\u7d22\u548c\u751f\u6210\u4e24\u4e2a\u6b65\u9aa4&#xff0c;\u65e8\u5728\u5229\u7528\u5916\u90e8\u77e5\u8bc6\u5e93\u6765\u589e\u5f3a\u751f\u6210\u6a21\u578b\u7684\u80fd\u529b\u3002\u5176\u57fa\u672c\u6d41\u7a0b\u5305\u62ec&#xff1a;<\/p>\n<ul>\n<li>\u68c0\u7d22&#xff1a;\u6839\u636e\u7528\u6237\u67e5\u8be2\u4ece\u77e5\u8bc6\u5e93\u4e2d\u68c0\u7d22\u76f8\u5173\u6587\u6863\u6216\u7247\u6bb5\u3002<\/li>\n<li>\u751f\u6210&#xff1a;\u5c06\u68c0\u7d22\u5230\u7684\u5185\u5bb9\u4e0e\u7528\u6237\u67e5\u8be2\u4e00\u8d77\u8f93\u5165\u751f\u6210\u6a21\u578b&#xff0c;\u751f\u6210\u6700\u7ec8\u56de\u7b54\u3002<\/li>\n<\/ul>\n<p>RAG\u7684\u4f18\u52bf\u5728\u4e8e\u80fd\u591f\u5229\u7528\u6700\u65b0\u7684\u3001\u975e\u53c2\u6570\u5316\u7684\u77e5\u8bc6&#xff08;\u77e5\u8bc6\u5e93&#xff09;\u6765\u8865\u5145\u751f\u6210\u6a21\u578b\u7684\u53c2\u6570\u5316\u77e5\u8bc6&#xff0c;\u4ece\u800c\u751f\u6210\u66f4\u51c6\u786e\u3001\u66f4\u53ef\u9760\u7684\u56de\u7b54&#xff0c;\u5e76\u51cf\u5c11\u6a21\u578b\u4ea7\u751f\u5e7b\u89c9&#xff08;hallucination&#xff09;\u7684\u60c5\u51b5\u3002<\/p>\n<li>\u5904\u7406\u77e5\u8bc6\u5e93\u672a\u8986\u76d6\u95ee\u9898\u7684\u7b56\u7565<\/li>\n<p>\u5f53\u77e5\u8bc6\u5e93\u4e2d\u6ca1\u6709\u4e0e\u7528\u6237\u67e5\u8be2\u76f8\u5173\u7684\u5185\u5bb9\u65f6&#xff0c;RAG\u7cfb\u7edf\u9700\u8981\u91c7\u53d6\u9002\u5f53\u7684\u7b56\u7565\u6765\u5904\u7406\u3002<\/p>\n<p>2.1 \u95ee\u9898\u8bc6\u522b<\/p>\n<p>\u9996\u5148&#xff0c;\u7cfb\u7edf\u9700\u8981\u8bc6\u522b\u51fa\u5f53\u524d\u67e5\u8be2\u662f\u5426\u5728\u77e5\u8bc6\u5e93\u4e2d\u6709\u76f8\u5173\u4fe1\u606f\u3002\u8fd9\u53ef\u4ee5\u901a\u8fc7\u4ee5\u4e0b\u65b9\u5f0f&#xff1a;<\/p>\n<ul>\n<li>\u68c0\u7d22\u7ed3\u679c\u7684\u76f8\u5173\u6027\u8bc4\u5206&#xff1a;\u5982\u679c\u68c0\u7d22\u5230\u7684\u6587\u6863\u4e0e\u67e5\u8be2\u7684\u76f8\u5173\u6027\u5206\u6570\u4f4e\u4e8e\u67d0\u4e2a\u9608\u503c&#xff0c;\u53ef\u4ee5\u8ba4\u4e3a\u77e5\u8bc6\u5e93\u4e2d\u6ca1\u6709\u76f8\u5173\u4fe1\u606f\u3002<\/li>\n<li>\u68c0\u7d22\u7ed3\u679c\u7684\u6570\u91cf&#xff1a;\u5982\u679c\u68c0\u7d22\u7ed3\u679c\u4e3a\u7a7a\u6216\u6570\u91cf\u6781\u5c11&#xff0c;\u53ef\u80fd\u610f\u5473\u7740\u77e5\u8bc6\u5e93\u672a\u8986\u76d6\u3002<\/li>\n<\/ul>\n<p>2.2 \u54cd\u5e94\u7b56\u7565<\/p>\n<p>\u4e00\u65e6\u786e\u5b9a\u77e5\u8bc6\u5e93\u672a\u8986\u76d6&#xff0c;\u53ef\u4ee5\u91c7\u7528\u4ee5\u4e0b\u54cd\u5e94\u7b56\u7565&#xff1a;<\/p>\n<p>a) \u76f4\u63a5\u544a\u77e5\u7528\u6237\u77e5\u8bc6\u5e93\u4e2d\u6ca1\u6709\u76f8\u5173\u4fe1\u606f&#xff0c;\u5e76\u5c1d\u8bd5\u63d0\u4f9b\u5176\u4ed6\u5e2e\u52a9\u3002 b) \u5229\u7528\u751f\u6210\u6a21\u578b\u672c\u8eab\u7684\u77e5\u8bc6&#xff08;\u5982\u679c\u751f\u6210\u6a21\u578b\u662f\u9884\u8bad\u7ec3\u7684\u5927\u8bed\u8a00\u6a21\u578b&#xff0c;\u5b83\u53ef\u80fd\u5df2\u7ecf\u5177\u5907\u76f8\u5173\u80cc\u666f\u77e5\u8bc6&#xff09;\u6765\u56de\u7b54\u95ee\u9898&#xff0c;\u4f46\u9700\u8981\u660e\u786e\u544a\u77e5\u7528\u6237\u8be5\u56de\u7b54\u662f\u57fa\u4e8e\u6a21\u578b\u7684\u4e00\u822c\u6027\u77e5\u8bc6&#xff0c;\u800c\u975e\u7279\u5b9a\u77e5\u8bc6\u5e93\u3002 c) \u7ed3\u5408\u751f\u6210\u6a21\u578b\u7684\u77e5\u8bc6\u548c\u68c0\u7d22\u5230\u7684\u8fb9\u7f18\u76f8\u5173\u7684\u5185\u5bb9&#xff0c;\u8fdb\u884c\u63a8\u65ad\u6027\u56de\u7b54&#xff0c;\u540c\u65f6\u6ce8\u660e\u4e0d\u786e\u5b9a\u6027\u3002<\/p>\n<p>2.3 \u6df7\u5408\u65b9\u6cd5<\/p>\n<p>\u53e6\u4e00\u79cd\u7b56\u7565\u662f\u91c7\u7528\u6df7\u5408\u65b9\u6cd5&#xff0c;\u5373\u540c\u65f6\u4f7f\u7528\u53c2\u6570\u5316\u77e5\u8bc6&#xff08;\u751f\u6210\u6a21\u578b\u5185\u90e8\u77e5\u8bc6&#xff09;\u548c\u975e\u53c2\u6570\u5316\u77e5\u8bc6&#xff08;\u68c0\u7d22\u5230\u7684\u77e5\u8bc6&#xff09;\u3002\u5f53\u68c0\u7d22\u5230\u7684\u77e5\u8bc6\u4e0d\u8db3\u65f6&#xff0c;\u66f4\u591a\u5730\u4f9d\u8d56\u751f\u6210\u6a21\u578b\u7684\u77e5\u8bc6\u3002\u8fd9\u53ef\u4ee5\u901a\u8fc7\u5728\u751f\u6210\u8fc7\u7a0b\u4e2d\u8c03\u6574\u68c0\u7d22\u5185\u5bb9\u7684\u6743\u91cd\u6765\u5b9e\u73b0\u3002<\/p>\n<p>2.4 \u7528\u6237\u4ea4\u4e92\u4e0e\u53cd\u9988<\/p>\n<p>\u7cfb\u7edf\u53ef\u4ee5\u8bbe\u8ba1\u4ea4\u4e92\u6d41\u7a0b&#xff0c;\u5f53\u65e0\u6cd5\u56de\u7b54\u65f6&#xff0c;\u8be2\u95ee\u7528\u6237\u662f\u5426\u613f\u610f\u63d0\u4f9b\u66f4\u591a\u4fe1\u606f&#xff0c;\u6216\u8005\u5c06\u95ee\u9898\u8bb0\u5f55\u4e0b\u6765&#xff0c;\u7528\u4e8e\u540e\u7eed\u77e5\u8bc6\u5e93\u7684\u66f4\u65b0\u3002<\/p>\n<li>\u77e5\u8bc6\u5e93\u66f4\u65b0\u673a\u5236<\/li>\n<p>\u77e5\u8bc6\u5e93\u7684\u66f4\u65b0\u662fRAG\u7cfb\u7edf\u4fdd\u6301\u65f6\u6548\u6027\u7684\u5173\u952e\u3002\u66f4\u65b0\u673a\u5236\u5305\u62ec&#xff1a;<\/p>\n<p>3.1 \u5b9e\u65f6\u66f4\u65b0\u4e0e\u6279\u91cf\u66f4\u65b0<\/p>\n<ul>\n<li>\u5b9e\u65f6\u66f4\u65b0&#xff1a;\u5bf9\u4e8e\u66f4\u65b0\u9891\u7387\u9ad8\u3001\u65f6\u6548\u6027\u8981\u6c42\u5f3a\u7684\u6570\u636e&#xff08;\u5982\u65b0\u95fb\u3001\u80a1\u7968\u4ef7\u683c&#xff09;&#xff0c;\u91c7\u7528\u5b9e\u65f6\u66f4\u65b0\u3002\u53ef\u4ee5\u901a\u8fc7\u6d88\u606f\u961f\u5217&#xff08;\u5982Kafka&#xff09;\u76d1\u542c\u6570\u636e\u6e90\u53d8\u5316&#xff0c;\u5b9e\u65f6\u5199\u5165\u77e5\u8bc6\u5e93\u3002<\/li>\n<li>\u6279\u91cf\u66f4\u65b0&#xff1a;\u5bf9\u4e8e\u66f4\u65b0\u9891\u7387\u4f4e\u7684\u6570\u636e&#xff08;\u5982\u767e\u79d1\u5168\u4e66\u3001\u5386\u53f2\u8d44\u6599&#xff09;&#xff0c;\u53ef\u4ee5\u91c7\u7528\u5b9a\u65f6\u6279\u91cf\u66f4\u65b0&#xff0c;\u4f8b\u5982\u6bcf\u5929\u6216\u6bcf\u5468\u66f4\u65b0\u4e00\u6b21\u3002<\/li>\n<\/ul>\n<p>3.2 \u589e\u91cf\u66f4\u65b0\u4e0e\u5168\u91cf\u66f4\u65b0<\/p>\n<ul>\n<li>\u589e\u91cf\u66f4\u65b0&#xff1a;\u53ea\u66f4\u65b0\u53d1\u751f\u53d8\u5316\u7684\u6570\u636e&#xff0c;\u51cf\u5c11\u66f4\u65b0\u5f00\u9500\u3002\u9700\u8981\u6570\u636e\u6e90\u63d0\u4f9b\u53d8\u5316\u6807\u8bc6&#xff08;\u5982\u65f6\u95f4\u6233\u3001\u7248\u672c\u53f7&#xff09;\u3002<\/li>\n<li>\u5168\u91cf\u66f4\u65b0&#xff1a;\u91cd\u65b0\u6784\u5efa\u6574\u4e2a\u77e5\u8bc6\u5e93&#xff0c;\u9002\u7528\u4e8e\u6570\u636e\u6e90\u53d8\u5316\u5927\u6216\u65e0\u6cd5\u8ffd\u8e2a\u53d8\u5316\u7684\u60c5\u51b5&#xff0c;\u4f46\u5f00\u9500\u8f83\u5927\u3002<\/li>\n<\/ul>\n<p>3.3 \u6570\u636e\u6e90\u76d1\u63a7\u4e0e\u89e6\u53d1\u66f4\u65b0<\/p>\n<ul>\n<li>\u76d1\u63a7\u6570\u636e\u6e90\u7684\u53d8\u5316&#xff08;\u5982API\u3001\u6570\u636e\u5e93\u3001\u6587\u4ef6\u7cfb\u7edf&#xff09;&#xff0c;\u4e00\u65e6\u68c0\u6d4b\u5230\u53d8\u5316&#xff0c;\u89e6\u53d1\u66f4\u65b0\u6d41\u7a0b\u3002<\/li>\n<li>\u8bbe\u7f6e\u66f4\u65b0\u7b56\u7565&#xff0c;\u4f8b\u5982\u5b9a\u671f\u68c0\u67e5\u3001\u4e8b\u4ef6\u9a71\u52a8\u7b49\u3002<\/li>\n<\/ul>\n<p>3.4 \u7248\u672c\u63a7\u5236\u4e0e\u56de\u6eda<\/p>\n<ul>\n<li>\u5bf9\u77e5\u8bc6\u5e93\u8fdb\u884c\u7248\u672c\u7ba1\u7406&#xff0c;\u6bcf\u6b21\u66f4\u65b0\u751f\u6210\u4e00\u4e2a\u7248\u672c&#xff0c;\u4fbf\u4e8e\u5728\u51fa\u73b0\u95ee\u9898\u65f6\u56de\u6eda\u5230\u4e4b\u524d\u7684\u7248\u672c\u3002<\/li>\n<li>\u5728\u66f4\u65b0\u8fc7\u7a0b\u4e2d&#xff0c;\u4fdd\u8bc1\u7cfb\u7edf\u7684\u53ef\u7528\u6027&#xff0c;\u53ef\u4ee5\u4f7f\u7528\u53cc\u5199\u3001\u5f71\u5b50\u77e5\u8bc6\u5e93\u7b49\u6280\u672f&#xff0c;\u9010\u6b65\u5207\u6362\u3002<\/li>\n<\/ul>\n<li>\u5e38\u89c1RAG\u95ee\u9898\u53ca\u89e3\u51b3\u65b9\u6848<\/li>\n<p>4.1 \u68c0\u7d22\u8d28\u91cf\u95ee\u9898<\/p>\n<p>4.1.1 \u68c0\u7d22\u4e0d\u5168 &#8211; \u95ee\u9898&#xff1a;\u68c0\u7d22\u7cfb\u7edf\u672a\u80fd\u68c0\u7d22\u5230\u6240\u6709\u76f8\u5173\u6587\u6863\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u4f18\u5316\u68c0\u7d22\u6a21\u578b&#xff0c;\u4f7f\u7528\u66f4\u5148\u8fdb\u7684\u5d4c\u5165\u6a21\u578b&#xff08;\u5982BERT\u3001RoBERTa&#xff09;\u8fdb\u884c\u8bed\u4e49\u68c0\u7d22&#xff1b;\u7ed3\u5408\u5173\u952e\u8bcd\u68c0\u7d22\u548c\u8bed\u4e49\u68c0\u7d22&#xff1b;\u8c03\u6574\u68c0\u7d22\u7684\u53ec\u56de\u6570\u91cf&#xff08;top-k&#xff09;\u548c\u9608\u503c\u3002<\/p>\n<p>4.1.2 \u68c0\u7d22\u4e0d\u76f8\u5173 &#8211; \u95ee\u9898&#xff1a;\u68c0\u7d22\u5230\u7684\u6587\u6863\u4e0e\u67e5\u8be2\u4e0d\u76f8\u5173&#xff0c;\u5bfc\u81f4\u751f\u6210\u6a21\u578b\u53d7\u5230\u5e72\u6270\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u63d0\u9ad8\u68c0\u7d22\u7cbe\u5ea6&#xff0c;\u4f7f\u7528\u91cd\u65b0\u6392\u5e8f&#xff08;re-ranking&#xff09;\u6280\u672f&#xff0c;\u4f8b\u5982\u4f7f\u7528\u4ea4\u53c9\u7f16\u7801\u5668&#xff08;cross-encoder&#xff09;\u5bf9\u68c0\u7d22\u7ed3\u679c\u8fdb\u884c\u91cd\u6392&#xff1b;\u4f7f\u7528\u591a\u9636\u6bb5\u68c0\u7d22&#xff08;\u5148\u53ec\u56de\u518d\u7cbe\u6392&#xff09;\u3002<\/p>\n<p>4.1.3 \u68c0\u7d22\u7ed3\u679c\u6392\u5e8f\u95ee\u9898 &#8211; \u95ee\u9898&#xff1a;\u76f8\u5173\u6587\u6863\u6ca1\u6709\u6392\u5728\u524d\u9762&#xff0c;\u5bfc\u81f4\u751f\u6210\u6a21\u578b\u65e0\u6cd5\u4f18\u5148\u5229\u7528\u6700\u76f8\u5173\u7684\u4fe1\u606f\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u4f7f\u7528\u5b66\u4e60\u6392\u5e8f&#xff08;Learning to Rank&#xff09;\u6280\u672f&#xff0c;\u5229\u7528\u7528\u6237\u70b9\u51fb\u6570\u636e\u6216\u4eba\u5de5\u6807\u6ce8\u6570\u636e\u8bad\u7ec3\u6392\u5e8f\u6a21\u578b&#xff1b;\u5728\u751f\u6210\u6b65\u9aa4\u4e2d&#xff0c;\u53ef\u4ee5\u8ba9\u6a21\u578b\u540c\u65f6\u770b\u5230\u591a\u4e2a\u68c0\u7d22\u7ed3\u679c&#xff0c;\u5e76\u5b66\u4e60\u5982\u4f55\u6574\u5408\u5b83\u4eec\u3002<\/p>\n<p>4.2 \u751f\u6210\u8d28\u91cf\u95ee\u9898<\/p>\n<p>4.2.1 \u751f\u6210\u4e0e\u68c0\u7d22\u5185\u5bb9\u4e0d\u4e00\u81f4 &#8211; \u95ee\u9898&#xff1a;\u751f\u6210\u6a21\u578b\u5ffd\u7565\u4e86\u68c0\u7d22\u5230\u7684\u5185\u5bb9&#xff0c;\u6216\u8005\u4ea7\u751f\u4e0e\u68c0\u7d22\u5185\u5bb9\u77db\u76fe\u7684\u4fe1\u606f\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u5728\u751f\u6210\u6a21\u578b\u7684\u8f93\u5165\u4e2d\u660e\u786e\u6307\u793a\u68c0\u7d22\u5185\u5bb9\u7684\u91cd\u8981\u6027&#xff1b;\u4f7f\u7528\u6ce8\u610f\u529b\u673a\u5236\u52a0\u5f3a\u68c0\u7d22\u5185\u5bb9\u7684\u5f71\u54cd&#xff1b;\u5728\u8bad\u7ec3\u751f\u6210\u6a21\u578b\u65f6&#xff0c;\u52a0\u5165\u5bf9\u68c0\u7d22\u5185\u5bb9\u5229\u7528\u7387\u7684\u76d1\u7763\u3002<\/p>\n<p>4.2.2 \u751f\u6210\u5185\u5bb9\u7f3a\u4e4f\u53ef\u4fe1\u5ea6 &#8211; \u95ee\u9898&#xff1a;\u751f\u6210\u7684\u5185\u5bb9\u867d\u7136\u6d41\u7545&#xff0c;\u4f46\u4e8b\u5b9e\u6027\u9519\u8bef\u8f83\u591a\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u5f15\u5165\u4e8b\u5b9e\u6027\u68c0\u67e5&#xff08;fact-checking&#xff09;\u6a21\u5757&#xff0c;\u5bf9\u751f\u6210\u7684\u5185\u5bb9\u8fdb\u884c\u9a8c\u8bc1&#xff1b;\u4f7f\u7528\u591a\u4e2a\u68c0\u7d22\u7ed3\u679c\u8fdb\u884c\u4ea4\u53c9\u9a8c\u8bc1&#xff1b;\u5728\u751f\u6210\u8fc7\u7a0b\u4e2d\u52a0\u5165\u5f15\u7528\u673a\u5236&#xff0c;\u8981\u6c42\u6a21\u578b\u4e3a\u751f\u6210\u7684\u5185\u5bb9\u63d0\u4f9b\u68c0\u7d22\u6587\u6863\u4e2d\u7684\u4f9d\u636e\u3002<\/p>\n<p>4.2.3 \u751f\u6210\u5185\u5bb9\u5197\u4f59\u6216\u4fe1\u606f\u4e0d\u8db3 &#8211; \u95ee\u9898&#xff1a;\u751f\u6210\u7684\u5185\u5bb9\u91cd\u590d\u5570\u55e6&#xff0c;\u6216\u8005\u9057\u6f0f\u5173\u952e\u4fe1\u606f\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u63a7\u5236\u751f\u6210\u7684\u957f\u5ea6&#xff0c;\u4f7f\u7528\u957f\u5ea6\u60e9\u7f5a&#xff08;length penalty&#xff09;&#xff1b;\u5728\u751f\u6210\u8fc7\u7a0b\u4e2d\u52a0\u5165\u8986\u76d6\u5ea6&#xff08;coverage&#xff09;\u8981\u6c42&#xff0c;\u786e\u4fdd\u68c0\u7d22\u5230\u7684\u5173\u952e\u4fe1\u606f\u90fd\u88ab\u8986\u76d6&#xff1b;\u4f7f\u7528\u6458\u8981\u6280\u672f\u5bf9\u751f\u6210\u5185\u5bb9\u8fdb\u884c\u538b\u7f29\u3002<\/p>\n<p>\u00a0\u7bc7\u5e45\u9650\u5236\u4e0b\u9762\u5c31\u53ea\u80fd\u7ed9\u5927\u5bb6\u5c55\u793a\u5c0f\u518c\u90e8\u5206\u5185\u5bb9\u4e86\u3002\u6574\u7406\u4e86\u4e00\u4efd\u6838\u5fc3\u9762\u8bd5\u7b14\u8bb0\u5305\u62ec\u4e86&#xff1a;Java\u9762\u8bd5\u3001Spring\u3001JVM\u3001MyBatis\u3001Redis\u3001MySQL\u3001\u5e76\u53d1\u7f16\u7a0b\u3001\u5fae\u670d\u52a1\u3001Linux\u3001Springboot\u3001SpringCloud\u3001MQ\u3001Kafc<\/p>\n<p>\u9700\u8981\u5168\u5957\u9762\u8bd5\u7b14\u8bb0\u53ca\u7b54\u6848<span class=\"link-card-box\"><span class=\"link-title\">\u3010\u70b9\u51fb\u6b64\u5904\u5373\u53ef\/\u514d\u8d39\u83b7\u53d6\u3011<\/span><span class=\"link-link\"><img decoding=\"async\" class=\"link-link-icon\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260131071652-697dac649ff65.png\" \/>https:\/\/docs.qq.com\/doc\/DQXdYWE9LZ2ZHZ1ho<\/span><\/span><\/p>\n<p>4.3 \u7cfb\u7edf\u6027\u80fd\u95ee\u9898<\/p>\n<p>4.3.1 \u68c0\u7d22\u901f\u5ea6\u6162 &#8211; \u95ee\u9898&#xff1a;\u68c0\u7d22\u9636\u6bb5\u8017\u65f6\u8fc7\u957f&#xff0c;\u5f71\u54cd\u7cfb\u7edf\u54cd\u5e94\u65f6\u95f4\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u4f7f\u7528\u9ad8\u6548\u7684\u5411\u91cf\u68c0\u7d22\u5e93&#xff08;\u5982FAISS\u3001Annoy&#xff09;&#xff1b;\u5bf9\u6587\u6863\u8fdb\u884c\u5206\u5757\u7d22\u5f15&#xff0c;\u51cf\u5c11\u6bcf\u4e2a\u7d22\u5f15\u7684\u89c4\u6a21&#xff1b;\u4f7f\u7528\u8fd1\u4f3c\u6700\u8fd1\u90bb&#xff08;ANN&#xff09;\u7b97\u6cd5\u52a0\u901f\u68c0\u7d22\u3002<\/p>\n<p>4.3.2 \u751f\u6210\u901f\u5ea6\u6162 &#8211; \u95ee\u9898&#xff1a;\u751f\u6210\u6a21\u578b\u63a8\u7406\u901f\u5ea6\u6162&#xff0c;\u5c24\u5176\u662f\u5927\u6a21\u578b\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u4f7f\u7528\u6a21\u578b\u84b8\u998f&#xff08;distillation&#xff09;\u5f97\u5230\u5c0f\u6a21\u578b&#xff1b;\u4f7f\u7528\u91cf\u5316&#xff08;quantization&#xff09;\u6280\u672f\u51cf\u5c11\u6a21\u578b\u5927\u5c0f&#xff1b;\u4f7f\u7528\u7f13\u5b58\u673a\u5236&#xff0c;\u5bf9\u76f8\u540c\u6216\u76f8\u4f3c\u7684\u67e5\u8be2\u7f13\u5b58\u751f\u6210\u7ed3\u679c\u3002<\/p>\n<p>4.3.3 \u9ad8\u5e76\u53d1\u4e0b\u7684\u7cfb\u7edf\u7a33\u5b9a\u6027 &#8211; \u95ee\u9898&#xff1a;\u5e76\u53d1\u8bf7\u6c42\u591a\u65f6&#xff0c;\u7cfb\u7edf\u54cd\u5e94\u53d8\u6162\u751a\u81f3\u5d29\u6e83\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u91c7\u7528\u5fae\u670d\u52a1\u67b6\u6784&#xff0c;\u5bf9\u68c0\u7d22\u670d\u52a1\u548c\u751f\u6210\u670d\u52a1\u8fdb\u884c\u6c34\u5e73\u6269\u5c55&#xff1b;\u4f7f\u7528\u8d1f\u8f7d\u5747\u8861&#xff1b;\u8bbe\u7f6e\u8bf7\u6c42\u961f\u5217\u548c\u9650\u6d41\u673a\u5236\u3002<\/p>\n<p>4.4 \u77e5\u8bc6\u5e93\u66f4\u65b0\u95ee\u9898<\/p>\n<p>4.4.1 \u66f4\u65b0\u5ef6\u8fdf &#8211; \u95ee\u9898&#xff1a;\u77e5\u8bc6\u5e93\u66f4\u65b0\u4e0d\u53ca\u65f6&#xff0c;\u5bfc\u81f4\u7528\u6237\u83b7\u53d6\u5230\u8fc7\u65f6\u4fe1\u606f\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u6839\u636e\u6570\u636e\u6e90\u7684\u66f4\u65b0\u9891\u7387\u8bbe\u7f6e\u5408\u7406\u7684\u66f4\u65b0\u7b56\u7565&#xff1b;\u5bf9\u4e8e\u5b9e\u65f6\u6027\u8981\u6c42\u9ad8\u7684\u6570\u636e&#xff0c;\u91c7\u7528\u6d41\u5f0f\u66f4\u65b0&#xff1b;\u5efa\u7acb\u76d1\u63a7\u544a\u8b66&#xff0c;\u5f53\u66f4\u65b0\u5ef6\u8fdf\u8d85\u8fc7\u9608\u503c\u65f6\u89e6\u53d1\u4eba\u5de5\u5e72\u9884\u3002<\/p>\n<p>4.4.2 \u66f4\u65b0\u5bfc\u81f4\u7684\u6570\u636e\u4e0d\u4e00\u81f4 &#8211; \u95ee\u9898&#xff1a;\u66f4\u65b0\u8fc7\u7a0b\u4e2d&#xff0c;\u90e8\u5206\u6570\u636e\u66f4\u65b0\u6210\u529f&#xff0c;\u90e8\u5206\u5931\u8d25&#xff0c;\u5bfc\u81f4\u77e5\u8bc6\u5e93\u72b6\u6001\u4e0d\u4e00\u81f4\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u4f7f\u7528\u4e8b\u52a1\u6027\u66f4\u65b0&#xff0c;\u4fdd\u8bc1\u66f4\u65b0\u7684\u539f\u5b50\u6027&#xff1b;\u5728\u66f4\u65b0\u524d\u5907\u4efd&#xff0c;\u66f4\u65b0\u5931\u8d25\u65f6\u56de\u6eda&#xff1b;\u4f7f\u7528\u7248\u672c\u63a7\u5236&#xff0c;\u6bcf\u6b21\u66f4\u65b0\u751f\u6210\u65b0\u7248\u672c&#xff0c;\u66f4\u65b0\u6210\u529f\u540e\u518d\u5207\u6362\u7248\u672c\u3002<\/p>\n<p>4.4.3 \u5386\u53f2\u6570\u636e\u4e0e\u5b9e\u65f6\u6570\u636e\u878d\u5408 &#8211; \u95ee\u9898&#xff1a;\u5982\u4f55\u5c06\u5386\u53f2\u6570\u636e\u4e0e\u5b9e\u65f6\u6570\u636e\u7ed3\u5408\u8d77\u6765&#xff0c;\u907f\u514d\u6570\u636e\u51b2\u7a81\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u8bbe\u8ba1\u6570\u636e\u878d\u5408\u7b56\u7565&#xff0c;\u4f8b\u5982\u4ee5\u5b9e\u65f6\u6570\u636e\u4e3a\u51c6&#xff0c;\u6216\u8005\u6309\u7167\u65f6\u95f4\u6233\u9009\u62e9\u6700\u65b0\u6570\u636e&#xff1b;\u5bf9\u4e8e\u51b2\u7a81\u7684\u6570\u636e&#xff0c;\u53ef\u4ee5\u4fdd\u7559\u591a\u4e2a\u7248\u672c&#xff0c;\u5e76\u5728\u68c0\u7d22\u65f6\u6839\u636e\u65f6\u95f4\u4e0a\u4e0b\u6587\u9009\u62e9\u3002<\/p>\n<p>4.5 \u591a\u6a21\u6001RAG\u95ee\u9898<\/p>\n<p>4.5.1 \u591a\u6a21\u6001\u6570\u636e\u68c0\u7d22 &#8211; \u95ee\u9898&#xff1a;\u77e5\u8bc6\u5e93\u4e2d\u5305\u542b\u6587\u672c\u3001\u56fe\u50cf\u3001\u89c6\u9891\u7b49\u591a\u79cd\u6a21\u6001\u7684\u6570\u636e&#xff0c;\u5982\u4f55\u8de8\u6a21\u6001\u68c0\u7d22\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u4f7f\u7528\u591a\u6a21\u6001\u5d4c\u5165\u6a21\u578b&#xff08;\u5982CLIP&#xff09;\u5c06\u4e0d\u540c\u6a21\u6001\u7684\u6570\u636e\u6620\u5c04\u5230\u540c\u4e00\u5411\u91cf\u7a7a\u95f4&#xff1b;\u6784\u5efa\u591a\u6a21\u6001\u7d22\u5f15&#xff0c;\u652f\u6301\u8de8\u6a21\u6001\u68c0\u7d22\u3002<\/p>\n<p>4.5.2 \u591a\u6a21\u6001\u751f\u6210 &#8211; \u95ee\u9898&#xff1a;\u5982\u4f55\u6839\u636e\u591a\u6a21\u6001\u68c0\u7d22\u7ed3\u679c\u751f\u6210\u591a\u6a21\u6001\u5185\u5bb9&#xff08;\u4f8b\u5982&#xff0c;\u751f\u6210\u5305\u542b\u56fe\u7247\u548c\u6587\u672c\u7684\u56de\u7b54&#xff09;\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u4f7f\u7528\u591a\u6a21\u6001\u751f\u6210\u6a21\u578b&#xff08;\u5982DALL-E\u3001GPT-4V&#xff09;&#xff1b;\u5c06\u4e0d\u540c\u6a21\u6001\u7684\u68c0\u7d22\u7ed3\u679c\u8f93\u5165\u5230\u751f\u6210\u6a21\u578b&#xff0c;\u5e76\u8bbe\u8ba1\u5408\u9002\u7684\u63d0\u793a\u8bcd\u8ba9\u6a21\u578b\u751f\u6210\u591a\u6a21\u6001\u5185\u5bb9\u3002<\/p>\n<p>4.6 \u5b89\u5168\u4e0e\u9690\u79c1\u95ee\u9898<\/p>\n<p>4.6.1 \u6570\u636e\u6cc4\u9732\u98ce\u9669 &#8211; \u95ee\u9898&#xff1a;\u77e5\u8bc6\u5e93\u4e2d\u53ef\u80fd\u5305\u542b\u654f\u611f\u4fe1\u606f&#xff0c;\u68c0\u7d22\u548c\u751f\u6210\u8fc7\u7a0b\u4e2d\u53ef\u80fd\u6cc4\u9732\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u5bf9\u77e5\u8bc6\u5e93\u4e2d\u7684\u654f\u611f\u4fe1\u606f\u8fdb\u884c\u8131\u654f\u5904\u7406&#xff1b;\u5728\u751f\u6210\u6a21\u578b\u4e2d\u52a0\u5165\u9690\u79c1\u4fdd\u62a4\u673a\u5236&#xff0c;\u4f8b\u5982\u5dee\u5206\u9690\u79c1&#xff1b;\u5bf9\u7528\u6237\u67e5\u8be2\u8fdb\u884c\u8fc7\u6ee4&#xff0c;\u9632\u6b62\u6076\u610f\u67e5\u8be2\u8bf1\u5bfc\u751f\u6210\u654f\u611f\u4fe1\u606f\u3002<\/p>\n<p>4.6.2 \u751f\u6210\u6709\u5bb3\u5185\u5bb9 &#8211; \u95ee\u9898&#xff1a;\u751f\u6210\u6a21\u578b\u53ef\u80fd\u57fa\u4e8e\u68c0\u7d22\u5230\u7684\u6709\u5bb3\u5185\u5bb9\u751f\u6210\u6709\u5bb3\u56de\u7b54\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u5bf9\u77e5\u8bc6\u5e93\u5185\u5bb9\u8fdb\u884c\u5ba1\u6838&#xff0c;\u8fc7\u6ee4\u6709\u5bb3\u4fe1\u606f&#xff1b;\u5728\u751f\u6210\u6a21\u578b\u8f93\u51fa\u524d\u52a0\u5165\u5185\u5bb9\u5b89\u5168\u8fc7\u6ee4&#xff1b;\u4f7f\u7528\u5bf9\u9f50&#xff08;alignment&#xff09;\u6280\u672f\u4f7f\u751f\u6210\u6a21\u578b\u7b26\u5408\u5b89\u5168\u89c4\u8303\u3002<\/p>\n<p>4.7 \u8bc4\u4f30\u4e0e\u76d1\u63a7\u95ee\u9898<\/p>\n<p>4.7.1 \u5982\u4f55\u8bc4\u4f30RAG\u7cfb\u7edf\u6548\u679c &#8211; \u95ee\u9898&#xff1a;RAG\u7cfb\u7edf\u7684\u8bc4\u4f30\u6d89\u53ca\u68c0\u7d22\u548c\u751f\u6210\u591a\u4e2a\u73af\u8282&#xff0c;\u96be\u4ee5\u7528\u4e00\u4e2a\u6307\u6807\u8861\u91cf\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u5206\u522b\u8bc4\u4f30\u68c0\u7d22\u548c\u751f\u6210\u6a21\u5757&#xff0c;\u540c\u65f6\u8bc4\u4f30\u7aef\u5230\u7aef\u6548\u679c\u3002\u68c0\u7d22\u6a21\u5757\u8bc4\u4f30\u53ec\u56de\u7387\u3001\u51c6\u786e\u7387&#xff1b;\u751f\u6210\u6a21\u5757\u8bc4\u4f30\u6d41\u7545\u6027\u3001\u76f8\u5173\u6027\u548c\u4e8b\u5b9e\u6b63\u786e\u6027&#xff1b;\u7aef\u5230\u7aef\u8bc4\u4f30\u53ef\u4ee5\u91c7\u7528\u4eba\u5de5\u8bc4\u4f30&#xff0c;\u6216\u8005\u4f7f\u7528\u81ea\u52a8\u8bc4\u4f30\u6307\u6807&#xff08;\u5982RAGAS\u3001BLEU\u3001ROUGE\u7b49&#xff09;\u3002<\/p>\n<p>4.7.2 \u76d1\u63a7\u6307\u6807\u8bbe\u8ba1 &#8211; \u95ee\u9898&#xff1a;\u7ebf\u4e0a\u7cfb\u7edf\u9700\u8981\u76d1\u63a7\u54ea\u4e9b\u6307\u6807\u6765\u4fdd\u8bc1\u7cfb\u7edf\u5065\u5eb7\u3002 &#8211; \u89e3\u51b3\u65b9\u6848&#xff1a;\u76d1\u63a7\u68c0\u7d22\u6210\u529f\u7387\u3001\u68c0\u7d22\u5ef6\u8fdf\u3001\u751f\u6210\u5ef6\u8fdf\u3001\u9519\u8bef\u7387&#xff1b;\u76d1\u63a7\u77e5\u8bc6\u5e93\u66f4\u65b0\u72b6\u6001&#xff1b;\u76d1\u63a7\u7528\u6237\u53cd\u9988&#xff08;\u5982\u70b9\u8d5e\u3001\u70b9\u8e29&#xff09;\u6765\u8bc4\u4f30\u56de\u7b54\u8d28\u91cf\u3002<\/p>\n<li>\u672a\u6765\u5c55\u671b\u4e0e\u603b\u7ed3<\/li>\n<p>\u968f\u7740\u5927\u8bed\u8a00\u6a21\u578b\u548c\u68c0\u7d22\u6280\u672f\u7684\u53d1\u5c55&#xff0c;RAG\u7cfb\u7edf\u5c06\u5728\u66f4\u591a\u9886\u57df\u5f97\u5230\u5e94\u7528\u3002\u672a\u6765\u53ef\u80fd\u7684\u65b9\u5411\u5305\u62ec&#xff1a;<\/p>\n<ul>\n<li>\u66f4\u9ad8\u6548\u7684\u68c0\u7d22\u6280\u672f&#xff0c;\u5982\u52a8\u6001\u68c0\u7d22&#xff08;\u5728\u751f\u6210\u8fc7\u7a0b\u4e2d\u591a\u6b21\u68c0\u7d22&#xff09;\u3002<\/li>\n<li>\u66f4\u667a\u80fd\u7684\u751f\u6210\u6a21\u578b&#xff0c;\u80fd\u591f\u66f4\u597d\u5730\u5229\u7528\u68c0\u7d22\u5185\u5bb9\u3002<\/li>\n<li>\u591a\u6a21\u6001RAG\u7684\u666e\u53ca\u3002<\/li>\n<li>\u66f4\u5f3a\u7684\u5b89\u5168\u4e0e\u9690\u79c1\u4fdd\u62a4\u3002<\/li>\n<\/ul>\n<p>\u603b\u7ed3&#xff1a;RAG\u7cfb\u7edf\u901a\u8fc7\u7ed3\u5408\u68c0\u7d22\u548c\u751f\u6210&#xff0c;\u80fd\u591f\u63d0\u4f9b\u66f4\u51c6\u786e\u3001\u66f4\u53ef\u9760\u7684\u56de\u7b54\u3002\u7136\u800c&#xff0c;\u6784\u5efa\u4e00\u4e2a\u9ad8\u6548\u7684RAG\u7cfb\u7edf\u9700\u8981\u89e3\u51b3\u68c0\u7d22\u8d28\u91cf\u3001\u751f\u6210\u8d28\u91cf\u3001\u7cfb\u7edf\u6027\u80fd\u3001\u77e5\u8bc6\u5e93\u66f4\u65b0\u3001\u5b89\u5168\u9690\u79c1\u548c\u8bc4\u4f30\u76d1\u63a7\u7b49\u591a\u65b9\u9762\u7684\u6311\u6218\u3002\u901a\u8fc7\u4e0d\u65ad\u4f18\u5316\u548c\u8fed\u4ee3&#xff0c;RAG\u7cfb\u7edf\u5c06\u6210\u4e3a\u5f3a\u5927\u7684\u77e5\u8bc6\u589e\u5f3a\u5bf9\u8bdd\u7cfb\u7edf\u3002<\/p>\n<p>\u4ee5\u4e0a\u662f\u4e00\u4e2a\u8be6\u7ec6\u7684\u63d0\u7eb2\u548c\u90e8\u5206\u5185\u5bb9\u5c55\u5f00&#xff0c;\u7531\u4e8e\u5b57\u6570\u9650\u5236&#xff0c;\u65e0\u6cd5\u5b8c\u5168\u5c55\u5f00\u52302\u4e07\u5b57&#xff0c;\u4f46\u5df2\u7ecf\u6db5\u76d6\u4e86\u4e3b\u8981\u65b9\u9762\u3002\u5728\u5b9e\u9645\u9762\u8bd5\u4e2d&#xff0c;\u53ef\u4ee5\u6839\u636e\u9762\u8bd5\u5b98\u7684\u5174\u8da3\u70b9\u9009\u62e9\u5176\u4e2d\u51e0\u4e2a\u65b9\u9762\u6df1\u5165\u8ba8\u8bba\u3002<\/p>\n<h3>RAG\u7cfb\u7edf\u6df1\u5ea6\u89e3\u6790&#xff1a;\u672a\u8986\u76d6\u95ee\u9898\u5904\u7406\u4e0e\u77e5\u8bc6\u5e93\u66f4\u65b0\u673a\u5236<\/h3>\n<h4>\u4e00\u3001RAG\u5982\u4f55\u5904\u7406\u77e5\u8bc6\u5e93\u6ca1\u6709\u7684\u95ee\u9898&#xff1f;<\/h4>\n<h5>1.1 \u95ee\u9898\u8bc6\u522b\u4e0e\u5206\u7c7b<\/h5>\n<p>\u5f53\u7528\u6237\u67e5\u8be2\u8d85\u51fa\u77e5\u8bc6\u5e93\u8303\u56f4\u65f6&#xff0c;\u9996\u5148\u9700\u8981\u51c6\u786e\u8bc6\u522b\u95ee\u9898\u7c7b\u578b&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class QueryAnalyzer { \u00a0 \/\/ \u68c0\u6d4b\u67e5\u8be2\u662f\u5426\u5728\u77e5\u8bc6\u5e93\u8986\u76d6\u8303\u56f4\u5185 \u00a0 public QueryAnalysisResult analyzeQuery(String query, KnowledgeBaseStats stats) { \u00a0 \u00a0 \u00a0 QueryAnalysisResult result &#061; new QueryAnalysisResult(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u8bed\u4e49\u76f8\u4f3c\u5ea6\u68c0\u6d4b \u00a0 \u00a0 \u00a0 double maxSimilarity &#061; calculateMaxSimilarity(query, stats); \u00a0 \u00a0 \u00a0 result.setInDomain(maxSimilarity &gt; THRESHOLD_DOMAIN); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5173\u952e\u8bcd\u5339\u914d\u68c0\u6d4b \u00a0 \u00a0 \u00a0 Set&lt;String&gt; queryKeywords &#061; extractKeywords(query); \u00a0 \u00a0 \u00a0 Set&lt;String&gt; kbKeywords &#061; stats.getKeywords(); \u00a0 \u00a0 \u00a0 double keywordCoverage &#061; calculateCoverage(queryKeywords, kbKeywords); \u00a0 \u00a0 \u00a0 result.setKeywordCoverage(keywordCoverage); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u4e3b\u9898\u5206\u5e03\u68c0\u6d4b \u00a0 \u00a0 \u00a0 TopicDistribution queryTopic &#061; classifyTopic(query); \u00a0 \u00a0 \u00a0 TopicDistribution kbTopics &#061; stats.getTopicDistribution(); \u00a0 \u00a0 \u00a0 result.setTopicDrift(calculateTopicDrift(queryTopic, kbTopics)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u65f6\u95f4\u8303\u56f4\u68c0\u6d4b&#xff08;\u5bf9\u4e8e\u65f6\u6548\u6027\u67e5\u8be2&#xff09; \u00a0 \u00a0 \u00a0 TimeRange queryTimeRange &#061; extractTimeRange(query); \u00a0 \u00a0 \u00a0 TimeRange kbTimeRange &#061; stats.getTimeCoverage(); \u00a0 \u00a0 \u00a0 result.setTimeCoverage(calculateTimeCoverage(queryTimeRange, kbTimeRange)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return result; \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u591a\u7ef4\u5ea6\u5224\u65ad\u67e5\u8be2\u662f\u5426\u5728\u77e5\u8bc6\u5e93\u5916 \u00a0 public boolean isOutOfKnowledgeBase(QueryAnalysisResult analysis) { \u00a0 \u00a0 \u00a0 return analysis.getMaxSimilarity() &lt; THRESHOLD_SIMILARITY || \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 analysis.getKeywordCoverage() &lt; THRESHOLD_COVERAGE || \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 analysis.getTopicDrift() &gt; THRESHOLD_DRIFT || \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 !analysis.isTimeCovered(); \u00a0 } } <\/p>\n<h5>1.2 \u5206\u5c42\u5904\u7406\u7b56\u7565<\/h5>\n<p>\u6839\u636e\u67e5\u8be2\u8d85\u51fa\u8303\u56f4\u7684\u7a0b\u5ea6&#xff0c;\u91c7\u7528\u4e0d\u540c\u7684\u5904\u7406\u7b56\u7565&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class OODQueryHandler { \u00a0 \/\/ \u5904\u7406\u8d85\u51fa\u77e5\u8bc6\u5e93\u7684\u67e5\u8be2 \u00a0 public Response handleOutOfDomainQuery(String query, QueryAnalysisResult analysis) { \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u8d85\u51fa\u7a0b\u5ea6\u9009\u62e9\u7b56\u7565 \u00a0 \u00a0 \u00a0 if (analysis.getMaxSimilarity() &gt; 0.5) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u90e8\u5206\u76f8\u5173&#xff1a;\u5c1d\u8bd5\u77e5\u8bc6\u6269\u5c55 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return handlePartiallyRelevant(query, analysis); \u00a0 \u00a0 \u00a0 } else if (analysis.getKeywordCoverage() &gt; 0.3) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5173\u952e\u8bcd\u90e8\u5206\u5339\u914d&#xff1a;\u8fdb\u884c\u6982\u5ff5\u8fc1\u79fb \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return handleConceptTransfer(query, analysis); \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5b8c\u5168\u4e0d\u76f8\u5173&#xff1a;\u901a\u7528\u56de\u590d\u6216\u62d2\u7edd \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return handleCompletelyIrrelevant(query, analysis); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u7b56\u75651&#xff1a;\u90e8\u5206\u76f8\u5173\u65f6\u7684\u77e5\u8bc6\u6269\u5c55 \u00a0 private Response handlePartiallyRelevant(String query, QueryAnalysisResult analysis) { \u00a0 \u00a0 \u00a0 \/\/ 1. \u68c0\u7d22\u76f8\u5173\u77e5\u8bc6\u7247\u6bb5 \u00a0 \u00a0 \u00a0 List&lt;KnowledgeFragment&gt; fragments &#061; retrieveRelatedFragments(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u6784\u5efa\u4e0a\u4e0b\u6587 \u00a0 \u00a0 \u00a0 String context &#061; buildContextFromFragments(fragments); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u751f\u6210\u63d0\u793a\u8bcd \u00a0 \u00a0 \u00a0 String prompt &#061; buildExpansionPrompt(query, context, analysis); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u8c03\u7528LLM\u8fdb\u884c\u77e5\u8bc6\u6269\u5c55\u63a8\u7406 \u00a0 \u00a0 \u00a0 String response &#061; llmService.generateWithConstraints(prompt, getConstraints()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u6dfb\u52a0\u4e0d\u786e\u5b9a\u6027\u6807\u6ce8 \u00a0 \u00a0 \u00a0 return new Response(response, ConfidenceLevel.LOW, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;\u6b64\u56de\u7b54\u57fa\u4e8e\u6709\u9650\u7684\u76f8\u5173\u4fe1\u606f\u63a8\u7406\u5f97\u51fa&#xff0c;\u53ef\u80fd\u4e0d\u5b8c\u5168\u51c6\u786e&#034;); \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u7b56\u75652&#xff1a;\u6982\u5ff5\u8fc1\u79fb\u5b66\u4e60 \u00a0 private Response handleConceptTransfer(String query, QueryAnalysisResult analysis) { \u00a0 \u00a0 \u00a0 \/\/ 1. \u63d0\u53d6\u67e5\u8be2\u4e2d\u7684\u6838\u5fc3\u6982\u5ff5 \u00a0 \u00a0 \u00a0 List&lt;String&gt; concepts &#061; extractConcepts(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5bfb\u627e\u76f8\u4f3c\u6982\u5ff5\u6620\u5c04 \u00a0 \u00a0 \u00a0 Map&lt;String, String&gt; conceptMapping &#061; findConceptMapping(concepts); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u91cd\u6784\u67e5\u8be2 \u00a0 \u00a0 \u00a0 String rewrittenQuery &#061; rewriteQueryWithMapping(query, conceptMapping); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u57fa\u4e8e\u91cd\u6784\u67e5\u8be2\u68c0\u7d22 \u00a0 \u00a0 \u00a0 List&lt;KnowledgeFragment&gt; fragments &#061; knowledgeBase.retrieve(rewrittenQuery); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u751f\u6210\u7c7b\u6bd4\u63a8\u7406\u56de\u7b54 \u00a0 \u00a0 \u00a0 return generateAnalogicalResponse(query, fragments, conceptMapping); \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u7b56\u75653&#xff1a;\u5b8c\u5168\u4e0d\u76f8\u5173\u7684\u5904\u7406 \u00a0 private Response handleCompletelyIrrelevant(String query, QueryAnalysisResult analysis) { \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u4e1a\u52a1\u9700\u6c42\u9009\u62e9\u4e0d\u540c\u7b56\u7565 \u00a0 \u00a0 \u00a0 switch (responseStrategy) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case HONEST_DECLINE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return honestDecline(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case GENERAL_KNOWLEDGE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return useGeneralKnowledge(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case QUESTION_CLARIFICATION: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return askForClarification(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case REDIRECTION: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return redirectToOtherResource(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 default: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return defaultResponse(query); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u8bda\u5b9e\u5730\u544a\u77e5\u77e5\u8bc6\u5e93\u9650\u5236 \u00a0 private Response honestDecline(String query) { \u00a0 \u00a0 \u00a0 String response &#061; &#034;\u62b1\u6b49&#xff0c;\u6211\u7684\u77e5\u8bc6\u5e93\u76ee\u524d\u6ca1\u6709\u5173\u4e8e\u300c&#034; &#043; query &#043; &#034;\u300d\u7684\u8be6\u7ec6\u4fe1\u606f\u3002\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;\u6211\u7684\u77e5\u8bc6\u4e3b\u8981\u8986\u76d6\u4ee5\u4e0b\u9886\u57df&#xff1a;\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 getKnowledgeCoverageSummary() &#043; &#034;\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;\u5982\u679c\u60a8\u6709\u5176\u4ed6\u76f8\u5173\u95ee\u9898&#xff0c;\u6211\u5f88\u4e50\u610f\u5e2e\u52a9\u3002&#034;; \u00a0 \u00a0 \u00a0 return new Response(response, ConfidenceLevel.NONE, &#034;\u77e5\u8bc6\u5e93\u672a\u8986\u76d6\u6b64\u95ee\u9898&#034;); \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u4f7f\u7528LLM\u7684\u901a\u7528\u77e5\u8bc6 \u00a0 private Response useGeneralKnowledge(String query) { \u00a0 \u00a0 \u00a0 String prompt &#061; &#034;\u8bf7\u57fa\u4e8e\u60a8\u7684\u901a\u7528\u77e5\u8bc6\u56de\u7b54\u4ee5\u4e0b\u95ee\u9898&#xff1a;\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;\u95ee\u9898&#xff1a;&#034; &#043; query &#043; &#034;\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;\u8bf7\u6ce8\u610f&#xff1a;\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;1. \u5982\u679c\u4fe1\u606f\u4e0d\u786e\u5b9a&#xff0c;\u8bf7\u660e\u786e\u8bf4\u660e\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;2. \u533a\u5206\u4e8b\u5b9e\u548c\u89c2\u70b9\\\\n&#034; &#043; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;3. \u63d0\u4f9b\u4fe1\u606f\u6765\u6e90\u7684\u8bf4\u660e&#034;; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String response &#061; llmService.generate(prompt); \u00a0 \u00a0 \u00a0 return new Response(response, ConfidenceLevel.MEDIUM, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;\u6b64\u56de\u7b54\u57fa\u4e8e\u901a\u7528\u77e5\u8bc6&#xff0c;\u975e\u4e13\u4e1a\u77e5\u8bc6\u5e93\u5185\u5bb9&#034;); \u00a0 } } <\/p>\n<h5>1.3 \u57fa\u4e8e\u7f6e\u4fe1\u5ea6\u7684\u56de\u7b54\u7b56\u7565<\/h5>\n<p>java<\/p>\n<p>public class ConfidenceBasedResponse { \u00a0 private static final Map&lt;ConfidenceLevel, ResponseStrategy&gt; STRATEGY_MAP &#061; Map.of( \u00a0 \u00a0 \u00a0 ConfidenceLevel.HIGH, ResponseStrategy.DIRECT_ANSWER, \u00a0 \u00a0 \u00a0 ConfidenceLevel.MEDIUM, ResponseStrategy.ANSWER_WITH_CAVEAT, \u00a0 \u00a0 \u00a0 ConfidenceLevel.LOW, ResponseStrategy.CONDITIONAL_ANSWER, \u00a0 \u00a0 \u00a0 ConfidenceLevel.NONE, ResponseStrategy.DECLINE_OR_EXTEND \u00a0 ); \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u7f6e\u4fe1\u5ea6\u751f\u6210\u56de\u7b54 \u00a0 public Response generateResponse(String query, RetrievalResult retrievalResult) { \u00a0 \u00a0 \u00a0 ConfidenceLevel confidence &#061; calculateConfidence(query, retrievalResult); \u00a0 \u00a0 \u00a0 ResponseStrategy strategy &#061; STRATEGY_MAP.get(confidence); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return switch (strategy) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DIRECT_ANSWER -&gt; directAnswer(query, retrievalResult); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case ANSWER_WITH_CAVEAT -&gt; answerWithCaveat(query, retrievalResult, confidence); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case CONDITIONAL_ANSWER -&gt; conditionalAnswer(query, retrievalResult); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DECLINE_OR_EXTEND -&gt; declineOrExtend(query, retrievalResult); \u00a0 \u00a0 \u00a0 }; \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u8ba1\u7b97\u56de\u7b54\u7f6e\u4fe1\u5ea6 \u00a0 private ConfidenceLevel calculateConfidence(String query, RetrievalResult result) { \u00a0 \u00a0 \u00a0 \/\/ \u591a\u7ef4\u5ea6\u8ba1\u7b97\u7f6e\u4fe1\u5ea6\u5206\u6570 \u00a0 \u00a0 \u00a0 double score &#061; 0.0; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u68c0\u7d22\u7ed3\u679c\u76f8\u5173\u6027 \u00a0 \u00a0 \u00a0 score &#043;&#061; result.getMaxRelevance() * 0.4; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u7ed3\u679c\u6570\u91cf\u5145\u5206\u6027 \u00a0 \u00a0 \u00a0 score &#043;&#061; Math.min(result.getDocumentCount() \/ 10.0, 1.0) * 0.2; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u7ed3\u679c\u4e00\u81f4\u6027&#xff08;\u591a\u4e2a\u7ed3\u679c\u662f\u5426\u76f8\u4e92\u5370\u8bc1&#xff09; \u00a0 \u00a0 \u00a0 score &#043;&#061; calculateConsistency(result.getDocuments()) * 0.2; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u77e5\u8bc6\u5e93\u8986\u76d6\u7387 \u00a0 \u00a0 \u00a0 score &#043;&#061; calculateCoverage(query, result) * 0.2; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8f6c\u6362\u4e3a\u7f6e\u4fe1\u5ea6\u7b49\u7ea7 \u00a0 \u00a0 \u00a0 if (score &gt;&#061; 0.8) return ConfidenceLevel.HIGH; \u00a0 \u00a0 \u00a0 if (score &gt;&#061; 0.5) return ConfidenceLevel.MEDIUM; \u00a0 \u00a0 \u00a0 if (score &gt;&#061; 0.3) return ConfidenceLevel.LOW; \u00a0 \u00a0 \u00a0 return ConfidenceLevel.NONE; \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u6761\u4ef6\u6027\u56de\u7b54&#xff08;\u4f4e\u7f6e\u4fe1\u5ea6\u65f6&#xff09; \u00a0 private Response conditionalAnswer(String query, RetrievalResult result) { \u00a0 \u00a0 \u00a0 String prompt &#061; &#034;&#034;&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u57fa\u4e8e\u4ee5\u4e0b\u53ef\u80fd\u76f8\u5173\u7684\u4fe1\u606f&#xff0c;\u8bf7\u8c28\u614e\u56de\u7b54\u7528\u6237\u7684\u95ee\u9898\u3002 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u6ce8\u610f&#xff1a;\u8fd9\u4e9b\u4fe1\u606f\u53ef\u80fd\u4e0d\u5b8c\u6574\u6216\u4e0d\u5b8c\u5168\u76f8\u5173&#xff0c;\u56de\u7b54\u65f6\u5e94&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 1. \u660e\u786e\u8bf4\u660e\u4fe1\u606f\u7684\u5c40\u9650\u6027 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 2. \u533a\u5206\u4e8b\u5b9e\u548c\u63a8\u65ad \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 3. \u63d0\u4f9b\u591a\u4e2a\u53ef\u80fd\u6027&#xff08;\u5982\u679c\u6709&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 4. \u5efa\u8bae\u9a8c\u8bc1\u6765\u6e90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u76f8\u5173\u4fe1\u606f&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 %s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u7528\u6237\u95ee\u9898&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u6309\u7167\u4ee5\u4e0b\u683c\u5f0f\u56de\u7b54&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [\u4fe1\u606f\u5c40\u9650\u6027\u8bf4\u660e] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [\u6838\u5fc3\u56de\u7b54] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [\u4e0d\u786e\u5b9a\u6027\u8bf4\u660e] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [\u5efa\u8bae\u9a8c\u8bc1\u6216\u8865\u5145\u4fe1\u606f\u6765\u6e90] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;&#034;&#034;.formatted(formatDocuments(result.getDocuments()), query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String answer &#061; llmService.generate(prompt); \u00a0 \u00a0 \u00a0 return new Response(answer, ConfidenceLevel.LOW, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;\u6b64\u56de\u7b54\u57fa\u4e8e\u6709\u9650\u4e14\u53ef\u80fd\u4e0d\u5b8c\u5168\u76f8\u5173\u7684\u4fe1\u606f&#034;); \u00a0 } } <\/p>\n<h5>1.4 \u4e3b\u52a8\u5b66\u4e60\u548c\u77e5\u8bc6\u7f3a\u53e3\u8bc6\u522b<\/h5>\n<p>java<\/p>\n<p>public class KnowledgeGapDetector { \u00a0 \/\/ \u5b9a\u671f\u5206\u6790\u672a\u8986\u76d6\u67e5\u8be2&#xff0c;\u8bc6\u522b\u77e5\u8bc6\u7f3a\u53e3 \u00a0 public List&lt;KnowledgeGap&gt; detectGaps(List&lt;UnansweredQuery&gt; unansweredQueries) { \u00a0 \u00a0 \u00a0 \/\/ 1. \u805a\u7c7b\u5206\u6790\u76f8\u4f3c\u672a\u56de\u7b54\u67e5\u8be2 \u00a0 \u00a0 \u00a0 Map&lt;String, List&lt;UnansweredQuery&gt;&gt; clusters &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 clusterSimilarQueries(unansweredQueries); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8bc6\u522b\u9ad8\u9891\u77e5\u8bc6\u7f3a\u53e3 \u00a0 \u00a0 \u00a0 List&lt;KnowledgeGap&gt; gaps &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 for (Map.Entry&lt;String, List&lt;UnansweredQuery&gt;&gt; entry : clusters.entrySet()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (entry.getValue().size() &gt;&#061; GAP_THRESHOLD) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeGap gap &#061; extractGapInfo(entry.getKey(), entry.getValue()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 gaps.add(gap); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u8ba1\u7b97\u7f3a\u53e3\u4f18\u5148\u7ea7 \u00a0 \u00a0 \u00a0 gaps.forEach(gap -&gt; gap.setPriority(calculatePriority(gap))); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return gaps.stream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .sorted(Comparator.comparing(KnowledgeGap::getPriority).reversed()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .collect(Collectors.toList()); \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u63d0\u53d6\u77e5\u8bc6\u7f3a\u53e3\u4fe1\u606f \u00a0 private KnowledgeGap extractGapInfo(String clusterId, List&lt;UnansweredQuery&gt; queries) { \u00a0 \u00a0 \u00a0 KnowledgeGap gap &#061; new KnowledgeGap(); \u00a0 \u00a0 \u00a0 gap.setId(clusterId); \u00a0 \u00a0 \u00a0 gap.setFrequency(queries.size()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u63d0\u53d6\u4ee3\u8868\u6027\u67e5\u8be2 \u00a0 \u00a0 \u00a0 gap.setRepresentativeQueries(extractRepresentativeQueries(queries)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5206\u6790\u4e3b\u9898\u5206\u5e03 \u00a0 \u00a0 \u00a0 gap.setTopics(analyzeTopics(queries)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8ba1\u7b97\u7528\u6237\u5f71\u54cd\u5ea6 \u00a0 \u00a0 \u00a0 gap.setUserImpact(calculateUserImpact(queries)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5206\u6790\u4e1a\u52a1\u91cd\u8981\u6027 \u00a0 \u00a0 \u00a0 gap.setBusinessImportance(calculateBusinessImportance(queries)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return gap; \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u751f\u6210\u77e5\u8bc6\u7f3a\u53e3\u62a5\u544a \u00a0 public KnowledgeGapReport generateReport(List&lt;KnowledgeGap&gt; gaps) { \u00a0 \u00a0 \u00a0 KnowledgeGapReport report &#061; new KnowledgeGapReport(); \u00a0 \u00a0 \u00a0 report.setDetectionDate(LocalDate.now()); \u00a0 \u00a0 \u00a0 report.setTotalGaps(gaps.size()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6309\u4f18\u5148\u7ea7\u5206\u7c7b \u00a0 \u00a0 \u00a0 Map&lt;PriorityLevel, List&lt;KnowledgeGap&gt;&gt; gapsByPriority &#061; gaps.stream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .collect(Collectors.groupingBy(gap -&gt; classifyPriority(gap.getPriority()))); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 report.setCriticalGaps(gapsByPriority.getOrDefault(PriorityLevel.CRITICAL, List.of())); \u00a0 \u00a0 \u00a0 report.setHighGaps(gapsByPriority.getOrDefault(PriorityLevel.HIGH, List.of())); \u00a0 \u00a0 \u00a0 report.setMediumGaps(gapsByPriority.getOrDefault(PriorityLevel.MEDIUM, List.of())); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5206\u6790\u8d8b\u52bf \u00a0 \u00a0 \u00a0 report.setTrendAnalysis(analyzeGapTrends(gaps)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u751f\u6210\u5efa\u8bae \u00a0 \u00a0 \u00a0 report.setRecommendations(generateRecommendations(gaps)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return report; \u00a0 } } <\/p>\n<h4>\u4e8c\u3001RAG\u77e5\u8bc6\u5e93\u5982\u4f55\u66f4\u65b0\u6570\u636e&#xff1f;<\/h4>\n<h5>2.1 \u77e5\u8bc6\u5e93\u66f4\u65b0\u67b6\u6784\u8bbe\u8ba1<\/h5>\n<p>java<\/p>\n<p>public class KnowledgeBaseUpdateSystem { \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u7cfb\u7edf\u4e3b\u63a7\u7c7b \u00a0 public class KnowledgeBaseUpdater { \u00a0 \u00a0 \u00a0 private final DataSourceMonitor sourceMonitor; \u00a0 \u00a0 \u00a0 private final UpdateScheduler scheduler; \u00a0 \u00a0 \u00a0 private final UpdateExecutor executor; \u00a0 \u00a0 \u00a0 private final QualityValidator validator; \u00a0 \u00a0 \u00a0 private final VersionManager versionManager; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void initialize() { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u521d\u59cb\u5316\u6570\u636e\u6e90\u76d1\u542c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 sourceMonitor.registerDataSources(getDataSources()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 sourceMonitor.setChangeListener(this::handleDataSourceChange); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8bbe\u7f6e\u5b9a\u65f6\u4efb\u52a1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scheduler.schedulePeriodicUpdates(getUpdateSchedule()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u542f\u52a8\u76d1\u63a7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 startMonitoring(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5904\u7406\u6570\u636e\u6e90\u53d8\u5316 \u00a0 \u00a0 \u00a0 private void handleDataSourceChange(DataSourceChangeEvent event) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (event.getChangeType()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case INCREMENTAL_CHANGE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleIncrementalUpdate(event); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case MAJOR_UPDATE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleMajorUpdate(event); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case SCHEMA_CHANGE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleSchemaUpdate(event); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u589e\u91cf\u66f4\u65b0\u5904\u7406 \u00a0 \u00a0 \u00a0 private void handleIncrementalUpdate(DataSourceChangeEvent event) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 UpdateTask task &#061; UpdateTask.builder() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .type(UpdateType.INCREMENTAL) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .source(event.getSource()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .changes(event.getChanges()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .priority(event.getPriority()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .build(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5f02\u6b65\u6267\u884c\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 executor.executeAsync(task, this::onUpdateComplete); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u5b8c\u6210\u56de\u8c03 \u00a0 \u00a0 \u00a0 private void onUpdateComplete(UpdateResult result) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (result.isSuccess()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u9a8c\u8bc1\u66f4\u65b0\u8d28\u91cf \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ValidationResult validation &#061; validator.validateUpdate(result); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (validation.isValid()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u521b\u5efa\u65b0\u7248\u672c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 versionManager.createVersion(result, validation); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateIndexes(result); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u89e6\u53d1\u7f13\u5b58\u5931\u6548 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 invalidateCaches(result.getAffectedKeys()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8bb0\u5f55\u66f4\u65b0\u65e5\u5fd7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 logUpdate(result, validation); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u56de\u6eda\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 rollbackUpdate(result, validation); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleUpdateFailure(result); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u6570\u636e\u6e90\u76d1\u63a7\u5668 \u00a0 public class DataSourceMonitor { \u00a0 \u00a0 \u00a0 private final Map&lt;String, DataSource&gt; dataSources &#061; new ConcurrentHashMap&lt;&gt;(); \u00a0 \u00a0 \u00a0 private final List&lt;ChangeListener&gt; listeners &#061; new CopyOnWriteArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6ce8\u518c\u6570\u636e\u6e90 \u00a0 \u00a0 \u00a0 public void registerDataSource(String sourceId, DataSource source) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 dataSources.put(sourceId, source); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 startMonitoringSource(sourceId, source); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5f00\u59cb\u76d1\u63a7\u6570\u636e\u6e90 \u00a0 \u00a0 \u00a0 private void startMonitoringSource(String sourceId, DataSource source) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (source.getType()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DATABASE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 monitorDatabase(sourceId, source); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case API: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 monitorApi(sourceId, source); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case FILE_SYSTEM: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 monitorFileSystem(sourceId, source); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case MESSAGE_QUEUE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 monitorMessageQueue(sourceId, source); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u76d1\u63a7\u6570\u636e\u5e93\u53d8\u5316 \u00a0 \u00a0 \u00a0 private void monitorDatabase(String sourceId, DataSource source) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 DatabaseConfig config &#061; (DatabaseConfig) source.getConfig(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b56\u75651: \u57fa\u4e8eCDC&#xff08;Change Data Capture&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (config.supportsCDC()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 startCDCListening(sourceId, config); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b56\u75652: \u57fa\u4e8e\u65f6\u95f4\u6233\u8f6e\u8be2 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 else if (config.hasTimestampColumn()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scheduleTimestampPolling(sourceId, config); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b56\u75653: \u57fa\u4e8e\u7248\u672c\u53f7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 else if (config.hasVersionColumn()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scheduleVersionPolling(sourceId, config); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b56\u75654: \u5168\u91cf\u8f6e\u8be2 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scheduleFullPolling(sourceId, config); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u76d1\u63a7API\u53d8\u5316 \u00a0 \u00a0 \u00a0 private void monitorApi(String sourceId, DataSource source) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ApiConfig config &#061; (ApiConfig) source.getConfig(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636eAPI\u7c7b\u578b\u9009\u62e9\u76d1\u63a7\u7b56\u7565 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (config.isWebhookSupported()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 registerWebhook(sourceId, config); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (config.isPollingSupported()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scheduleApiPolling(sourceId, config); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (config.isEventDriven()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 subscribeToEvents(sourceId, config); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h5>2.2 \u589e\u91cf\u66f4\u65b0\u4e0e\u5168\u91cf\u66f4\u65b0\u7b56\u7565<\/h5>\n<p>java<\/p>\n<p>public class UpdateStrategyManager { \u00a0 \u00a0 \u00a0 \/\/ \u589e\u91cf\u66f4\u65b0\u5b9e\u73b0 \u00a0 public class IncrementalUpdateStrategy implements UpdateStrategy { \u00a0 \u00a0 \u00a0 &#064;Override \u00a0 \u00a0 \u00a0 public UpdateResult execute(UpdateTask task) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u83b7\u53d6\u53d8\u66f4\u6570\u636e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;DataChange&gt; changes &#061; fetchIncrementalChanges(task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8f6c\u6362\u6570\u636e\u683c\u5f0f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;KnowledgeDocument&gt; documents &#061; convertChangesToDocuments(changes); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5e94\u7528\u53d8\u66f4\u5230\u77e5\u8bc6\u5e93 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return applyIncrementalChanges(documents, task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return UpdateResult.failed(task.getId(), e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;DataChange&gt; fetchIncrementalChanges(UpdateTask task) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 DataSource source &#061; task.getSource(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u6570\u636e\u6e90\u7c7b\u578b\u91c7\u7528\u4e0d\u540c\u7684\u589e\u91cf\u83b7\u53d6\u65b9\u5f0f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (source.getType()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DATABASE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return fetchDatabaseChanges(source, task.getLastUpdateTime()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case API: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return fetchApiChanges(source, task.getLastUpdateTime()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case FILE_SYSTEM: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return fetchFileSystemChanges(source, task.getLastUpdateTime()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 default: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new UnsupportedDataSourceException(source.getType()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private UpdateResult applyIncrementalChanges(List&lt;KnowledgeDocument&gt; documents, UpdateTask task) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 UpdateResult result &#061; new UpdateResult(task.getId()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (KnowledgeDocument doc : documents) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u64cd\u4f5c\u7c7b\u578b\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (doc.getOperation()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case INSERT: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase.insert(doc); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.incrementInserted(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case UPDATE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase.update(doc); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.incrementUpdated(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DELETE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase.delete(doc.getId()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.incrementDeleted(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.addError(doc.getId(), e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u7d22\u5f15&#xff08;\u589e\u91cf\u66f4\u65b0&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateIndexesIncrementally(documents); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u5411\u91cf\u5b58\u50a8 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateVectorStoreIncrementally(documents); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return result.success(); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u5168\u91cf\u66f4\u65b0\u5b9e\u73b0 \u00a0 public class FullUpdateStrategy implements UpdateStrategy { \u00a0 \u00a0 \u00a0 &#064;Override \u00a0 \u00a0 \u00a0 public UpdateResult execute(UpdateTask task) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u521b\u5efa\u4e34\u65f6\u77e5\u8bc6\u5e93 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeBase tempKB &#061; createTemporaryKnowledgeBase(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5206\u6279\u52a0\u8f7d\u6570\u636e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 int batchSize &#061; 1000; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 int totalProcessed &#061; 0; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 while (hasMoreData(task)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;KnowledgeDocument&gt; batch &#061; fetchDataBatch(task, batchSize); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5904\u7406\u6279\u6570\u636e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 processBatch(tempKB, batch); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 totalProcessed &#043;&#061; batch.size(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 logProgress(totalProcessed); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u68c0\u67e5\u8d44\u6e90\u4f7f\u7528 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (shouldPauseForGC()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 System.gc(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Thread.sleep(1000); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u6784\u5efa\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 buildIndexes(tempKB); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 6. \u539f\u5b50\u5207\u6362 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return switchKnowledgeBase(tempKB, task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return UpdateResult.failed(task.getId(), e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private UpdateResult switchKnowledgeBase(KnowledgeBase newKB, UpdateTask task) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 UpdateResult result &#061; new UpdateResult(task.getId()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u505c\u6b62\u63a5\u53d7\u65b0\u8bf7\u6c42 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase.setReadOnly(true); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u7b49\u5f85\u5f53\u524d\u8bf7\u6c42\u5b8c\u6210 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 waitForPendingRequests(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5907\u4efd\u5f53\u524d\u77e5\u8bc6\u5e93 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 backupCurrentKnowledgeBase(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u539f\u5b50\u66ff\u6362 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeBase oldKB &#061; knowledgeBase; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase &#061; newKB; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u9a8c\u8bc1\u65b0\u77e5\u8bc6\u5e93 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ValidationResult validation &#061; validateNewKnowledgeBase(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!validation.isValid()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u56de\u6eda \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase &#061; oldKB; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new ValidationException(&#034;\u65b0\u77e5\u8bc6\u5e93\u9a8c\u8bc1\u5931\u8d25&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 6. \u6e05\u7406\u65e7\u8d44\u6e90 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 cleanupOldResources(oldKB); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 7. \u9884\u70ed\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 warmUpCaches(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.setStats(collectStatistics(newKB)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return result.success(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6062\u590d\u5907\u4efd \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 restoreFromBackup(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw e; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u6df7\u5408\u66f4\u65b0\u7b56\u7565&#xff08;\u667a\u80fd\u9009\u62e9&#xff09; \u00a0 public class HybridUpdateStrategy implements UpdateStrategy { \u00a0 \u00a0 \u00a0 &#064;Override \u00a0 \u00a0 \u00a0 public UpdateResult execute(UpdateTask task) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5206\u6790\u66f4\u65b0\u7c7b\u578b\u548c\u89c4\u6a21 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 UpdateAnalysis analysis &#061; analyzeUpdateTask(task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u5206\u6790\u7ed3\u679c\u9009\u62e9\u7b56\u7565 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (shouldUseIncremental(analysis)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return incrementalStrategy.execute(task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (shouldUseDelta(analysis)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return deltaStrategy.execute(task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return fullStrategy.execute(task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private boolean shouldUseIncremental(UpdateAnalysis analysis) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5224\u65ad\u6761\u4ef6&#xff1a;\u53d8\u66f4\u6bd4\u4f8b\u5c0f&#xff0c;\u7ed3\u6784\u4e0d\u53d8&#xff0c;\u65f6\u95f4\u8981\u6c42\u9ad8 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return analysis.getChangeRatio() &lt; 0.1 &amp;&amp; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 !analysis.hasSchemaChanges() &amp;&amp; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 analysis.isTimeSensitive(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private boolean shouldUseDelta(UpdateAnalysis analysis) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5224\u65ad\u6761\u4ef6&#xff1a;\u4e2d\u7b49\u53d8\u66f4\u6bd4\u4f8b&#xff0c;\u6709\u7ed3\u6784\u53d8\u5316\u4f46\u517c\u5bb9 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return analysis.getChangeRatio() &gt;&#061; 0.1 &amp;&amp; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 analysis.getChangeRatio() &lt; 0.5 &amp;&amp; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 analysis.hasCompatibleSchemaChanges(); \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h5>2.3 \u5b9e\u65f6\u66f4\u65b0\u4e0e\u6d41\u5f0f\u5904\u7406<\/h5>\n<p>java<\/p>\n<p>public class RealTimeUpdateProcessor { \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u6d88\u606f\u961f\u5217\u7684\u5b9e\u65f6\u66f4\u65b0 \u00a0 public class MessageQueueUpdater { \u00a0 \u00a0 \u00a0 private final KafkaConsumer&lt;String, UpdateMessage&gt; consumer; \u00a0 \u00a0 \u00a0 private final UpdatePipeline pipeline; \u00a0 \u00a0 \u00a0 private final ExecutorService executor; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void start() { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 consumer.subscribe(List.of(&#034;knowledge-updates&#034;)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 while (true) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ConsumerRecords&lt;String, UpdateMessage&gt; records &#061; consumer.poll(Duration.ofMillis(100)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (ConsumerRecord&lt;String, UpdateMessage&gt; record : record) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5f02\u6b65\u5904\u7406\u6bcf\u6761\u6d88\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 executor.submit(() -&gt; processUpdateMessage(record.value())); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5f02\u6b65\u63d0\u4ea4\u504f\u79fb\u91cf \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 consumer.commitAsync(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void processUpdateMessage(UpdateMessage message) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u9a8c\u8bc1\u6d88\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!validateMessage(message)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.warn(&#034;Invalid update message: {}&#034;, message); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u6839\u636e\u6d88\u606f\u7c7b\u578b\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (message.getType()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DOCUMENT_CREATED: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleDocumentCreate(message); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DOCUMENT_UPDATED: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleDocumentUpdate(message); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DOCUMENT_DELETED: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleDocumentDelete(message); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case BATCH_UPDATE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleBatchUpdate(message); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u53d1\u9001\u786e\u8ba4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 sendAcknowledgment(message); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.error(&#034;Failed to process update message&#034;, e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleProcessingError(message, e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void handleDocumentCreate(UpdateMessage message) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8f6c\u6362\u6d88\u606f\u4e3a\u6587\u6863 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeDocument doc &#061; convertToDocument(message.getPayload()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6dfb\u52a0\u5230\u77e5\u8bc6\u5e93 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase.insert(doc); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u5411\u91cf\u7d22\u5f15&#xff08;\u5f02\u6b65&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 vectorIndex.updateAsync(doc); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u5168\u6587\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 fulltextIndex.index(doc); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 cacheManager.invalidate(doc.getKey()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u89e6\u53d1\u4e0b\u6e38\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 triggerDownstreamProcessing(doc); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u6d41\u5f0f\u5904\u7406\u7ba1\u9053 \u00a0 public class UpdatePipeline { \u00a0 \u00a0 \u00a0 private final List&lt;ProcessingStage&gt; stages; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void process(UpdateEvent event) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u521b\u5efa\u5904\u7406\u4e0a\u4e0b\u6587 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ProcessingContext context &#061; new ProcessingContext(event); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u987a\u5e8f\u6267\u884c\u5904\u7406\u9636\u6bb5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (ProcessingStage stage : stages) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 stage.process(context); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u68c0\u67e5\u662f\u5426\u9700\u8981\u7ec8\u6b62 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (context.shouldTerminate()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 context.addError(stage.getName(), e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u9519\u8bef\u5904\u7406\u7b56\u7565\u51b3\u5b9a\u662f\u5426\u7ee7\u7eed \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!stage.getErrorStrategy().shouldContinue(e)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new PipelineException(&#034;Pipeline failed at stage: &#034; &#043; stage.getName(), e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5904\u7406\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handlePipelineResult(context); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5904\u7406\u9636\u6bb5\u5b9a\u4e49 \u00a0 \u00a0 \u00a0 public interface ProcessingStage { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String getName(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 void process(ProcessingContext context); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ErrorStrategy getErrorStrategy(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5177\u4f53\u5904\u7406\u9636\u6bb5&#xff1a;\u6570\u636e\u9a8c\u8bc1 \u00a0 \u00a0 \u00a0 public class ValidationStage implements ProcessingStage { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#064;Override \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void process(ProcessingContext context) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 UpdateEvent event &#061; context.getEvent(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u683c\u5f0f\u9a8c\u8bc1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!validateFormat(event.getData())) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new ValidationException(&#034;Invalid data format&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5b8c\u6574\u6027\u9a8c\u8bc1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!validateCompleteness(event.getData())) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new ValidationException(&#034;Incomplete data&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u4e00\u81f4\u6027\u9a8c\u8bc1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!validateConsistency(event.getData())) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new ValidationException(&#034;Data consistency check failed&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u4e1a\u52a1\u89c4\u5219\u9a8c\u8bc1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!validateBusinessRules(event.getData())) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new ValidationException(&#034;Business rule violation&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 context.setValidated(true); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5177\u4f53\u5904\u7406\u9636\u6bb5&#xff1a;\u6570\u636e\u8f6c\u6362 \u00a0 \u00a0 \u00a0 public class TransformationStage implements ProcessingStage { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#064;Override \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void process(ProcessingContext context) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!context.isValidated()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new IllegalStateException(&#034;Data not validated&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 RawData rawData &#061; context.getEvent().getData(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u6807\u51c6\u5316\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 StandardizedData standardized &#061; standardize(rawData); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u589e\u5f3a\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 EnhancedData enhanced &#061; enhance(standardized); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5411\u91cf\u5316\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 VectorizedData vectorized &#061; vectorize(enhanced); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u5143\u6570\u636e\u63d0\u53d6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Metadata metadata &#061; extractMetadata(enhanced); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6784\u5efa\u77e5\u8bc6\u6587\u6863 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeDocument doc &#061; KnowledgeDocument.builder() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .content(enhanced.getContent()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .vector(vectorized.getVector()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .metadata(metadata) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .rawData(rawData) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .build(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 context.setDocument(doc); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h5>2.4 \u7248\u672c\u63a7\u5236\u4e0e\u56de\u6eda\u673a\u5236<\/h5>\n<p>java<\/p>\n<p>\u00a0\u00a0\u7bc7\u5e45\u9650\u5236\u4e0b\u9762\u5c31\u53ea\u80fd\u7ed9\u5927\u5bb6\u5c55\u793a\u5c0f\u518c\u90e8\u5206\u5185\u5bb9\u4e86\u3002\u6574\u7406\u4e86\u4e00\u4efd\u6838\u5fc3\u9762\u8bd5\u7b14\u8bb0\u5305\u62ec\u4e86&#xff1a;Java\u9762\u8bd5\u3001Spring\u3001JVM\u3001MyBatis\u3001Redis\u3001MySQL\u3001\u5e76\u53d1\u7f16\u7a0b\u3001\u5fae\u670d\u52a1\u3001Linux\u3001Springboot\u3001SpringCloud\u3001MQ\u3001Kafc<\/p>\n<p>\u9700\u8981\u5168\u5957\u9762\u8bd5\u7b14\u8bb0\u53ca\u7b54\u6848<span class=\"link-card-box\"><span class=\"link-title\">\u3010\u70b9\u51fb\u6b64\u5904\u5373\u53ef\/\u514d\u8d39\u83b7\u53d6\u3011<\/span><span class=\"link-link\"><img decoding=\"async\" class=\"link-link-icon\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260131071652-697dac649ff65.png\" \/>https:\/\/docs.qq.com\/doc\/DQXdYWE9LZ2ZHZ1ho<\/span><\/span><\/p>\n<\/p>\n<p>public class KnowledgeBaseVersionManager { \u00a0 \u00a0 \u00a0 \/\/ \u7248\u672c\u63a7\u5236\u7cfb\u7edf \u00a0 public class VersionControlSystem { \u00a0 \u00a0 \u00a0 private final VersionStore versionStore; \u00a0 \u00a0 \u00a0 private final VersionPolicy versionPolicy; \u00a0 \u00a0 \u00a0 private final RollbackManager rollbackManager; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u521b\u5efa\u65b0\u7248\u672c \u00a0 \u00a0 \u00a0 public VersionInfo createVersion(UpdateResult updateResult, ValidationResult validation) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u751f\u6210\u7248\u672c\u4fe1\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 VersionInfo version &#061; VersionInfo.builder() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .versionId(generateVersionId()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .timestamp(Instant.now()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .updateResult(updateResult) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .validationResult(validation) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .checksum(calculateChecksum()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .metadata(collectMetadata()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .build(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u521b\u5efa\u7248\u672c\u5feb\u7167 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 createSnapshot(version); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u4fdd\u5b58\u7248\u672c\u4fe1\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 versionStore.save(version); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u5e94\u7528\u7248\u672c\u4fdd\u7559\u7b56\u7565 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 applyRetentionPolicy(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u8bb0\u5f55\u7248\u672c\u65e5\u5fd7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 logVersionCreation(version); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return version; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u521b\u5efa\u5feb\u7167 \u00a0 \u00a0 \u00a0 private void createSnapshot(VersionInfo version) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5bfc\u51fa\u5f53\u524d\u72b6\u6001 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeBaseSnapshot snapshot &#061; knowledgeBase.export(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u538b\u7f29\u5feb\u7167 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompressedSnapshot compressed &#061; compressSnapshot(snapshot); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5b58\u50a8\u5feb\u7167 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 snapshotStorage.store(version.getVersionId(), compressed); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u521b\u5efa\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 createSnapshotIndex(version, snapshot); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u56de\u6eda\u5230\u6307\u5b9a\u7248\u672c \u00a0 \u00a0 \u00a0 public RollbackResult rollbackToVersion(String targetVersionId, RollbackOptions options) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u9a8c\u8bc1\u76ee\u6807\u7248\u672c\u5b58\u5728 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 VersionInfo targetVersion &#061; versionStore.get(targetVersionId); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (targetVersion &#061;&#061; null) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw new VersionNotFoundException(targetVersionId); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u521b\u5efa\u5f53\u524d\u7248\u672c\u5feb\u7167&#xff08;\u7528\u4e8e\u53ef\u80fd\u7684\u6062\u590d&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 VersionInfo currentVersion &#061; createVersion(null, null); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u505c\u6b62\u63a5\u53d7\u65b0\u8bf7\u6c42 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase.setReadOnly(true); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u7b49\u5f85\u5904\u7406\u4e2d\u7684\u8bf7\u6c42\u5b8c\u6210 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 waitForPendingOperations(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u52a0\u8f7d\u76ee\u6807\u7248\u672c\u5feb\u7167 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeBaseSnapshot snapshot &#061; loadSnapshot(targetVersionId); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 6. \u6062\u590d\u77e5\u8bc6\u5e93\u72b6\u6001 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 restoreFromSnapshot(snapshot); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 7. \u9a8c\u8bc1\u6062\u590d\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ValidationResult validation &#061; validateRestoredState(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 8. \u91cd\u65b0\u542f\u7528\u77e5\u8bc6\u5e93 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 knowledgeBase.setReadOnly(false); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 9. \u8bb0\u5f55\u56de\u6eda\u65e5\u5fd7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 logRollback(currentVersion, targetVersion, validation); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return RollbackResult.success(currentVersion, targetVersion, validation); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5c1d\u8bd5\u6062\u590d\u4e4b\u524d\u7684\u72b6\u6001 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 emergencyRestore(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception restoreEx) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.error(&#034;Emergency restore failed&#034;, restoreEx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return RollbackResult.failed(e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u589e\u91cf\u7248\u672c\u7ba1\u7406&#xff08;\u9488\u5bf9\u9891\u7e41\u66f4\u65b0&#xff09; \u00a0 public class IncrementalVersionManager { \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u5dee\u5f02\u7684\u7248\u672c\u5b58\u50a8 \u00a0 \u00a0 \u00a0 public class DeltaBasedVersioning { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public VersionInfo createDeltaVersion(UpdateResult updateResult) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u8ba1\u7b97\u4e0e\u4e0a\u4e00\u7248\u672c\u7684\u5dee\u5f02 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeBaseDelta delta &#061; calculateDelta(updateResult); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5b58\u50a8\u5dee\u5f02 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 deltaStorage.store(delta); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u521b\u5efa\u7248\u672c\u94fe \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 VersionInfo version &#061; createVersionFromDelta(delta); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 versionStore.save(version); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u66f4\u65b0\u7248\u672c\u6307\u9488 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateCurrentVersion(version); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return version; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8ba1\u7b97\u5dee\u5f02 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private KnowledgeBaseDelta calculateDelta(UpdateResult updateResult) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeBaseDelta delta &#061; new KnowledgeBaseDelta(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6536\u96c6\u6240\u6709\u53d8\u66f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.setInserts(collectInsertedDocuments()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.setUpdates(collectUpdatedDocuments()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.setDeletes(collectDeletedDocumentIds()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8ba1\u7b97\u5143\u6570\u636e\u5dee\u5f02 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.setMetadataChanges(calculateMetadataChanges()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8ba1\u7b97\u7d22\u5f15\u5dee\u5f02 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.setIndexChanges(calculateIndexChanges()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return delta; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5e94\u7528\u5dee\u5f02 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void applyDelta(KnowledgeBaseDelta delta) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5e94\u7528\u6587\u6863\u53d8\u66f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.getInserts().forEach(knowledgeBase::insert); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.getUpdates().forEach(knowledgeBase::update); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 delta.getDeletes().forEach(knowledgeBase::delete); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5e94\u7528\u5143\u6570\u636e\u53d8\u66f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 applyMetadataChanges(delta.getMetadataChanges()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5e94\u7528\u7d22\u5f15\u53d8\u66f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 applyIndexChanges(delta.getIndexChanges()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u9a8c\u8bc1\u5e94\u7528\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 validateDeltaApplication(delta); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h4>\u4e09\u3001\u5e38\u89c1RAG\u95ee\u9898\u53ca\u89e3\u51b3\u65b9\u6848&#xff08;\u8be6\u7ec6\u89e3\u6790&#xff09;<\/h4>\n<h5>3.1 \u68c0\u7d22\u8d28\u91cf\u95ee\u9898\u53ca\u4f18\u5316\u65b9\u6848<\/h5>\n<h6>\u95ee\u98981&#xff1a;\u68c0\u7d22\u7ed3\u679c\u4e0d\u76f8\u5173<\/h6>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>\u5411\u91cf\u8868\u793a\u4e0d\u51c6\u786e<\/li>\n<li>\u67e5\u8be2\u4e0e\u6587\u6863\u7684\u8bed\u4e49\u9e3f\u6c9f<\/li>\n<li>\u77e5\u8bc6\u5e93\u6587\u6863\u8d28\u91cf\u5dee<\/li>\n<li>\u7d22\u5f15\u7b56\u7565\u4e0d\u5408\u7406<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class RetrievalOptimizer { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u591a\u9636\u6bb5\u68c0\u7d22\u4f18\u5316 \u00a0 public class MultiStageRetrieval { \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; retrieveWithStages(String query) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u9636\u6bb51&#xff1a;\u521d\u6b65\u53ec\u56de&#xff08;\u9ad8\u53ec\u56de\u7387&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; initialResults &#061; stage1Retrieval(query, 100); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u9636\u6bb52&#xff1a;\u91cd\u65b0\u6392\u5e8f&#xff08;\u9ad8\u7cbe\u5ea6&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; rerankedResults &#061; stage2Reranking(query, initialResults); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u9636\u6bb53&#xff1a;\u591a\u6837\u6027\u8c03\u6574 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; diverseResults &#061; stage3Diversification(rerankedResults); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u9636\u6bb54&#xff1a;\u76f8\u5173\u6027\u8fc7\u6ee4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; filteredResults &#061; stage4Filtering(query, diverseResults); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return filteredResults.subList(0, Math.min(10, filteredResults.size())); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;Document&gt; stage1Retrieval(String query, int k) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6df7\u5408\u68c0\u7d22\u7b56\u7565 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; results &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5411\u91cf\u68c0\u7d22&#xff08;\u8bed\u4e49\u76f8\u4f3c\u5ea6&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 results.addAll(vectorRetriever.retrieve(query, k\/2)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5173\u952e\u8bcd\u68c0\u7d22&#xff08;BM25&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 results.addAll(keywordRetriever.retrieve(query, k\/4)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5143\u6570\u636e\u8fc7\u6ee4\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 results.addAll(metadataRetriever.retrieve(query, k\/4)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return results; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;Document&gt; stage2Reranking(String query, List&lt;Document&gt; candidates) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4f7f\u7528\u4ea4\u53c9\u7f16\u7801\u5668\u8fdb\u884c\u7cbe\u6392 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CrossEncoderReranker reranker &#061; new CrossEncoderReranker(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return candidates.stream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .map(doc -&gt; new ScoredDocument(doc, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 reranker.score(query, doc.getContent()))) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .sorted(Comparator.comparing(ScoredDocument::getScore).reversed()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .map(ScoredDocument::getDocument) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .collect(Collectors.toList()); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u67e5\u8be2\u6269\u5c55\u4e0e\u91cd\u6784 \u00a0 public class QueryOptimizer { \u00a0 \u00a0 \u00a0 public String optimizeQuery(String originalQuery, QueryContext context) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u67e5\u8be2\u89e3\u6790 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ParsedQuery parsed &#061; parseQuery(originalQuery); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u540c\u4e49\u8bcd\u6269\u5c55 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String expanded &#061; expandSynonyms(parsed); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u8bed\u4e49\u91cd\u6784 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String rewritten &#061; semanticRewrite(expanded, context); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u6dfb\u52a0\u7ea6\u675f\u6761\u4ef6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String constrained &#061; addConstraints(rewritten, context); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return constrained; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String semanticRewrite(String query, QueryContext context) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4f7f\u7528LLM\u8fdb\u884c\u67e5\u8be2\u91cd\u6784 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String prompt &#061; &#034;&#034;&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u5c06\u7528\u6237\u67e5\u8be2\u91cd\u6784\u4e3a\u66f4\u9002\u5408\u68c0\u7d22\u7cfb\u7edf\u7406\u89e3\u7684\u7248\u672c\u3002 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8981\u6c42&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 1. \u4fdd\u6301\u539f\u610f\u4e0d\u53d8 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 2. \u660e\u786e\u5316\u6a21\u7cca\u6982\u5ff5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 3. \u8865\u5145\u9690\u542b\u7684\u4e0a\u4e0b\u6587 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 4. \u7ed3\u6784\u5316\u590d\u6742\u67e5\u8be2 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u539f\u59cb\u67e5\u8be2&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u4e0a\u4e0b\u6587&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u8f93\u51fa\u91cd\u6784\u540e\u7684\u67e5\u8be2&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;&#034;&#034;.formatted(query, context); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return llmService.generate(prompt); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u6df7\u5408\u68c0\u7d22\u7b56\u7565 \u00a0 public class HybridRetrieval { \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; hybridRetrieve(String query, HybridConfig config) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5e76\u884c\u6267\u884c\u591a\u79cd\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture&lt;List&lt;Document&gt;&gt; vectorFuture &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.supplyAsync(() -&gt; vectorRetrieve(query)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture&lt;List&lt;Document&gt;&gt; keywordFuture &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.supplyAsync(() -&gt; keywordRetrieve(query)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture&lt;List&lt;Document&gt;&gt; semanticFuture &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.supplyAsync(() -&gt; semanticRetrieve(query)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b49\u5f85\u6240\u6709\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.allOf(vectorFuture, keywordFuture, semanticFuture).join(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u878d\u5408\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return fuseResults( \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 vectorFuture.join(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 keywordFuture.join(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 semanticFuture.join(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 config \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;Document&gt; fuseResults(List&lt;Document&gt; vectorResults, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; keywordResults, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; semanticResults, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 HybridConfig config) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5f52\u4e00\u5316\u5206\u6570 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Map&lt;String, Double&gt; scores &#061; new HashMap&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u52a0\u6743\u878d\u5408 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 addScores(scores, vectorResults, config.getVectorWeight()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 addScores(scores, keywordResults, config.getKeywordWeight()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 addScores(scores, semanticResults, config.getSemanticWeight()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u6392\u5e8f\u5e76\u53bb\u91cd \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return scores.entrySet().stream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .sorted(Map.Entry.&lt;String, Double&gt;comparingByValue().reversed()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .map(entry -&gt; documentMap.get(entry.getKey())) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .distinct() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .limit(config.getMaxResults()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .collect(Collectors.toList()); \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h6>\u95ee\u98982&#xff1a;\u68c0\u7d22\u6548\u7387\u4f4e\u4e0b<\/h6>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>\u5411\u91cf\u68c0\u7d22\u590d\u6742\u5ea6\u9ad8<\/li>\n<li>\u7d22\u5f15\u672a\u4f18\u5316<\/li>\n<li>\u786c\u4ef6\u8d44\u6e90\u4e0d\u8db3<\/li>\n<li>\u67e5\u8be2\u590d\u6742\u5ea6\u9ad8<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class RetrievalEfficiencyOptimizer { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u7d22\u5f15\u4f18\u5316 \u00a0 public class IndexOptimization { \u00a0 \u00a0 \u00a0 public void optimizeIndexes(KnowledgeBase kb) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5411\u91cf\u7d22\u5f15\u4f18\u5316 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 optimizeVectorIndex(kb); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5012\u6392\u7d22\u5f15\u4f18\u5316 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 optimizeInvertedIndex(kb); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5143\u6570\u636e\u7d22\u5f15\u4f18\u5316 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 optimizeMetadataIndex(kb); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u5206\u5c42\u7d22\u5f15\u7b56\u7565 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 createHierarchicalIndexes(kb); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void optimizeVectorIndex(KnowledgeBase kb) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u9009\u62e9\u5408\u9002\u7684ANN\u7b97\u6cd5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (vectorIndexType) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case &#034;HNSW&#034;: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 buildHNSWIndex(kb.getVectors()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case &#034;IVF&#034;: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 buildIVFIndex(kb.getVectors()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case &#034;PQ&#034;: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 buildPQIndex(kb.getVectors()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8c03\u6574\u53c2\u6570 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 tuneIndexParameters(kb.getStatistics()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u9884\u6784\u5efa\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 prebuildIndexForCommonQueries(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void createHierarchicalIndexes(KnowledgeBase kb) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u6587\u6863\u805a\u7c7b\u521b\u5efa\u5c42\u7ea7\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Cluster&gt; clusters &#061; clusterDocuments(kb.getDocuments()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (Cluster cluster : clusters) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4e3a\u6bcf\u4e2a\u7c07\u521b\u5efa\u4e13\u95e8\u7684\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 createClusterIndex(cluster); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6784\u5efa\u7c07\u6458\u8981\u5411\u91cf \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 createClusterSummaryVector(cluster); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5efa\u7acb\u7c07\u95f4\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 createInterClusterIndex(clusters); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u7f13\u5b58\u7b56\u7565\u4f18\u5316 \u00a0 public class RetrievalCache { \u00a0 \u00a0 \u00a0 private final Cache&lt;String, List&lt;Document&gt;&gt; queryCache; \u00a0 \u00a0 \u00a0 private final Cache&lt;String, List&lt;Document&gt;&gt; semanticCache; \u00a0 \u00a0 \u00a0 private final Cache&lt;String, byte[]&gt; embeddingCache; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; retrieveWithCache(String query) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u67e5\u8be2\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String cacheKey &#061; generateCacheKey(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; cached &#061; queryCache.getIfPresent(cacheKey); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (cached !&#061; null) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 cacheStats.hit(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return cached; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 cacheStats.miss(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8bed\u4e49\u7f13\u5b58&#xff08;\u76f8\u4f3c\u67e5\u8be2&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; semanticCached &#061; findInSemanticCache(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (semanticCached !&#061; null) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return semanticCached; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u6267\u884c\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; results &#061; doRetrieval(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u66f4\u65b0\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateCaches(query, results); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return results; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void updateCaches(String query, List&lt;Document&gt; results) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u67e5\u8be2\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 queryCache.put(generateCacheKey(query), results); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u8bed\u4e49\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateSemanticCache(query, results); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u70ed\u95e8\u6587\u6863\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updatePopularDocumentCache(results); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void updateSemanticCache(String query, List&lt;Document&gt; results) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u751f\u6210\u67e5\u8be2\u5411\u91cf \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 float[] queryVector &#061; embeddingService.embed(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u67e5\u627e\u8bed\u4e49\u76f8\u4f3c\u7684\u7f13\u5b58\u6761\u76ee \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (CacheEntry entry : semanticCache.getAll()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 float similarity &#061; cosineSimilarity(queryVector, entry.getQueryVector()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (similarity &gt; 0.9) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5408\u5e76\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; merged &#061; mergeResults(results, entry.getResults()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 semanticCache.put(entry.getKey(), merged); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6dfb\u52a0\u65b0\u6761\u76ee \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 semanticCache.put(generateSemanticKey(query), results); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u8fd1\u4f3c\u6700\u8fd1\u90bb\u68c0\u7d22\u4f18\u5316 \u00a0 public class ANNRetrievalOptimizer { \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; approximateRetrieve(String query, int k, double recallTarget) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u81ea\u9002\u5e94\u53c2\u6570\u8c03\u6574 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 SearchParameters params &#061; adjustParametersByRecallTarget(recallTarget); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u591a\u5c42\u68c0\u7d22\u7b56\u7565 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; results &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b2c\u4e00\u5c42&#xff1a;\u7c97\u7c92\u5ea6\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 results.addAll(coarseGrainedRetrieve(query, k * 2, params)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b2c\u4e8c\u5c42&#xff1a;\u7cbe\u7c92\u5ea6\u68c0\u7d22&#xff08;\u5728\u7c97\u7c92\u5ea6\u7ed3\u679c\u4e0a&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 results &#061; fineGrainedRetrieve(query, results, k, params); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b2c\u4e09\u5c42&#xff1a;\u91cd\u6392\u5e8f&#xff08;\u5982\u679c\u9700\u8981\u66f4\u9ad8\u7cbe\u5ea6&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (requiresReranking(results, recallTarget)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 results &#061; rerankWithExactSimilarity(query, results); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return results.subList(0, Math.min(k, results.size())); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private SearchParameters adjustParametersByRecallTarget(double recallTarget) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 SearchParameters params &#061; new SearchParameters(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u53ec\u56de\u7387\u76ee\u6807\u8c03\u6574\u641c\u7d22\u53c2\u6570 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (recallTarget &gt;&#061; 0.95) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 params.setEfSearch(1000); \/\/ \u6269\u5927\u641c\u7d22\u8303\u56f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 params.setMaxCandidates(10000); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (recallTarget &gt;&#061; 0.85) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 params.setEfSearch(500); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 params.setMaxCandidates(5000); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 params.setEfSearch(200); \/\/ \u5e73\u8861\u7cbe\u5ea6\u548c\u901f\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 params.setMaxCandidates(1000); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return params; \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h5>3.2 \u751f\u6210\u8d28\u91cf\u95ee\u9898\u53ca\u4f18\u5316\u65b9\u6848<\/h5>\n<h6>\u95ee\u98981&#xff1a;\u751f\u6210\u4e0e\u68c0\u7d22\u5185\u5bb9\u4e0d\u4e00\u81f4&#xff08;\u5e7b\u89c9\u95ee\u9898&#xff09;<\/h6>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>LLM\u8fc7\u5ea6\u4f9d\u8d56\u81ea\u8eab\u77e5\u8bc6<\/li>\n<li>\u68c0\u7d22\u5185\u5bb9\u672a\u5145\u5206\u52a0\u6743<\/li>\n<li>\u63d0\u793a\u5de5\u7a0b\u4e0d\u5b8c\u5584<\/li>\n<li>\u4e0a\u4e0b\u6587\u7a97\u53e3\u9650\u5236<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class GenerationConsistencyEnforcer { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u57fa\u4e8e\u68c0\u7d22\u5185\u5bb9\u7684\u7ea6\u675f\u751f\u6210 \u00a0 public class ConstrainedGeneration { \u00a0 \u00a0 \u00a0 public String generateWithConstraints(String query, List&lt;Document&gt; retrievedDocs) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u63d0\u53d6\u68c0\u7d22\u5185\u5bb9\u7684\u5173\u952e\u4fe1\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Map&lt;String, Object&gt; constraints &#061; extractConstraints(retrievedDocs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u6784\u5efa\u7ea6\u675f\u63d0\u793a\u8bcd \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String constrainedPrompt &#061; buildConstrainedPrompt(query, retrievedDocs, constraints); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u6267\u884c\u7ea6\u675f\u751f\u6210 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String draftResponse &#061; llmService.generate(constrainedPrompt); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u4e8b\u5b9e\u6027\u68c0\u67e5\u4e0e\u4fee\u6b63 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String verifiedResponse &#061; verifyAndCorrect(draftResponse, retrievedDocs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u6dfb\u52a0\u5f15\u7528\u6807\u8bb0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String finalResponse &#061; addCitations(verifiedResponse, retrievedDocs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return finalResponse; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String buildConstrainedPrompt(String query, List&lt;Document&gt; docs, Map&lt;String, Object&gt; constraints) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return &#034;&#034;&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u57fa\u4e8e\u4ee5\u4e0b\u68c0\u7d22\u5230\u7684\u4fe1\u606f\u56de\u7b54\u95ee\u9898\u3002\u5fc5\u987b\u9075\u5b88\u4ee5\u4e0b\u7ea6\u675f&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u7ea6\u675f\u6761\u4ef6&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 1. \u53ea\u4f7f\u7528\u63d0\u4f9b\u7684\u68c0\u7d22\u4fe1\u606f&#xff0c;\u4e0d\u8981\u6dfb\u52a0\u5916\u90e8\u77e5\u8bc6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 2. \u5982\u679c\u4fe1\u606f\u4e0d\u8db3&#xff0c;\u8bf7\u660e\u786e\u8bf4\u660e&#034;\u6839\u636e\u63d0\u4f9b\u7684\u4fe1\u606f&#xff0c;\u65e0\u6cd5\u5b8c\u5168\u56de\u7b54&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 3. \u5173\u952e\u6570\u636e\u5fc5\u987b\u6765\u81ea\u68c0\u7d22\u5185\u5bb9 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 4. \u4fdd\u6301\u56de\u7b54\u4e0e\u68c0\u7d22\u4fe1\u606f\u4e00\u81f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u68c0\u7d22\u5230\u7684\u4fe1\u606f&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 %s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u7528\u6237\u95ee\u9898&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u4e25\u683c\u6309\u7167\u4ee5\u4e0b\u683c\u5f0f\u56de\u7b54&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [\u56de\u7b54\u6b63\u6587] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [\u6570\u636e\u6765\u6e90\u8bf4\u660e] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 [\u4fe1\u606f\u5b8c\u6574\u6027\u8bf4\u660e] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;&#034;&#034;.formatted(formatDocuments(docs), query); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String verifyAndCorrect(String response, List&lt;Document&gt; docs) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u63d0\u53d6\u56de\u7b54\u4e2d\u7684\u5173\u952e\u4e8b\u5b9e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Fact&gt; claimedFacts &#061; extractFacts(response); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u9a8c\u8bc1\u6bcf\u4e2a\u4e8b\u5b9e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Fact&gt; verifiedFacts &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (Fact fact : claimedFacts) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 VerificationResult result &#061; verifyFact(fact, docs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (result.isVerified()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 verifiedFacts.add(fact); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (result.isContradicted()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4fee\u6b63\u77db\u76fe\u4e8b\u5b9e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Fact corrected &#061; correctFact(fact, result.getCorrectInfo()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 verifiedFacts.add(corrected); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u79fb\u9664\u672a\u9a8c\u8bc1\u4e8b\u5b9e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.warn(&#034;Removing unverified fact: {}&#034;, fact); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u91cd\u6784\u56de\u7b54 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return reconstructResponse(verifiedFacts, response); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u4e8b\u5b9e\u6027\u68c0\u67e5\u4e0e\u4fee\u6b63\u7ba1\u9053 \u00a0 public class FactCheckingPipeline { \u00a0 \u00a0 \u00a0 public FactCheckResult checkResponse(String response, List&lt;Document&gt; sources) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 FactCheckResult result &#061; new FactCheckResult(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u4e8b\u5b9e\u63d0\u53d6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;ClaimedFact&gt; claimedFacts &#061; extractClaims(response); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u591a\u7ef4\u5ea6\u9a8c\u8bc1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (ClaimedFact fact : claimedFacts) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 FactVerification verification &#061; verifyFact(fact, sources); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.addVerification(verification); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7edf\u8ba1\u9a8c\u8bc1\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (verification.getStatus()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case SUPPORTED: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.incrementSupported(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case CONTRADICTED: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.incrementContradicted(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case UNVERIFIED: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.incrementUnverified(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u8ba1\u7b97\u6574\u4f53\u7f6e\u4fe1\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.setConfidenceScore(calculateConfidence(result)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u751f\u6210\u4fee\u6b63\u5efa\u8bae \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (result.getContradictedCount() &gt; 0) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 result.setCorrectionSuggestions(generateCorrections(result)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return result; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private FactVerification verifyFact(ClaimedFact fact, List&lt;Document&gt; sources) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u591a\u8bc1\u636e\u9a8c\u8bc1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Evidence&gt; supportingEvidences &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Evidence&gt; contradictingEvidences &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (Document doc : sources) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Evidence evidence &#061; checkEvidence(fact, doc); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (evidence.supports()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 supportingEvidences.add(evidence); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (evidence.contradicts()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 contradictingEvidences.add(evidence); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5224\u65ad\u4e8b\u5b9e\u72b6\u6001 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!supportingEvidences.isEmpty() &amp;&amp; contradictingEvidences.isEmpty()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return FactVerification.supported(fact, supportingEvidences); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (!contradictingEvidences.isEmpty()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return FactVerification.contradicted(fact, contradictingEvidences); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return FactVerification.unverified(fact); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u5f15\u7528\u589e\u5f3a\u751f\u6210 \u00a0 public class CitationAwareGeneration { \u00a0 \u00a0 \u00a0 public CitedResponse generateWithCitations(String query, List&lt;Document&gt; retrievedDocs) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5bf9\u68c0\u7d22\u6587\u6863\u8fdb\u884c\u6bb5\u843d\u5212\u5206 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;DocumentChunk&gt; chunks &#061; chunkDocuments(retrievedDocs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u6784\u5efa\u5e26\u6709\u5f15\u7528\u7684\u4e0a\u4e0b\u6587 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String contextWithCitations &#061; buildContextWithCitations(chunks); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u63d0\u793a\u6a21\u578b\u751f\u6210\u5e26\u5f15\u7528\u7684\u56de\u7b54 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String prompt &#061; buildCitationPrompt(query, contextWithCitations); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u751f\u6210\u56de\u7b54 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String response &#061; llmService.generate(prompt); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u89e3\u6790\u548c\u9a8c\u8bc1\u5f15\u7528 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Citation&gt; citations &#061; parseCitations(response); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 validateCitations(citations, chunks); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 6. \u6784\u5efa\u6700\u7ec8\u54cd\u5e94 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return CitedResponse.builder() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .content(removeCitationMarkers(response)) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .citations(citations) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .sourceDocuments(retrievedDocs) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .build(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String buildContextWithCitations(List&lt;DocumentChunk&gt; chunks) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 StringBuilder context &#061; new StringBuilder(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (int i &#061; 0; i &lt; chunks.size(); i&#043;&#043;) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 DocumentChunk chunk &#061; chunks.get(i); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 context.append(String.format(&#034;[%d] %s\\\\n&#034;, i &#043; 1, chunk.getContent())); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return context.toString(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String buildCitationPrompt(String query, String context) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return &#034;&#034;&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u57fa\u4e8e\u4ee5\u4e0b\u5e26\u7f16\u53f7\u7684\u53c2\u8003\u8d44\u6599\u56de\u7b54\u95ee\u9898\u3002 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8981\u6c42&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 1. \u56de\u7b54\u4e2d\u7684\u6bcf\u4e2a\u91cd\u8981\u9648\u8ff0\u90fd\u5fc5\u987b\u5f15\u7528\u5bf9\u5e94\u7684\u8d44\u6599\u7f16\u53f7&#xff0c;\u683c\u5f0f\u4e3a[\u7f16\u53f7] \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 2. \u5982\u679c\u6ca1\u6709\u76f8\u5173\u8d44\u6599\u652f\u6301&#xff0c;\u8bf7\u8bf4\u660e&#034;\u6ca1\u6709\u627e\u5230\u76f8\u5173\u8d44\u6599&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 3. \u5982\u679c\u8d44\u6599\u4e4b\u95f4\u5b58\u5728\u77db\u76fe&#xff0c;\u8bf7\u6307\u51fa\u5e76\u8bf4\u660e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 4. \u53ea\u4f7f\u7528\u63d0\u4f9b\u7684\u8d44\u6599&#xff0c;\u4e0d\u8981\u6dfb\u52a0\u5916\u90e8\u77e5\u8bc6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u53c2\u8003\u8d44\u6599&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 %s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u95ee\u9898&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u751f\u6210\u5e26\u5f15\u7528\u7684\u56de\u7b54&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;&#034;&#034;.formatted(context, query); \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h6>\u95ee\u98982&#xff1a;\u751f\u6210\u5185\u5bb9\u5197\u4f59\u6216\u4fe1\u606f\u4e0d\u8db3<\/h6>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>\u68c0\u7d22\u5185\u5bb9\u91cd\u590d<\/li>\n<li>\u751f\u6210\u6a21\u578b\u8fc7\u5ea6\u89e3\u91ca<\/li>\n<li>\u7f3a\u4e4f\u5185\u5bb9\u89c4\u5212<\/li>\n<li>\u672a\u8003\u8651\u7528\u6237\u80cc\u666f\u77e5\u8bc6<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class GenerationQualityOptimizer { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u5185\u5bb9\u89c4\u5212\u4e0e\u6458\u8981 \u00a0 public class ContentPlanner { \u00a0 \u00a0 \u00a0 public String generateWithPlanning(String query, List&lt;Document&gt; docs) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5185\u5bb9\u89c4\u5212\u9636\u6bb5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ContentPlan plan &#061; createContentPlan(query, docs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u4fe1\u606f\u63d0\u53d6\u4e0e\u7ec4\u7ec7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 StructuredInfo structuredInfo &#061; extractAndOrganizeInfo(docs, plan); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u751f\u6210\u8349\u7a3f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String draft &#061; generateDraft(structuredInfo, plan); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u4f18\u5316\u4e0e\u538b\u7f29 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String optimized &#061; optimizeAndCompress(draft, plan); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return optimized; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private ContentPlan createContentPlan(String query, List&lt;Document&gt; docs) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4f7f\u7528\u5c0f\u6a21\u578b\u6216\u89c4\u5219\u751f\u6210\u5185\u5bb9\u5927\u7eb2 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String planningPrompt &#061; &#034;&#034;&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u6839\u636e\u7528\u6237\u95ee\u9898\u548c\u76f8\u5173\u8d44\u6599&#xff0c;\u5236\u5b9a\u56de\u7b54\u7684\u5185\u5bb9\u8ba1\u5212\u3002 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8981\u6c42&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 1. \u786e\u5b9a\u6838\u5fc3\u8981\u70b9&#xff08;\u4e0d\u8d85\u8fc73\u4e2a&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 2. \u4e3a\u6bcf\u4e2a\u8981\u70b9\u5206\u914d\u6743\u91cd \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 3. \u89c4\u5212\u56de\u7b54\u7ed3\u6784 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 4. \u786e\u5b9a\u8be6\u7ec6\u7a0b\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 5. \u8bc6\u522b\u9700\u8981\u5f3a\u8c03\u7684\u5173\u952e\u4fe1\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u7528\u6237\u95ee\u9898&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u76f8\u5173\u8d44\u6599\u6458\u8981&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u8f93\u51faJSON\u683c\u5f0f\u7684\u5185\u5bb9\u8ba1\u5212&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;&#034;&#034;.formatted(query, summarizeDocuments(docs)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String planJson &#061; smallLlm.generate(planningPrompt); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return parseContentPlan(planJson); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String optimizeAndCompress(String draft, ContentPlan plan) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u53bb\u9664\u5197\u4f59 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String deduplicated &#061; removeDuplicates(draft); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u7b80\u5316\u590d\u6742\u8868\u8fbe \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String simplified &#061; simplifyLanguage(deduplicated); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u786e\u4fdd\u4fe1\u606f\u5b8c\u6574\u6027 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String complete &#061; ensureCompleteness(simplified, plan); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u8c03\u6574\u957f\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return adjustLength(complete, plan.getTargetLength()); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u81ea\u9002\u5e94\u8be6\u7ec6\u7a0b\u5ea6\u63a7\u5236 \u00a0 public class DetailLevelController { \u00a0 \u00a0 \u00a0 public String generateWithAdaptiveDetail(String query, List&lt;Document&gt; docs, UserProfile user) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5206\u6790\u67e5\u8be2\u590d\u6742\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ComplexityLevel complexity &#061; analyzeQueryComplexity(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5206\u6790\u7528\u6237\u80cc\u666f\u77e5\u8bc6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeLevel userKnowledge &#061; assessUserKnowledge(user, query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u786e\u5b9a\u8be6\u7ec6\u7a0b\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 DetailLevel detailLevel &#061; determineDetailLevel(complexity, userKnowledge); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u6839\u636e\u8be6\u7ec6\u7a0b\u5ea6\u751f\u6210\u56de\u7b54 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return generateWithDetailControl(query, docs, detailLevel); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private DetailLevel determineDetailLevel(ComplexityLevel complexity, KnowledgeLevel userKnowledge) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u89c4\u5219\u6216\u5b66\u4e60\u6a21\u578b\u786e\u5b9a\u8be6\u7ec6\u7a0b\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (userKnowledge &#061;&#061; KnowledgeLevel.EXPERT) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return DetailLevel.CONCISE; \/\/ \u4e13\u5bb6\u9700\u8981\u7b80\u6d01 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (complexity &#061;&#061; ComplexityLevel.HIGH &amp;&amp; userKnowledge &#061;&#061; KnowledgeLevel.BEGINNER) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return DetailLevel.VERY_DETAILED; \/\/ \u521d\u5b66\u8005\u9762\u5bf9\u590d\u6742\u95ee\u9898\u9700\u8981\u8be6\u7ec6\u89e3\u91ca \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (complexity &#061;&#061; ComplexityLevel.LOW) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return DetailLevel.MODERATE; \/\/ \u7b80\u5355\u95ee\u9898\u4e2d\u7b49\u8be6\u7ec6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return DetailLevel.DETAILED; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String generateWithDetailControl(String query, List&lt;Document&gt; docs, DetailLevel detailLevel) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String prompt &#061; &#034;&#034;&#034; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8bf7\u6839\u636e\u6307\u5b9a\u7684\u8be6\u7ec6\u7a0b\u5ea6\u56de\u7b54\u7528\u6237\u95ee\u9898\u3002 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u8be6\u7ec6\u7a0b\u5ea6\u8981\u6c42&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u5177\u4f53\u8981\u6c42&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 %s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u53c2\u8003\u8d44\u6599&#xff1a; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 %s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u95ee\u9898&#xff1a;%s \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 &#034;&#034;&#034;.formatted( \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 detailLevel.getName(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 detailLevel.getGuidelines(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 formatDocuments(docs), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 query \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return llmService.generate(prompt); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u4fe1\u606f\u5bc6\u5ea6\u4f18\u5316 \u00a0 public class InformationDensityOptimizer { \u00a0 \u00a0 \u00a0 public String optimizeDensity(String response, double targetDensity) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u8ba1\u7b97\u5f53\u524d\u4fe1\u606f\u5bc6\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 double currentDensity &#061; calculateInformationDensity(response); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5206\u6790\u5bc6\u5ea6\u95ee\u9898 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 DensityAnalysis analysis &#061; analyzeDensity(response); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u6839\u636e\u76ee\u6807\u5bc6\u5ea6\u8c03\u6574 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (currentDensity &lt; targetDensity) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u589e\u52a0\u4fe1\u606f\u5bc6\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return increaseDensity(response, analysis, targetDensity); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (currentDensity &gt; targetDensity) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u964d\u4f4e\u4fe1\u606f\u5bc6\u5ea6&#xff08;\u589e\u52a0\u89e3\u91ca&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return decreaseDensity(response, analysis, targetDensity); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return response; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private String increaseDensity(String response, DensityAnalysis analysis, double targetDensity) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u79fb\u9664\u5197\u4f59\u89e3\u91ca \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String compressed &#061; removeRedundantExplanations(response, analysis); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5408\u5e76\u76f8\u4f3c\u4fe1\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String merged &#061; mergeSimilarInformation(compressed); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u4f7f\u7528\u66f4\u7cbe\u786e\u7684\u8868\u8fbe \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String precise &#061; useMorePreciseLanguage(merged); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u6dfb\u52a0\u7ed3\u6784\u5316\u4fe1\u606f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String structured &#061; addStructure(precise); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return structured; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private double calculateInformationDensity(String text) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4fe1\u606f\u5bc6\u5ea6 &#061; \u5173\u952e\u4fe1\u606f\u5355\u5143\u6570\u91cf \/ \u603b\u5b57\u6570 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 int keyInfoUnits &#061; extractKeyInformationUnits(text).size(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 int totalWords &#061; countWords(text); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return totalWords &gt; 0 ? (double) keyInfoUnits \/ totalWords : 0; \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h5>3.3 \u7cfb\u7edf\u6027\u80fd\u95ee\u9898\u53ca\u4f18\u5316\u65b9\u6848<\/h5>\n<h6>\u95ee\u98981&#xff1a;\u68c0\u7d22\u901f\u5ea6\u6162<\/h6>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>\u5411\u91cf\u68c0\u7d22\u590d\u6742\u5ea6\u9ad8<\/li>\n<li>\u7d22\u5f15\u89c4\u6a21\u8fc7\u5927<\/li>\n<li>\u786c\u4ef6\u9650\u5236<\/li>\n<li>\u67e5\u8be2\u4f18\u5316\u4e0d\u8db3<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>\u00a0\u00a0\u7bc7\u5e45\u9650\u5236\u4e0b\u9762\u5c31\u53ea\u80fd\u7ed9\u5927\u5bb6\u5c55\u793a\u5c0f\u518c\u90e8\u5206\u5185\u5bb9\u4e86\u3002\u6574\u7406\u4e86\u4e00\u4efd\u6838\u5fc3\u9762\u8bd5\u7b14\u8bb0\u5305\u62ec\u4e86&#xff1a;Java\u9762\u8bd5\u3001Spring\u3001JVM\u3001MyBatis\u3001Redis\u3001MySQL\u3001\u5e76\u53d1\u7f16\u7a0b\u3001\u5fae\u670d\u52a1\u3001Linux\u3001Springboot\u3001SpringCloud\u3001MQ\u3001Kafc<\/p>\n<p>\u9700\u8981\u5168\u5957\u9762\u8bd5\u7b14\u8bb0\u53ca\u7b54\u6848<span class=\"link-card-box\"><span class=\"link-title\">\u3010\u70b9\u51fb\u6b64\u5904\u5373\u53ef\/\u514d\u8d39\u83b7\u53d6\u3011<\/span><span class=\"link-link\"><img decoding=\"async\" class=\"link-link-icon\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260131071652-697dac649ff65.png\" \/>https:\/\/docs.qq.com\/doc\/DQXdYWE9LZ2ZHZ1ho<\/span><\/span><\/p>\n<\/p>\n<p>public class RetrievalPerformanceOptimizer { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u5206\u5c42\u68c0\u7d22\u67b6\u6784 \u00a0 public class HierarchicalRetrieval { \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; hierarchicalRetrieve(String query, int k) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b2c\u4e00\u5c42&#xff1a;\u7c97\u7c92\u5ea6\u805a\u7c7b\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Cluster&gt; candidateClusters &#061; retrieveClusters(query, 10); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b2c\u4e8c\u5c42&#xff1a;\u7c07\u5185\u7ec6\u7c92\u5ea6\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; results &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (Cluster cluster : candidateClusters) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; clusterDocs &#061; retrieveWithinCluster(query, cluster, k\/5); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 results.addAll(clusterDocs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (results.size() &gt;&#061; k * 2) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \/\/ \u63d0\u524d\u7ec8\u6b62 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b2c\u4e09\u5c42&#xff1a;\u5168\u5c40\u7cbe\u6392 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return rerankAndSelect(query, results, k); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;Cluster&gt; retrieveClusters(String query, int maxClusters) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4f7f\u7528\u7c07\u4e2d\u5fc3\u5411\u91cf\u8fdb\u884c\u5feb\u901f\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 float[] queryVector &#061; embeddingService.embed(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ ANN\u68c0\u7d22\u7c07\u4e2d\u5fc3 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return clusterIndex.annSearch(queryVector, maxClusters); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;Document&gt; retrieveWithinCluster(String query, Cluster cluster, int k) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5728\u7c07\u5185\u8fdb\u884c\u66f4\u7cbe\u786e\u7684\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return cluster.getIndex().search(query, k); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u91cf\u5316\u4e0e\u538b\u7f29 \u00a0 public class VectorQuantization { \u00a0 \u00a0 \u00a0 public QuantizedIndex buildQuantizedIndex(List&lt;float[]&gt; vectors) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u9009\u62e9\u5408\u9002\u7684\u91cf\u5316\u65b9\u6cd5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 QuantizationMethod method &#061; selectQuantizationMethod(vectors); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8bad\u7ec3\u91cf\u5316\u5668 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Quantizer quantizer &#061; trainQuantizer(vectors, method); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u91cf\u5316\u6240\u6709\u5411\u91cf \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;QuantizedVector&gt; quantizedVectors &#061; vectors.stream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .map(quantizer::quantize) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .collect(Collectors.toList()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u6784\u5efa\u91cf\u5316\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return QuantizedIndex.builder() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .quantizer(quantizer) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .vectors(quantizedVectors) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .originalDim(vectors.get(0).length) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .compressionRatio(calculateCompressionRatio(vectors, quantizedVectors)) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .build(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private QuantizationMethod selectQuantizationMethod(List&lt;float[]&gt; vectors) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u6570\u636e\u7279\u5f81\u9009\u62e9\u91cf\u5316\u65b9\u6cd5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 DataCharacteristics chars &#061; analyzeDataCharacteristics(vectors); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (chars.getDistribution() &#061;&#061; DistributionType.NORMAL &amp;&amp; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 chars.getDimension() &gt; 128) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return QuantizationMethod.PRODUCT_QUANTIZATION; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (chars.getDimension() &lt;&#061; 128) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return QuantizationMethod.SCALAR_QUANTIZATION; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return QuantizationMethod.RESIDUAL_QUANTIZATION; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; searchWithQuantization(String query, QuantizedIndex index, int k) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u91cf\u5316\u67e5\u8be2\u5411\u91cf \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 QuantizedVector queryVector &#061; index.getQuantizer().quantize( \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 embeddingService.embed(query) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u975e\u5bf9\u79f0\u8ddd\u79bb\u8ba1\u7b97&#xff08;\u66f4\u7cbe\u786e&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return index.searchAsymmetric(queryVector, k); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u9884\u8ba1\u7b97\u4e0e\u7f13\u5b58\u4f18\u5316 \u00a0 public class PrecomputationEngine { \u00a0 \u00a0 \u00a0 public void precomputeCommonQueries() { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5206\u6790\u67e5\u8be2\u6a21\u5f0f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 QueryPatternAnalysis analysis &#061; analyzeQueryPatterns(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8bc6\u522b\u9ad8\u9891\u67e5\u8be2 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;String&gt; frequentQueries &#061; analysis.getFrequentQueries(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u9884\u8ba1\u7b97\u67e5\u8be2\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (String query : frequentQueries) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 precomputeAndCache(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u9884\u8ba1\u7b97\u67e5\u8be2\u53d8\u4f53 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (String query : frequentQueries) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;String&gt; variants &#061; generateQueryVariants(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (String variant : variants) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 precomputeAndCache(variant); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void precomputeAndCache(String query) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u6267\u884c\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; results &#061; doFullRetrieval(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u9884\u8ba1\u7b97\u76f8\u4f3c\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Map&lt;String, Float&gt; similarities &#061; precomputeSimilarities(query, results); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5b58\u50a8\u5230\u9884\u70ed\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 warmCache.put(query, new PrecomputedResult(results, similarities)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u9884\u6784\u5efa\u56de\u7b54\u6458\u8981 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 String summary &#061; precomputeSummary(query, results); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 summaryCache.put(query, summary); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public CachedResult getWithPrecomputation(String query) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u68c0\u67e5\u9884\u70ed\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 PrecomputedResult precomputed &#061; warmCache.get(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (precomputed !&#061; null) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return new CachedResult(precomputed, CacheType.WARM); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u68c0\u67e5\u67e5\u8be2\u53d8\u4f53\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CachedResult variantResult &#061; checkQueryVariants(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (variantResult !&#061; null) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return variantResult; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u68c0\u67e5\u8bed\u4e49\u76f8\u4f3c\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CachedResult semanticResult &#061; checkSemanticCache(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (semanticResult !&#061; null) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return semanticResult; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u6267\u884c\u5b9e\u65f6\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return new CachedResult(doRealTimeRetrieval(query), CacheType.NONE); \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h6>\u95ee\u98982&#xff1a;\u7cfb\u7edf\u53ef\u6269\u5c55\u6027\u95ee\u9898<\/h6>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>\u5355\u70b9\u74f6\u9888<\/li>\n<li>\u6570\u636e\u5206\u5e03\u4e0d\u5747<\/li>\n<li>\u8d44\u6e90\u7ade\u4e89<\/li>\n<li>\u67b6\u6784\u9650\u5236<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class ScalabilityOptimizer { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u5206\u5e03\u5f0f\u68c0\u7d22\u67b6\u6784 \u00a0 public class DistributedRetrieval { \u00a0 \u00a0 \u00a0 private final List&lt;RetrievalNode&gt; nodes; \u00a0 \u00a0 \u00a0 private final Router router; \u00a0 \u00a0 \u00a0 private final Merger merger; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; distributedRetrieve(String query, int k) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u67e5\u8be2\u8def\u7531 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;RetrievalTask&gt; tasks &#061; router.routeQuery(query, nodes.size()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5e76\u884c\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;CompletableFuture&lt;PartialResult&gt;&gt; futures &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (int i &#061; 0; i &lt; tasks.size(); i&#043;&#043;) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 RetrievalTask task &#061; tasks.get(i); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 RetrievalNode node &#061; nodes.get(i % nodes.size()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 futures.add(CompletableFuture.supplyAsync( \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 () -&gt; node.retrieve(task), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 retrievalExecutor \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 )); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5408\u5e76\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture&lt;List&lt;PartialResult&gt;&gt; allResults &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .thenApply(v -&gt; futures.stream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .map(CompletableFuture::join) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .collect(Collectors.toList())); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u5168\u5c40\u91cd\u6392\u5e8f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return allResults.thenApply(partialResults -&gt; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 merger.mergeAndRerank(partialResults, k) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ).join(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u667a\u80fd\u67e5\u8be2\u8def\u7531 \u00a0 \u00a0 \u00a0 public class SmartRouter { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public List&lt;RetrievalTask&gt; routeQuery(String query, int nodeCount) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5206\u6790\u67e5\u8be2\u7279\u5f81 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 QueryFeatures features &#061; extractQueryFeatures(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u57fa\u4e8e\u5185\u5bb9\u7684\u8def\u7531 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (features.isSemanticQuery()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return routeBySemanticHash(query, nodeCount); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u57fa\u4e8e\u8d1f\u8f7d\u7684\u8def\u7531 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 else if (features.isComplexQuery()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return routeByLoadBalancing(query, nodeCount); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u57fa\u4e8e\u6570\u636e\u5206\u5e03\u7684\u8def\u7531 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return routeByDataDistribution(query, nodeCount); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;RetrievalTask&gt; routeBySemanticHash(String query, int nodeCount) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u8bed\u4e49\u54c8\u5e0c\u5c06\u67e5\u8be2\u5206\u914d\u5230\u7279\u5b9a\u8282\u70b9 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 int hash &#061; semanticHash(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 int nodeIndex &#061; hash % nodeCount; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u521b\u5efa\u8def\u7531\u4efb\u52a1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 RetrievalTask task &#061; RetrievalTask.builder() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .query(query) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .targetNodes(Set.of(nodeIndex)) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .strategy(RetrievalStrategy.SEMANTIC) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .build(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return List.of(task); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u5f39\u6027\u4f38\u7f29\u673a\u5236 \u00a0 public class ElasticScaling { \u00a0 \u00a0 \u00a0 private final ScalingMonitor monitor; \u00a0 \u00a0 \u00a0 private final ScalingController controller; \u00a0 \u00a0 \u00a0 private final ResourcePool resourcePool; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void manageScaling() { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 while (true) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u76d1\u63a7\u7cfb\u7edf\u6307\u6807 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 SystemMetrics metrics &#061; monitor.collectMetrics(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5206\u6790\u8d1f\u8f7d\u6a21\u5f0f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 LoadPattern pattern &#061; analyzeLoadPattern(metrics); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u9884\u6d4b\u672a\u6765\u8d1f\u8f7d \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 LoadPrediction prediction &#061; predictFutureLoad(pattern); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u51b3\u5b9a\u4f38\u7f29\u64cd\u4f5c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ScalingDecision decision &#061; makeScalingDecision(metrics, prediction); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u6267\u884c\u4f38\u7f29\u64cd\u4f5c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 executeScaling(decision); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7b49\u5f85\u4e0b\u4e00\u4e2a\u76d1\u63a7\u5468\u671f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Thread.sleep(SCALING_INTERVAL_MS); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private ScalingDecision makeScalingDecision(SystemMetrics metrics, LoadPrediction prediction) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ScalingDecision decision &#061; new ScalingDecision(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u89c4\u5219\u7684\u51b3\u7b56 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (metrics.getCpuUsage() &gt; SCALE_OUT_CPU_THRESHOLD) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 decision.setAction(ScalingAction.SCALE_OUT); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 decision.setNodeCount(calculateScaleOutCount(metrics)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else if (metrics.getCpuUsage() &lt; SCALE_IN_CPU_THRESHOLD &amp;&amp; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 metrics.getActiveNodes() &gt; MIN_NODES) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 decision.setAction(ScalingAction.SCALE_IN); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 decision.setNodeCount(calculateScaleInCount(metrics)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u57fa\u4e8e\u9884\u6d4b\u7684\u9884\u4f38\u7f29 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (prediction.getExpectedLoad() &gt; metrics.getCurrentLoad() * 1.5) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 decision.setPreemptiveScaleOut(true); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 decision.setAdditionalNodes(prediction.getAdditionalNodesNeeded()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return decision; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void executeScaling(ScalingDecision decision) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (decision.getAction()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case SCALE_OUT: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scaleOut(decision.getNodeCount()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case SCALE_IN: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scaleIn(decision.getNodeCount()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case PREEMPTIVE_SCALE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 preemptiveScale(decision); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u91cd\u65b0\u5e73\u8861\u6570\u636e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 rebalanceData(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u8def\u7531\u8868 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateRoutingTable(); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u5f02\u6b65\u4e0e\u6d41\u5f0f\u5904\u7406 \u00a0 public class AsyncProcessingPipeline { \u00a0 \u00a0 \u00a0 private final ExecutorService retrievalExecutor; \u00a0 \u00a0 \u00a0 private final ExecutorService generationExecutor; \u00a0 \u00a0 \u00a0 private final ResultStreamer resultStreamer; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public CompletableFuture&lt;StreamingResponse&gt; processAsync(String query) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture&lt;StreamingResponse&gt; future &#061; new CompletableFuture&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u542f\u52a8\u5f02\u6b65\u68c0\u7d22 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture&lt;List&lt;Document&gt;&gt; retrievalFuture &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.supplyAsync(() -&gt; retrieveDocuments(query), retrievalExecutor); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u6d41\u5f0f\u8fd4\u56de\u90e8\u5206\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resultStreamer.startStreaming(future); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u68c0\u7d22\u5b8c\u6210\u540e\u5f02\u6b65\u751f\u6210 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 retrievalFuture.thenAcceptAsync(docs -&gt; { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6d41\u5f0f\u8fd4\u56de\u68c0\u7d22\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resultStreamer.streamRetrievalResults(docs); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5f02\u6b65\u751f\u6210\u56de\u7b54 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.supplyAsync(() -&gt; generateResponse(query, docs), generationExecutor) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .thenAccept(response -&gt; { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6d41\u5f0f\u8fd4\u56de\u751f\u6210\u7ed3\u679c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resultStreamer.streamGenerationResult(response); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resultStreamer.complete(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .exceptionally(ex -&gt; { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resultStreamer.streamError(ex); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return null; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }).exceptionally(ex -&gt; { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resultStreamer.streamError(ex); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return null; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return future; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6d41\u5f0f\u7ed3\u679c\u5904\u7406\u5668 \u00a0 \u00a0 \u00a0 public class ResultStreamer { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private final SseEmitter emitter; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private final List&lt;String&gt; bufferedChunks &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void startStreaming(CompletableFuture&lt;StreamingResponse&gt; future) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7acb\u5373\u8fd4\u56de\u521d\u59cb\u54cd\u5e94 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 StreamingResponse initial &#061; StreamingResponse.builder() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .status(StreamingStatus.STARTED) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .message(&#034;\u5f00\u59cb\u5904\u7406\u67e5\u8be2&#8230;&#034;) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .build(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 future.complete(initial); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8bbe\u7f6e\u8d85\u65f6\u548c\u9519\u8bef\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 emitter.onTimeout(() -&gt; handleTimeout()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 emitter.onError(ex -&gt; handleError(ex)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void streamRetrievalResults(List&lt;Document&gt; docs) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6d41\u5f0f\u8fd4\u56de\u68c0\u7d22\u8fdb\u5ea6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 streamChunk(&#034;\u5df2\u68c0\u7d22\u5230 &#034; &#043; docs.size() &#043; &#034; \u4e2a\u76f8\u5173\u6587\u6863&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6d41\u5f0f\u8fd4\u56de\u6587\u6863\u6458\u8981 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 docs.stream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .limit(5) \/\/ \u9650\u5236\u6570\u91cf\u907f\u514d\u8fc7\u591a\u6570\u636e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .forEach(doc -&gt; streamChunk(&#034;\u6587\u6863\u6458\u8981: &#034; &#043; doc.getSummary())); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void streamGenerationResult(String response) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6d41\u5f0f\u8fd4\u56de\u751f\u6210\u7ed3\u679c&#xff08;\u5206\u5757&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 chunkText(response, 100).forEach(this::streamChunk); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void streamChunk(String chunk) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 emitter.send(SseEmitter.event() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .name(&#034;chunk&#034;) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .data(chunk)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 bufferedChunks.add(chunk); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (IOException e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.error(&#034;Failed to stream chunk&#034;, e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h5>3.4 \u77e5\u8bc6\u5e93\u66f4\u65b0\u95ee\u9898\u53ca\u4f18\u5316\u65b9\u6848<\/h5>\n<h6>\u95ee\u98981&#xff1a;\u66f4\u65b0\u5ef6\u8fdf\u4e0e\u5b9e\u65f6\u6027\u5dee<\/h6>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>\u6279\u91cf\u66f4\u65b0\u5468\u671f\u957f<\/li>\n<li>\u7d22\u5f15\u91cd\u5efa\u8017\u65f6<\/li>\n<li>\u6570\u636e\u540c\u6b65\u5ef6\u8fdf<\/li>\n<li>\u8d44\u6e90\u7ade\u4e89<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class RealTimeUpdateOptimizer { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u589e\u91cf\u7d22\u5f15\u66f4\u65b0 \u00a0 public class IncrementalIndexUpdater { \u00a0 \u00a0 \u00a0 private final IndexWriter indexWriter; \u00a0 \u00a0 \u00a0 private final BufferManager bufferManager; \u00a0 \u00a0 \u00a0 private final MergeScheduler mergeScheduler; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void updateIncrementally(List&lt;DocumentUpdate&gt; updates) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u7f13\u51b2\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 UpdateBuffer buffer &#061; bufferManager.bufferUpdates(updates); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5e94\u7528\u66f4\u65b0\u5230\u5185\u5b58\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 MemoryIndex memoryIndex &#061; applyToMemoryIndex(buffer); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5f02\u6b65\u5199\u5165\u78c1\u76d8 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.runAsync(() -&gt; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 writeToDiskIndex(memoryIndex, buffer) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u5408\u5e76\u5c0f\u6bb5&#xff08;\u540e\u53f0&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (shouldMergeSegments()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 mergeScheduler.scheduleMerge(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private MemoryIndex applyToMemoryIndex(UpdateBuffer buffer) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 MemoryIndex index &#061; new MemoryIndex(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (DocumentUpdate update : buffer.getUpdates()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (update.getType()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case INSERT: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 index.addDocument(update.getDocument()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case UPDATE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 index.updateDocument(update.getDocumentId(), update.getDocument()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DELETE: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 index.deleteDocument(update.getDocumentId()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u5185\u5b58\u4e2d\u7684\u5411\u91cf\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateVectorIndexInMemory(index); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return index; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5b9e\u65f6\u67e5\u8be2&#xff1a;\u7ed3\u5408\u5185\u5b58\u548c\u78c1\u76d8\u7d22\u5f15 \u00a0 \u00a0 \u00a0 public List&lt;Document&gt; realTimeRetrieve(String query) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u67e5\u8be2\u5185\u5b58\u7d22\u5f15&#xff08;\u6700\u65b0\u6570\u636e&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; memoryResults &#061; memoryIndex.search(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u67e5\u8be2\u78c1\u76d8\u7d22\u5f15&#xff08;\u5386\u53f2\u6570\u636e&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Document&gt; diskResults &#061; diskIndex.search(query); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5408\u5e76\u7ed3\u679c&#xff08;\u5185\u5b58\u7ed3\u679c\u4f18\u5148\u7ea7\u66f4\u9ad8&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return mergeResults(memoryResults, diskResults); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u57fa\u4e8eCDC\u7684\u5b9e\u65f6\u540c\u6b65 \u00a0 public class CDCBasedSync { \u00a0 \u00a0 \u00a0 private final ChangeCapture changeCapture; \u00a0 \u00a0 \u00a0 private final ChangeProcessor changeProcessor; \u00a0 \u00a0 \u00a0 private final ReplicationManager replicationManager; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void startRealTimeSync() { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u6355\u83b7\u6570\u636e\u6e90\u53d8\u5316 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 changeCapture.startCapturing(changeEvent -&gt; { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5b9e\u65f6\u5904\u7406\u53d8\u5316 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.runAsync(() -&gt; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 processChangeEvent(changeEvent) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u542f\u52a8\u590d\u5236\u76d1\u542c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 replicationManager.startReplication(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void processChangeEvent(ChangeEvent event) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u8f6c\u6362\u53d8\u5316\u4e3a\u77e5\u8bc6\u5e93\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeUpdate update &#061; convertChangeEvent(event); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u9a8c\u8bc1\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!validateUpdate(update)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.warn(&#034;Invalid update from change event: {}&#034;, event); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u5e94\u7528\u66f4\u65b0&#xff08;\u539f\u5b50\u64cd\u4f5c&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 applyUpdateAtomically(update); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u89e6\u53d1\u4e0b\u6e38\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 triggerDownstreamUpdates(update); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u8bb0\u5f55\u66f4\u65b0\u65e5\u5fd7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 logUpdate(update); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.error(&#034;Failed to process change event&#034;, e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 handleProcessingError(event, e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void applyUpdateAtomically(KnowledgeUpdate update) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u4f7f\u7528\u4e8b\u52a1\u4fdd\u8bc1\u539f\u5b50\u6027 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Transaction tx &#061; knowledgeBase.beginTransaction(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5e94\u7528\u6587\u6863\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 applyDocumentUpdate(update, tx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u7d22\u5f15 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateIndexes(update, tx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u5411\u91cf\u5b58\u50a8 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateVectors(update, tx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u63d0\u4ea4\u4e8b\u52a1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 tx.commit(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u66f4\u65b0\u7f13\u5b58 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 updateCaches(update); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 tx.rollback(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 throw e; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u6d41\u5f0f\u5904\u7406\u7ba1\u9053 \u00a0 public class StreamingUpdatePipeline { \u00a0 \u00a0 \u00a0 private final KafkaStreams streams; \u00a0 \u00a0 \u00a0 private final UpdateProcessor processor; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void buildStreamingPipeline() { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6784\u5efaKafka Streams\u5904\u7406\u62d3\u6251 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 StreamsBuilder builder &#061; new StreamsBuilder(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u6e90\u6d41&#xff1a;\u539f\u59cb\u66f4\u65b0\u4e8b\u4ef6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KStream&lt;String, UpdateEvent&gt; sourceStream &#061; builder.stream(&#034;update-events&#034;); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8f6c\u6362\u6d41&#xff1a;\u8f6c\u6362\u4e3a\u6807\u51c6\u683c\u5f0f \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KStream&lt;String, StandardizedUpdate&gt; transformedStream &#061; sourceStream \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .mapValues(this::standardizeUpdate); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u8fc7\u6ee4\u6d41&#xff1a;\u8fc7\u6ee4\u65e0\u6548\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KStream&lt;String, StandardizedUpdate&gt; filteredStream &#061; transformedStream \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .filter((key, value) -&gt; isValidUpdate(value)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u5904\u7406\u6d41&#xff1a;\u5e94\u7528\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 filteredStream.foreach((key, update) -&gt; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 processor.processUpdate(update) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u5206\u652f\u6d41&#xff1a;\u6839\u636e\u7c7b\u578b\u5206\u522b\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Map&lt;String, KStream&lt;String, StandardizedUpdate&gt;&gt; branchedStreams &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 filteredStream.split(Named.as(&#034;branch-&#034;)) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .branch((key, update) -&gt; update.getType() &#061;&#061; UpdateType.INSERT, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Branched.as(&#034;inserts&#034;)) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .branch((key, update) -&gt; update.getType() &#061;&#061; UpdateType.UPDATE, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Branched.as(&#034;updates&#034;)) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .branch((key, update) -&gt; update.getType() &#061;&#061; UpdateType.DELETE, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Branched.as(&#034;deletes&#034;)) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .noDefaultBranch(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5206\u522b\u5904\u7406\u4e0d\u540c\u7c7b\u578b \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 processInserts(branchedStreams.get(&#034;branch-inserts&#034;)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 processUpdates(branchedStreams.get(&#034;branch-updates&#034;)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 processDeletes(branchedStreams.get(&#034;branch-deletes&#034;)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u542f\u52a8\u6d41\u5904\u7406 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 streams &#061; new KafkaStreams(builder.build(), getStreamsConfig()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 streams.start(); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private void processInserts(KStream&lt;String, StandardizedUpdate&gt; insertStream) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 insertStream \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5206\u6279\u5904\u7406&#xff08;\u7a97\u53e3\u5316&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .groupByKey() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .windowedBy(TimeWindows.of(Duration.ofSeconds(5))) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .aggregate( \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 () -&gt; new BatchAccumulator(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 (key, update, accumulator) -&gt; accumulator.add(update), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Materialized.with(Serdes.String(), new JsonSerde&lt;&gt;()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .toStream() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6279\u91cf\u5e94\u7528\u63d2\u5165 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 .foreach((windowedKey, batch) -&gt; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 processor.batchInsert(batch.getUpdates()) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h6>\u95ee\u98982&#xff1a;\u66f4\u65b0\u4e00\u81f4\u6027\u4fdd\u8bc1<\/h6>\n<p>\u00a0\u00a0\u7bc7\u5e45\u9650\u5236\u4e0b\u9762\u5c31\u53ea\u80fd\u7ed9\u5927\u5bb6\u5c55\u793a\u5c0f\u518c\u90e8\u5206\u5185\u5bb9\u4e86\u3002\u6574\u7406\u4e86\u4e00\u4efd\u6838\u5fc3\u9762\u8bd5\u7b14\u8bb0\u5305\u62ec\u4e86&#xff1a;Java\u9762\u8bd5\u3001Spring\u3001JVM\u3001MyBatis\u3001Redis\u3001MySQL\u3001\u5e76\u53d1\u7f16\u7a0b\u3001\u5fae\u670d\u52a1\u3001Linux\u3001Springboot\u3001SpringCloud\u3001MQ\u3001Kafc<\/p>\n<p>\u9700\u8981\u5168\u5957\u9762\u8bd5\u7b14\u8bb0\u53ca\u7b54\u6848<span class=\"link-card-box\"><span class=\"link-title\">\u3010\u70b9\u51fb\u6b64\u5904\u5373\u53ef\/\u514d\u8d39\u83b7\u53d6\u3011<\/span><span class=\"link-link\"><img decoding=\"async\" class=\"link-link-icon\" src=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260131071652-697dac649ff65.png\" \/>https:\/\/docs.qq.com\/doc\/DQXdYWE9LZ2ZHZ1ho<\/span><\/span><\/p>\n<\/p>\n<p>\u6839\u672c\u539f\u56e0&#xff1a;<\/p>\n<ul>\n<li>\u5e76\u53d1\u66f4\u65b0\u51b2\u7a81<\/li>\n<li>\u5206\u5e03\u5f0f\u7cfb\u7edf\u4e00\u81f4\u6027\u96be\u9898<\/li>\n<li>\u7f51\u7edc\u5206\u533a<\/li>\n<li>\u6545\u969c\u6062\u590d<\/li>\n<\/ul>\n<p>\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<p>java<\/p>\n<p>public class ConsistencyManager { \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68481&#xff1a;\u57fa\u4e8e\u7248\u672c\u7684\u4e00\u81f4\u6027\u63a7\u5236 \u00a0 public class VersionBasedConsistency { \u00a0 \u00a0 \u00a0 private final VersionStore versionStore; \u00a0 \u00a0 \u00a0 private final ConflictResolver conflictResolver; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public UpdateResult applyUpdateWithVersion(KnowledgeUpdate update, long expectedVersion) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u83b7\u53d6\u5f53\u524d\u7248\u672c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 long currentVersion &#061; knowledgeBase.getCurrentVersion(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u68c0\u67e5\u7248\u672c\u4e00\u81f4\u6027 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (expectedVersion !&#061; currentVersion) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7248\u672c\u51b2\u7a81&#xff0c;\u9700\u8981\u89e3\u51b3 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ConflictResolution resolution &#061; resolveConflict(update, expectedVersion, currentVersion); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return applyResolvedUpdate(resolution); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u7248\u672c\u4e00\u81f4&#xff0c;\u5e94\u7528\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return applyUpdate(update, currentVersion &#043; 1); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private ConflictResolution resolveConflict(KnowledgeUpdate update, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 long expectedVersion, \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 long currentVersion) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u83b7\u53d6\u51b2\u7a81\u7248\u672c\u4e4b\u95f4\u7684\u53d8\u66f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;KnowledgeUpdate&gt; conflictingUpdates &#061; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 versionStore.getUpdatesBetween(expectedVersion, currentVersion); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5206\u6790\u51b2\u7a81\u7c7b\u578b \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ConflictAnalysis analysis &#061; analyzeConflicts(update, conflictingUpdates); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u81ea\u52a8\u6216\u624b\u52a8\u89e3\u51b3\u51b2\u7a81 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (analysis.isAutoResolvable()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return conflictResolver.autoResolve(update, conflictingUpdates, analysis); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } else { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return conflictResolver.manualResolve(update, conflictingUpdates, analysis); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private UpdateResult applyResolvedUpdate(ConflictResolution resolution) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u521b\u5efa\u5408\u5e76\u540e\u7684\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 KnowledgeUpdate mergedUpdate &#061; mergeUpdates( \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resolution.getOriginalUpdate(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resolution.getConflictingUpdates(), \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 resolution.getResolutionStrategy() \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5e94\u7528\u5408\u5e76\u540e\u7684\u66f4\u65b0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return applyUpdate(mergedUpdate, resolution.getNewVersion()); \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68482&#xff1a;\u57fa\u4e8e\u4e8b\u52a1\u7684\u4e00\u81f4\u6027\u4fdd\u8bc1 \u00a0 public class TransactionalUpdate { \u00a0 \u00a0 \u00a0 private final TransactionManager txManager; \u00a0 \u00a0 \u00a0 private final LockManager lockManager; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public UpdateResult updateWithTransaction(KnowledgeUpdate update) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5f00\u59cb\u4e8b\u52a1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Transaction tx &#061; txManager.beginTransaction(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u83b7\u53d6\u5fc5\u8981\u7684\u9501 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Lock&gt; locks &#061; acquireLocks(update, tx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u9a8c\u8bc1\u524d\u7f6e\u6761\u4ef6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 validatePreconditions(update, tx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u6267\u884c\u66f4\u65b0\u64cd\u4f5c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 executeUpdateOperations(update, tx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u540e\u7f6e\u6761\u4ef6\u68c0\u67e5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 validatePostconditions(tx); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u63d0\u4ea4\u4e8b\u52a1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 tx.commit(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 6. \u91ca\u653e\u9501 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 releaseLocks(locks); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return UpdateResult.success(update.getId()); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u56de\u6eda\u4e8b\u52a1 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 tx.rollback(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u91ca\u653e\u9501 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 releaseAllLocks(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return UpdateResult.failed(update.getId(), e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 private List&lt;Lock&gt; acquireLocks(KnowledgeUpdate update, Transaction tx) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Lock&gt; locks &#061; new ArrayList&lt;&gt;(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6839\u636e\u66f4\u65b0\u7c7b\u578b\u83b7\u53d6\u4e0d\u540c\u7684\u9501 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 switch (update.getScope()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case DOCUMENT_LEVEL: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u6587\u6863\u7ea7\u9501 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 locks.add(lockManager.acquireDocumentLock(update.getDocumentId(), tx)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case COLLECTION_LEVEL: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u96c6\u5408\u7ea7\u9501 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 locks.add(lockManager.acquireCollectionLock(update.getCollection(), tx)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 case GLOBAL: \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5168\u5c40\u9501&#xff08;\u8c28\u614e\u4f7f\u7528&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 locks.add(lockManager.acquireGlobalLock(tx)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 break; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u83b7\u53d6\u7d22\u5f15\u9501 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (update.affectsIndex()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 locks.addAll(lockManager.acquireIndexLocks(update.getAffectedIndexes(), tx)); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return locks; \u00a0 \u00a0 \u00a0 } \u00a0 } \u00a0 \u00a0 \u00a0 \/\/ \u89e3\u51b3\u65b9\u68483&#xff1a;\u6700\u7ec8\u4e00\u81f4\u6027\u4fdd\u8bc1 \u00a0 public class EventualConsistency { \u00a0 \u00a0 \u00a0 private final ReplicationLog replicationLog; \u00a0 \u00a0 \u00a0 private final ConsistencyChecker consistencyChecker; \u00a0 \u00a0 \u00a0 private final RepairManager repairManager; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 public void ensureEventualConsistency() { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5b9a\u671f\u68c0\u67e5\u4e00\u81f4\u6027 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ScheduledExecutorService scheduler &#061; Executors.newScheduledThreadPool(1); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scheduler.scheduleAtFixedRate(() -&gt; { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u68c0\u67e5\u526f\u672c\u4e00\u81f4\u6027 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ConsistencyReport report &#061; consistencyChecker.checkConsistency(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u8bc6\u522b\u4e0d\u4e00\u81f4 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 List&lt;Inconsistency&gt; inconsistencies &#061; report.getInconsistencies(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!inconsistencies.isEmpty()) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u542f\u52a8\u4fee\u590d\u6d41\u7a0b \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 repairManager.repairInconsistencies(inconsistencies); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u8bb0\u5f55\u4fee\u590d\u65e5\u5fd7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 logRepairActions(inconsistencies); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.error(&#034;Consistency check failed&#034;, e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }, 0, CONSISTENCY_CHECK_INTERVAL, TimeUnit.MINUTES); \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8bfb\u4fee\u590d\u673a\u5236 \u00a0 \u00a0 \u00a0 public Document readWithRepair(String documentId) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u4ece\u4e3b\u526f\u672c\u8bfb\u53d6 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Document primaryDoc &#061; readFromPrimary(documentId); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u4ece\u4ece\u526f\u672c\u8bfb\u53d6&#xff08;\u5feb\u901f\u8fd4\u56de&#xff09; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture&lt;Document&gt; replicaFuture &#061; CompletableFuture.supplyAsync( \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 () -&gt; readFromReplica(documentId) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u6bd4\u8f83\u4e00\u81f4\u6027 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 Document replicaDoc &#061; replicaFuture.join(); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 if (!documentsEqual(primaryDoc, replicaDoc)) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 4. \u68c0\u6d4b\u5230\u4e0d\u4e00\u81f4&#xff0c;\u542f\u52a8\u5f02\u6b65\u4fee\u590d \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.runAsync(() -&gt; \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 repairInconsistency(documentId, primaryDoc, replicaDoc) \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 ); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 5. \u8fd4\u56de\u4e3b\u526f\u672c\u6570\u636e \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 return primaryDoc; \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u5199\u4f20\u64ad\u673a\u5236 \u00a0 \u00a0 \u00a0 public void propagateUpdate(KnowledgeUpdate update) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 1. \u5199\u5165\u4e3b\u526f\u672c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 applyToPrimary(update); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 2. \u5f02\u6b65\u4f20\u64ad\u5230\u4ece\u526f\u672c \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 CompletableFuture.runAsync(() -&gt; { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 for (ReplicaNode replica : replicaNodes) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 try { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 replica.applyUpdate(update); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } catch (Exception e) { \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 log.error(&#034;Failed to propagate update to replica&#034;, e); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ \u8bb0\u5f55\u5931\u8d25&#xff0c;\u7a0d\u540e\u91cd\u8bd5 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 scheduleRetry(update, replica); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 } \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 }); \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \/\/ 3. \u66f4\u65b0\u590d\u5236\u65e5\u5fd7 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 replicationLog.append(update); \u00a0 \u00a0 \u00a0 } \u00a0 } } <\/p>\n<h4>\u56db\u3001\u603b\u7ed3\u4e0e\u6700\u4f73\u5b9e\u8df5<\/h4>\n<p>\u901a\u8fc7\u4ee5\u4e0a\u8be6\u7ec6\u5206\u6790&#xff0c;\u6211\u4eec\u53ef\u4ee5\u603b\u7ed3\u51faRAG\u7cfb\u7edf\u7684\u5173\u952e\u95ee\u9898\u548c\u89e3\u51b3\u65b9\u6848&#xff1a;<\/p>\n<h5>4.1 \u5904\u7406\u77e5\u8bc6\u5e93\u672a\u8986\u76d6\u95ee\u9898\u7684\u6700\u4f73\u5b9e\u8df5<\/h5>\n<li>\u5206\u5c42\u8bc6\u522b\u7b56\u7565&#xff1a;\u4ece\u8bed\u4e49\u76f8\u4f3c\u5ea6\u3001\u5173\u952e\u8bcd\u8986\u76d6\u3001\u4e3b\u9898\u5206\u5e03\u7b49\u591a\u7ef4\u5ea6\u5224\u65ad\u67e5\u8be2\u662f\u5426\u5728\u77e5\u8bc6\u5e93\u8303\u56f4\u5185<\/li>\n<li>\u6e10\u8fdb\u5f0f\u54cd\u5e94\u7b56\u7565&#xff1a;\u6839\u636e\u8d85\u51fa\u7a0b\u5ea6\u91c7\u7528\u4e0d\u540c\u7684\u54cd\u5e94\u65b9\u5f0f&#xff0c;\u4ece\u77e5\u8bc6\u6269\u5c55\u5230\u8bda\u5b9e\u62d2\u7edd<\/li>\n<li>\u4e3b\u52a8\u5b66\u4e60\u673a\u5236&#xff1a;\u8bb0\u5f55\u672a\u8986\u76d6\u67e5\u8be2&#xff0c;\u5b9a\u671f\u5206\u6790\u77e5\u8bc6\u7f3a\u53e3&#xff0c;\u6307\u5bfc\u77e5\u8bc6\u5e93\u6269\u5c55<\/li>\n<li>\u7f6e\u4fe1\u5ea6\u900f\u660e\u5316&#xff1a;\u660e\u786e\u544a\u77e5\u7528\u6237\u56de\u7b54\u7684\u7f6e\u4fe1\u5ea6\u6c34\u5e73\u548c\u4f9d\u636e\u6765\u6e90<\/li>\n<h5>4.2 \u77e5\u8bc6\u5e93\u66f4\u65b0\u7684\u6700\u4f73\u5b9e\u8df5<\/h5>\n<li>\u6df7\u5408\u66f4\u65b0\u7b56\u7565&#xff1a;\u7ed3\u5408\u5b9e\u65f6\u589e\u91cf\u66f4\u65b0\u548c\u5b9a\u671f\u5168\u91cf\u66f4\u65b0&#xff0c;\u5e73\u8861\u5b9e\u65f6\u6027\u548c\u6548\u7387<\/li>\n<li>\u7248\u672c\u63a7\u5236\u673a\u5236&#xff1a;\u5b9e\u73b0\u5b8c\u5584\u7684\u7248\u672c\u7ba1\u7406&#xff0c;\u652f\u6301\u56de\u6eda\u548c\u7248\u672c\u5bf9\u6bd4<\/li>\n<li>\u4e00\u81f4\u6027\u4fdd\u8bc1&#xff1a;\u91c7\u7528\u9002\u5f53\u7684\u4e00\u81f4\u6027\u7ea7\u522b&#xff08;\u5f3a\u4e00\u81f4\u6027\u3001\u6700\u7ec8\u4e00\u81f4\u6027&#xff09;\u786e\u4fdd\u6570\u636e\u6b63\u786e\u6027<\/li>\n<li>\u6027\u80fd\u4f18\u5316&#xff1a;\u901a\u8fc7\u7d22\u5f15\u4f18\u5316\u3001\u7f13\u5b58\u7b56\u7565\u3001\u5206\u5e03\u5f0f\u67b6\u6784\u63d0\u9ad8\u66f4\u65b0\u6548\u7387<\/li>\n<h5>4.3 \u7cfb\u7edf\u8bbe\u8ba1\u539f\u5219<\/h5>\n<li>\u6a21\u5757\u5316\u8bbe\u8ba1&#xff1a;\u5c06\u68c0\u7d22\u3001\u751f\u6210\u3001\u66f4\u65b0\u7b49\u6a21\u5757\u89e3\u8026&#xff0c;\u4fbf\u4e8e\u72ec\u7acb\u4f18\u5316\u548c\u6269\u5c55<\/li>\n<li>\u53ef\u89c2\u6d4b\u6027&#xff1a;\u5efa\u7acb\u5b8c\u5584\u7684\u76d1\u63a7\u3001\u65e5\u5fd7\u548c\u8ffd\u8e2a\u4f53\u7cfb&#xff0c;\u5feb\u901f\u5b9a\u4f4d\u95ee\u9898<\/li>\n<li>\u5f39\u6027\u8bbe\u8ba1&#xff1a;\u5b9e\u73b0\u81ea\u52a8\u4f38\u7f29\u3001\u6545\u969c\u8f6c\u79fb\u548c\u964d\u7ea7\u673a\u5236&#xff0c;\u4fdd\u8bc1\u7cfb\u7edf\u53ef\u7528\u6027<\/li>\n<li>\u5b89\u5168\u6027\u8003\u8651&#xff1a;\u5b9e\u65bd\u8bbf\u95ee\u63a7\u5236\u3001\u6570\u636e\u8131\u654f\u3001\u8f93\u51fa\u8fc7\u6ee4\u7b49\u5b89\u5168\u63aa\u65bd<\/li>\n<h5>4.4 \u672a\u6765\u53d1\u5c55\u8d8b\u52bf<\/h5>\n<li>\u591a\u6a21\u6001RAG&#xff1a;\u652f\u6301\u56fe\u50cf\u3001\u89c6\u9891\u3001\u97f3\u9891\u7b49\u591a\u6a21\u6001\u4fe1\u606f\u7684\u68c0\u7d22\u548c\u751f\u6210<\/li>\n<li>\u4e2a\u6027\u5316RAG&#xff1a;\u57fa\u4e8e\u7528\u6237\u753b\u50cf\u548c\u5386\u53f2\u4ea4\u4e92\u7684\u4e2a\u6027\u5316\u68c0\u7d22\u548c\u751f\u6210<\/li>\n<li>\u8054\u90a6RAG&#xff1a;\u8de8\u7ec4\u7ec7\u3001\u8de8\u9886\u57df\u7684\u5b89\u5168\u77e5\u8bc6\u5171\u4eab\u548c\u534f\u540c<\/li>\n<li>\u81ea\u8fdb\u5316RAG&#xff1a;\u81ea\u52a8\u8bc6\u522b\u77e5\u8bc6\u7f3a\u53e3\u3001\u6536\u96c6\u65b0\u77e5\u8bc6\u3001\u4f18\u5316\u68c0\u7d22\u548c\u751f\u6210\u7b56\u7565<\/li>\n<p>RAG\u7cfb\u7edf\u4f5c\u4e3a\u8fde\u63a5\u5927\u8bed\u8a00\u6a21\u578b\u548c\u4e13\u4e1a\u77e5\u8bc6\u5e93\u7684\u5173\u952e\u6865\u6881&#xff0c;\u5176\u4f18\u5316\u662f\u4e00\u4e2a\u6301\u7eed\u7684\u8fc7\u7a0b\u3002\u968f\u7740\u6280\u672f\u7684\u4e0d\u65ad\u53d1\u5c55&#xff0c;\u6211\u4eec\u671f\u5f85\u770b\u5230\u66f4\u52a0\u667a\u80fd\u3001\u9ad8\u6548\u3001\u53ef\u9760\u7684RAG\u7cfb\u7edf\u5728\u66f4\u591a\u9886\u57df\u5f97\u5230\u5e94\u7528\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>RAG\u7cfb\u7edf\u6982\u8ff0<br \/>\nRAG&#xff08;Retrieval-Augmented Generation&#xff09;\u7cfb\u7edf\u7ed3\u5408\u4e86\u68c0\u7d22\u548c\u751f\u6210\u4e24\u4e2a\u6b65\u9aa4&#xff0c;\u65e8\u5728\u5229\u7528\u5916\u90e8\u77e5\u8bc6\u5e93\u6765\u589e\u5f3a\u751f\u6210\u6a21\u578b\u7684\u80fd\u529b\u3002\u5176\u57fa\u672c\u6d41\u7a0b\u5305\u62ec&#xff1a;<br \/>\n\u68c0\u7d22&#xff1a;\u6839\u636e\u7528\u6237\u67e5\u8be2\u4ece\u77e5\u8bc6\u5e93\u4e2d\u68c0\u7d22\u76f8\u5173\u6587\u6863\u6216\u7247\u6bb5\u3002\u751f\u6210&#xff1a;\u5c06\u68c0\u7d22\u5230\u7684\u5185\u5bb9\u4e0e\u7528\u6237\u67e5\u8be2\u4e00\u8d77\u8f93\u5165\u751f\u6210\u6a21\u578b&#xff0c;\u751f\u6210\u6700\u7ec8\u56de\u7b54\u3002<br \/>\nRAG\u7684\u4f18\u52bf\u5728\u4e8e\u80fd\u591f\u5229\u7528\u6700\u65b0\u7684\u3001\u975e\u53c2\u6570\u5316\u7684\u77e5\u8bc6&#xff08;\u77e5\u8bc6\u5e93&#xff09;\u6765\u8865\u5145<\/p>\n","protected":false},"author":2,"featured_media":69367,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[99,190,925,176],"topic":[],"class_list":["post-69368","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-server","tag-java","tag-190","tag-925","tag-176"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v20.3 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.wsisp.com\/helps\/69368.html\" \/>\n<meta property=\"og:locale\" content=\"zh_CN\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"og:description\" content=\"RAG\u7cfb\u7edf\u6982\u8ff0 RAG&#xff08;Retrieval-Augmented Generation&#xff09;\u7cfb\u7edf\u7ed3\u5408\u4e86\u68c0\u7d22\u548c\u751f\u6210\u4e24\u4e2a\u6b65\u9aa4&#xff0c;\u65e8\u5728\u5229\u7528\u5916\u90e8\u77e5\u8bc6\u5e93\u6765\u589e\u5f3a\u751f\u6210\u6a21\u578b\u7684\u80fd\u529b\u3002\u5176\u57fa\u672c\u6d41\u7a0b\u5305\u62ec&#xff1a; \u68c0\u7d22&#xff1a;\u6839\u636e\u7528\u6237\u67e5\u8be2\u4ece\u77e5\u8bc6\u5e93\u4e2d\u68c0\u7d22\u76f8\u5173\u6587\u6863\u6216\u7247\u6bb5\u3002\u751f\u6210&#xff1a;\u5c06\u68c0\u7d22\u5230\u7684\u5185\u5bb9\u4e0e\u7528\u6237\u67e5\u8be2\u4e00\u8d77\u8f93\u5165\u751f\u6210\u6a21\u578b&#xff0c;\u751f\u6210\u6700\u7ec8\u56de\u7b54\u3002 RAG\u7684\u4f18\u52bf\u5728\u4e8e\u80fd\u591f\u5229\u7528\u6700\u65b0\u7684\u3001\u975e\u53c2\u6570\u5316\u7684\u77e5\u8bc6&#xff08;\u77e5\u8bc6\u5e93&#xff09;\u6765\u8865\u5145\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.wsisp.com\/helps\/69368.html\" \/>\n<meta property=\"og:site_name\" content=\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\" \/>\n<meta property=\"article:published_time\" content=\"2026-01-31T07:16:53+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260131071652-697dac649ff65.png\" \/>\n<meta name=\"author\" content=\"admin\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"\u4f5c\u8005\" \/>\n\t<meta name=\"twitter:data1\" content=\"admin\" \/>\n\t<meta name=\"twitter:label2\" content=\"\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4\" \/>\n\t<meta name=\"twitter:data2\" content=\"29 \u5206\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/69368.html\",\"url\":\"https:\/\/www.wsisp.com\/helps\/69368.html\",\"name\":\"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"isPartOf\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\"},\"datePublished\":\"2026-01-31T07:16:53+00:00\",\"dateModified\":\"2026-01-31T07:16:53+00:00\",\"author\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\"},\"breadcrumb\":{\"@id\":\"https:\/\/www.wsisp.com\/helps\/69368.html#breadcrumb\"},\"inLanguage\":\"zh-Hans\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.wsisp.com\/helps\/69368.html\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/69368.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"\u9996\u9875\",\"item\":\"https:\/\/www.wsisp.com\/helps\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#website\",\"url\":\"https:\/\/www.wsisp.com\/helps\/\",\"name\":\"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3\",\"description\":\"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"zh-Hans\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41\",\"name\":\"admin\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"zh-Hans\",\"@id\":\"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"contentUrl\":\"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery\",\"caption\":\"admin\"},\"sameAs\":[\"http:\/\/wp.wsisp.com\"],\"url\":\"https:\/\/www.wsisp.com\/helps\/author\/admin\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.wsisp.com\/helps\/69368.html","og_locale":"zh_CN","og_type":"article","og_title":"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","og_description":"RAG\u7cfb\u7edf\u6982\u8ff0 RAG&#xff08;Retrieval-Augmented Generation&#xff09;\u7cfb\u7edf\u7ed3\u5408\u4e86\u68c0\u7d22\u548c\u751f\u6210\u4e24\u4e2a\u6b65\u9aa4&#xff0c;\u65e8\u5728\u5229\u7528\u5916\u90e8\u77e5\u8bc6\u5e93\u6765\u589e\u5f3a\u751f\u6210\u6a21\u578b\u7684\u80fd\u529b\u3002\u5176\u57fa\u672c\u6d41\u7a0b\u5305\u62ec&#xff1a; \u68c0\u7d22&#xff1a;\u6839\u636e\u7528\u6237\u67e5\u8be2\u4ece\u77e5\u8bc6\u5e93\u4e2d\u68c0\u7d22\u76f8\u5173\u6587\u6863\u6216\u7247\u6bb5\u3002\u751f\u6210&#xff1a;\u5c06\u68c0\u7d22\u5230\u7684\u5185\u5bb9\u4e0e\u7528\u6237\u67e5\u8be2\u4e00\u8d77\u8f93\u5165\u751f\u6210\u6a21\u578b&#xff0c;\u751f\u6210\u6700\u7ec8\u56de\u7b54\u3002 RAG\u7684\u4f18\u52bf\u5728\u4e8e\u80fd\u591f\u5229\u7528\u6700\u65b0\u7684\u3001\u975e\u53c2\u6570\u5316\u7684\u77e5\u8bc6&#xff08;\u77e5\u8bc6\u5e93&#xff09;\u6765\u8865\u5145","og_url":"https:\/\/www.wsisp.com\/helps\/69368.html","og_site_name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","article_published_time":"2026-01-31T07:16:53+00:00","og_image":[{"url":"https:\/\/www.wsisp.com\/helps\/wp-content\/uploads\/2026\/01\/20260131071652-697dac649ff65.png"}],"author":"admin","twitter_card":"summary_large_image","twitter_misc":{"\u4f5c\u8005":"admin","\u9884\u8ba1\u9605\u8bfb\u65f6\u95f4":"29 \u5206"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.wsisp.com\/helps\/69368.html","url":"https:\/\/www.wsisp.com\/helps\/69368.html","name":"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09 - \u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","isPartOf":{"@id":"https:\/\/www.wsisp.com\/helps\/#website"},"datePublished":"2026-01-31T07:16:53+00:00","dateModified":"2026-01-31T07:16:53+00:00","author":{"@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41"},"breadcrumb":{"@id":"https:\/\/www.wsisp.com\/helps\/69368.html#breadcrumb"},"inLanguage":"zh-Hans","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.wsisp.com\/helps\/69368.html"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.wsisp.com\/helps\/69368.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"\u9996\u9875","item":"https:\/\/www.wsisp.com\/helps"},{"@type":"ListItem","position":2,"name":"\u3010\u516b\u80a1\u6587\u3011Java\u9762\u8bd5\u7a81\u51fb\u6df1\u5ea6\u89e3\u6790\uff08RAG\u7bc7\uff09"}]},{"@type":"WebSite","@id":"https:\/\/www.wsisp.com\/helps\/#website","url":"https:\/\/www.wsisp.com\/helps\/","name":"\u7f51\u7855\u4e92\u8054\u5e2e\u52a9\u4e2d\u5fc3","description":"\u9999\u6e2f\u670d\u52a1\u5668_\u9999\u6e2f\u4e91\u670d\u52a1\u5668\u8d44\u8baf_\u670d\u52a1\u5668\u5e2e\u52a9\u6587\u6863_\u670d\u52a1\u5668\u6559\u7a0b","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.wsisp.com\/helps\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"zh-Hans"},{"@type":"Person","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/358e386c577a3ab51c4493330a20ad41","name":"admin","image":{"@type":"ImageObject","inLanguage":"zh-Hans","@id":"https:\/\/www.wsisp.com\/helps\/#\/schema\/person\/image\/","url":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","contentUrl":"https:\/\/gravatar.wp-china-yes.net\/avatar\/?s=96&d=mystery","caption":"admin"},"sameAs":["http:\/\/wp.wsisp.com"],"url":"https:\/\/www.wsisp.com\/helps\/author\/admin"}]}},"_links":{"self":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/69368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/comments?post=69368"}],"version-history":[{"count":0,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/posts\/69368\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media\/69367"}],"wp:attachment":[{"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/media?parent=69368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/categories?post=69368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/tags?post=69368"},{"taxonomy":"topic","embeddable":true,"href":"https:\/\/www.wsisp.com\/helps\/wp-json\/wp\/v2\/topic?post=69368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}