From feee56dc569ef61e6edb19649420cde7aa542b37 Mon Sep 17 00:00:00 2001 From: letai2001 Date: Wed, 8 Oct 2025 23:33:13 +0700 Subject: [PATCH] strakid --- .vscode/launch.json | 34 +-- README.md | 21 ++ __pycache__/main.cpython-313.pyc | Bin 0 -> 187 bytes image.png | Bin 0 -> 116810 bytes logs/api_2025-10-08.log | 248 ++++++++++++++++++ src/api/__pycache__/chat_api.cpython-313.pyc | Bin 0 -> 4742 bytes src/api/chat_api.py | 89 ++++++- .../__pycache__/llm_client.cpython-313.pyc | Bin 1709 -> 1709 bytes .../prompt_builder.cpython-313.pyc | Bin 3278 -> 5212 bytes .../__pycache__/rag_pipeline.cpython-313.pyc | Bin 1898 -> 2077 bytes .../__pycache__/retriever.cpython-313.pyc | Bin 3460 -> 3653 bytes src/chatbot/prompt_builder.py | 97 +++++-- src/chatbot/rag_pipeline.py | 11 +- src/chatbot/retriever.py | 16 +- .../ingest_semantic.cpython-313.pyc | Bin 3716 -> 3716 bytes 15 files changed, 455 insertions(+), 61 deletions(-) create mode 100644 __pycache__/main.cpython-313.pyc create mode 100644 image.png create mode 100644 logs/api_2025-10-08.log create mode 100644 src/api/__pycache__/chat_api.cpython-313.pyc diff --git a/.vscode/launch.json b/.vscode/launch.json index 7bf1ba8..4eb3cb3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,16 +1,20 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Debug rag_pipeline (as module)", - "type": "python", - "request": "launch", - "module": "src.chatbot.rag_pipeline", // chạy theo module - "cwd": "${workspaceFolder}", // thư mục gốc project - "envFile": "${workspaceFolder}/.env", // load biến môi trường - "env": { "PYTHONPATH": "${workspaceFolder}" }, // đảm bảo 'src' là package gốc - "console": "integratedTerminal", - "justMyCode": true - } - ] -} + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + + { + "name": "Python Debugger: FastAPI", + "type": "debugpy", + "request": "launch", + "module": "uvicorn", + "args": [ + "main:app", + "--port", "8386", + ], + "jinja": true + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index e69de29..3e977f0 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,21 @@ +How to debug : +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug rag_pipeline (as module)", + "type": "python", + "request": "launch", + "module": "src.chatbot.rag_pipeline", + "cwd": "${workspaceFolder}", + "envFile": "${workspaceFolder}/.env", + "env": { "PYTHONPATH": "${workspaceFolder}" }, + "console": "integratedTerminal", + "justMyCode": true + } + ] +} +(launch.json) + +uvicorn main:app --port 8386 (--host 0.0.0.0) +![alt text](image.png) \ No newline at end of file diff --git a/__pycache__/main.cpython-313.pyc b/__pycache__/main.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c461d4da989e337ec4fa2d266ba7563b77cff8d9 GIT binary patch literal 187 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 z%0D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 literal 0 HcmV?d00001 diff --git a/logs/api_2025-10-08.log b/logs/api_2025-10-08.log new file mode 100644 index 0000000..11a82a0 --- /dev/null +++ b/logs/api_2025-10-08.log @@ -0,0 +1,248 @@ +2025-10-08 23:26:27,626 [INFO] numexpr.utils - NumExpr defaulting to 12 threads. +2025-10-08 23:26:30,539 [INFO] httpx - HTTP Request: GET http://localhost:6333 "HTTP/1.1 200 OK" +2025-10-08 23:26:30,544 [INFO] httpx - HTTP Request: GET http://localhost:6333/collections/text_chunks "HTTP/1.1 200 OK" +2025-10-08 23:26:30,552 [INFO] sentence_transformers.SentenceTransformer - Load pretrained SentenceTransformer: Alibaba-NLP/gte-multilingual-base +2025-10-08 23:26:36,963 [INFO] rag_api - ✅ RAGPipeline đã khởi tạo thành công. +2025-10-08 23:26:40,982 [INFO] rag_api - 📥 Câu hỏi: Kể tên phần mềm miễn phí trên hệ điều hành Linux? +2025-10-08 23:26:41,196 [INFO] httpx - HTTP Request: POST http://localhost:6333/collections/text_chunks/points/search "HTTP/1.1 200 OK" +2025-10-08 23:26:42,517 [INFO] rag_api - ✅ Đã trả lời: Kể tên phần mềm miễn phí trên hệ điều hành Linux? ... +2025-10-08 23:28:23,168 [INFO] numexpr.utils - NumExpr defaulting to 12 threads. +2025-10-08 23:28:26,142 [INFO] httpx - HTTP Request: GET http://localhost:6333 "HTTP/1.1 200 OK" +2025-10-08 23:28:26,146 [INFO] httpx - HTTP Request: GET http://localhost:6333/collections/text_chunks "HTTP/1.1 200 OK" +2025-10-08 23:28:26,153 [INFO] sentence_transformers.SentenceTransformer - Load pretrained SentenceTransformer: Alibaba-NLP/gte-multilingual-base +2025-10-08 23:28:32,452 [INFO] rag_api - ✅ RAGPipeline đã khởi tạo thành công. +2025-10-08 23:28:35,794 [INFO] rag_api - 📥 Câu hỏi: Kể tên phần mềm miễn phí trên hệ điều hành Linux? +2025-10-08 23:28:36,017 [INFO] httpx - HTTP Request: POST http://localhost:6333/collections/text_chunks/points/search "HTTP/1.1 200 OK" +2025-10-08 23:28:36,936 [INFO] root - 📤 Gửi prompt tới LLM: ### Vai trò hệ thống: +Bạn là trợ lý AI chuyên nghiệp, hiểu tiếng Việt, có khả năng trả lời tự nhiên, chính xác và ngắn gọn. Chỉ sử dụng thông tin trong phần ngữ cảnh để trả lời. Nếu không đủ dữ liệu, hãy nói 'Tôi chưa có thông tin để trả lời chính xác' và không phỏng đoán hoặc suy luận thêm. + +### Dữ liệu ngữ cảnh: +Dưới đây là các thông tin có liên quan: + +(Đoạn 1 - score=0.670) +OpenMosix + +openMosix là một hệ thống quản lý các nhóm máy vi tính (tiếng Anh: "cluster") tự do và miễn phí theo giấy phép mã nguồn mở GPL. Hệ thống này cho phép các quá trình vi tính di chuyển từ một máy này đến một máy khác trong nhóm máy của hệ thống nếu như quá trình đó có thể được thi hành nhanh chóng hơn. Hệ thống openMosix hữu ích trong các ứng dụng thường hay truy cập đến phần cứng như các thao tác đọc và ghi trên đĩa cứng. openMosix được phát hành dưới dạng phần mềm vá ("patch") cho hạt nhân Linux. Ngoài ra hệ thống openMosix còn được phát hành theo một số đĩa LiveCD chuyên môn và dưới dạng sẵn sàng để dùng trong hệ điều hành Gentoo Linux. +Hiện tại phiên bản openMosix ổn định chạy trên hệ điều hành Linux nhân 2.4 với cấu trúc máy kiểu Intel x86. Hỗ trợ cho các cấu trúc AMD 64-bit chỉ có trong phiên bản đang được phát triển cho hạt nhân Linux phiên bản 2.6. Phiên bản openMosix dành cho hạt nhân Linux 2.6 đang còn được thử nghiệm. Ngoài ra, các chương trình hỗ trợ người dùng còn chưa có trong phiên bản này. +Hệ thống openMosix được ông Moshe Bar đưa lên mạng vào ngày 10 tháng 2 năm 2002 khi hệ thống Mosix mà ông tham gia phát triển trước đó trở thành phần mềm tư hữu. +Các LiveCD. +GNU/Linux LiveCD có openMosix: + +(Đoạn 2 - score=0.660) +GNU + +GNU là một hệ điều hành và bộ sưu tập phần mềm máy tính phong phú. GNU bao gồm toàn bộ phần mềm tự do, hầu hết được cấp phép theo General Public License (GPL) của GNU Project. +"GNU" là một kiểu viết tắt đệ quy của "GNU's Not Unix!", nó được chọn bởi thiết kế của GNU là tương tự Unix, nhưng khác với Unix vì nó là phần mềm miễn phí và không có mã Unix. Dự án GNU bao gồm nhân hệ điều hành, GNU Hurd, vốn là trọng tâm ban đầu của Free Software Foundation (FSF). Tuy nhiên với trạng thái của hạt nhân Hurd là chưa sẵn sàng ra mắt, các hạt nhân phi GNU, phổ biến nhất là nhân Linux, cũng có thể được sử dụng với phần mềm GNU. Sự kết hợp giữa GNU và Linux đã trở nên phổ biến đến mức bộ đôi này thường được gọi tắt là "Linux", hoặc ít thường xuyên hơn, "GNU/Linux". (xem Tranh cãi về đặt tên GNU/Linux) +Richard Stallman, người sáng lập dự án, xem GNU như một "phương tiện kỹ thuật để kết thúc xã hội". Liên quan đến Lawrence Lessig trong phần giới thiệu về ấn bản thứ hai của cuốn sách "Free Software, Free Society" của mình Stallman đã viết về "các khía cạnh xã hội của phần mềm và cách Phần mềm tự do có thể tạo ra công bằng và xã hội". +Lịch sử. +Việc phát triển hệ điều hành GNU được Richard Stallman khởi xướng khi ông làm việc tại Phòng thí nghiệm trí tuệ nhân tạo MIT. Nó được gọi là Dự án GNU, và được công bố công khai vào ngày 27 tháng 9 năm 1983, trên các nhóm tin net.unix-wizards và net.usoft bởi Stallman. Việc phát triển phần mềm bắt đầu vào ngày 5 tháng 1 năm 1984, khi Stallman nghỉ việc tại Phòng thí nghiệm để họ không thể đòi quyền sở hữu hoặc can thiệp vào việc phân phối các thành phần GNU dưới dạng phần mềm tự do. Richard Stallman đã chọn tên bằng cách sử dụng nhiều cách chơi chữ khác nhau, bao gồm cả bài hát "The Gnu". +Mục tiêu là ra mắt một hệ điều hành phần mềm hoàn toàn tự do. Stallman muốn người dùng máy tính được tự do nghiên cứu mã nguồn của phần mềm họ sử dụng, chia sẻ phần mềm với người khác, sửa đổi hành vi của phần mềm và xuất bản các phiên bản phần mềm được sửa đổi của riêng họ. Triết lý này sau đó đã được xuất bản thành Tuyên ngôn GNU vào tháng 3 năm 1985. +Kinh nghiệm của Richard Stallman với Incompatible Timesharing System (ITS), một hệ điều hành ban đầu được viết bằng hợp ngữ đã trở nên lỗi thời do PDP-10 bị ngừng phát triển, kiến ​​trúc máy tính mà ITS đã viết, dẫn đến một quyết định rằng hệ thống di động là cần thiết. Do đó ông đã quyết định rằng sự phát triển sẽ được bắt đầu bằng C và Lisp làm ngôn ngữ lập trình hệ thống, và GNU sẽ tương thích với Unix. Vào thời điểm đó, Unix đã là một hệ điều hành độc quyền phổ biến … + +(Đoạn 3 - score=0.658) +OpenSUSE Project + +openSUSE Proje … + +### Câu hỏi của người dùng: +Kể tên phần mềm miễn phí trên hệ điều hành Linux? + +### Hướng dẫn cho AI: +- Trả lời ngắn gọn, rõ ràng, đúng trọng tâm. +- Dựa hoàn toàn vào thông tin trong ngữ cảnh. +- Nếu thông tin không có trong ngữ cảnh, hãy nói rõ ràng rằng bạn chưa có dữ liệu để trả lời chính xác. +- Không bịa thêm, không suy diễn. + +### Trả lời: +... +2025-10-08 23:28:36,937 [INFO] rag_api - ✅ Đã trả lời: Kể tên phần mềm miễn phí trên hệ điều hành Linux? ... +2025-10-08 23:29:36,817 [INFO] rag_api - 📥 Câu hỏi: Radio Free Asia là tên viết tắt của đài nào? +2025-10-08 23:29:37,013 [INFO] httpx - HTTP Request: POST http://localhost:6333/collections/text_chunks/points/search "HTTP/1.1 200 OK" +2025-10-08 23:29:37,927 [INFO] root - 📤 Gửi prompt tới LLM: ### Vai trò hệ thống: +Bạn là trợ lý AI chuyên nghiệp, hiểu tiếng Việt, có khả năng trả lời tự nhiên, chính xác và ngắn gọn. Chỉ sử dụng thông tin trong phần ngữ cảnh để trả lời. Nếu không đủ dữ liệu, hãy nói 'Tôi chưa có thông tin để trả lời chính xác' và không phỏng đoán hoặc suy luận thêm. + +### Dữ liệu ngữ cảnh: +Dưới đây là các thông tin có liên quan: + +(Đoạn 1 - score=0.759) +Đài Á Châu Tự Do + +Đài Á Châu Tự Do (tên khác: RFA Tiếng Việt, Đài Châu Á Tự Do; tên tiếng Anh: Radio Free Asia, viết tắt là RFA) là một đài phát thanh tư nhân phi lợi nhuận có trụ sở chính tại Hoa Kỳ và được chính phủ Hoa Kỳ tài trợ nhằm phát sóng các chương trình phát thanh; cung cấp thông tin, tin tức và bình luận trực tuyến cho khán giả tại châu Á. Hoạt động với mục đích giúp những người theo dõi có thể tiếp cận các tin tức độc lập, không bị kiểm duyệt cho một số quốc gia ở châu Á có môi trường truyền thông, tự do báo chí và tự do ngôn luận kém. RFA được tài trợ và hoạt động dưới sự giám sát bởi —USAGM (tên trước đây là Hội đồng Quản trị Phát thanh và Truyền hình Hoa Kỳ—BBG), một cơ quan độc lập của chính phủ Hoa Kỳ nhưng họ phủ nhận rằng bản thân không chịu sự quản lý của chính phủ Hoa Kỳ và các thành viên của họ không có quan hệ mật thiết nào với chính phủ nước này. +Đài Á Châu Tự Do được thành lập dựa trên các nguyên tắc của Đạo luật Phát thanh Quốc tế năm 1994 với mục đích đã nêu là "thúc đẩy các giá trị dân chủ và nhân quyền", mục tiêu ban đầu của RFA nhằm đối địch với các nỗ lực tuyên truyền của Đảng Cộng sản Trung Quốc, cũng như cung cấp các thông tin truyền thông về chính phủ Bắc Triều Tiên. Chương trình đầu tiên của Đài Á Châu Tự Do được phát sóng bằng tiếng Quan Thoại ngày nay đã được mở rộng với 9 thứ tiếng ở châu Á. +Lịch sử. +Giai đoạn đầu. +Đầu thập niên 1950, với những căng thẳng đang gia tăng của cuộc Chiến tranh Lạnh, chính phủ Hoa Kỳ cần một cơ quan vận động chính trị nhằm đối chọi lại Chủ nghĩa cộng sản ở châu Á. Do đó vào năm 1951, Cơ quan Tình báo Trung ương (CIA) quyết định cho thành lập thành lập "Ủy ban Châu Á Tự do" (Committee for Free Asia), có trụ sở chính tại San Francisco, Hoa Kỳ và đồng thời cho phát sóng các chương trình của "Đài phát thanh châu Á tự do" (tiền thân của Đài Á Châu Tự Do- RFA sau này) trên khắp Trung Quốc đại lục và Đông Nam Á thông qua các trạm phát sóng ở Manila, Dhaka, Pakistan (ngày nay là Bangladesh) và Karachi, với văn phòng chính tại Tokyo, Nhật Bản. Sau khi phát sóng, CIA nhận thấy rằng Trung Quốc đại lục có rất ít máy radio thu vô tuyến cá nhân, vì vậy họ đã thiển khai kế hoạch ứng phó đó là sử dụng những quả khinh khí cầu bay từ đảo Đài Loan mang theo những chiếc đài thu thanh nhỏ được điều chỉnh để người dân người dân Trung Quốc có thể sử dụng. Nhưng kế hoạch này đã bị hủy bỏ vì những quả khinh khí cầu này thường bị gió thổi trở lại Đài Loan và không thể tới nơi. Cuối cùng các chương trình phát sóng bị dừng hẳn vào năm 1955 sau khoảng thời gian hoạt động kém hiệu quả. +Tái thành lập và đổi mới. +Mãi cho đến đầu thập niên 90, ở Trung Quốc đại lục ngày càng gia tăng các cuộc đàn áp dân chủ nhất là sau Sự kiện Thiên An Môn vào năm 1989. Thấy được sự cấp bách của vấn đề này dân biểu của Hạ viện Hoa Kỳ đã đề xuất ý tưởng hình thành đạo luật về phát thanh nhằm tìm cách tạo ra một tổ chức để thúc đẩy các giá trị dân chủ và nhân quyền ở châu Á hoạt động theo mô hình của Đài Âu Châu Tự Do. Vào tháng 10 năm 1991, Ủy ban Đối ngoại Thượng viện Hoa Kỳ lần đầu tiên đề xuất và thông qua đề xuất "thành lập một đài phát thanh dành riêng cho Trung Quốc đại lục", đồng thời quyết định lập một ủy ban đặc biệt để nghiên cứu tính khả thi của đề xuất này. Tháng 8 năm 1992, ủy ban đã đệ trình lên Quốc hội Hoa Kỳ và Tổng thống một báo cáo khả thi về việc thành lập "Đài Trung Quốc Tự do", và đã được thông qua. Nhưng sau đó, chính phủ Hoa Kỳ đã không sử dụng cái tên "Đài Trung Quốc Tự do" vì ngoài việc chủ yếu nhắm vào Trung Quốc đại lục, đài còn bao gồm một số quốc gia khác ở Đông Bắc Á và Đông Nam Á.. +Được tái lập lại như một tổ chức tư nhân vào tháng 3 năm 1996, Đài Á Châu Tự Do đã bắt đầu phát thanh trở lại từ tháng 9 năm 1996. Cần chú ý, tổ chức mới này không có liên quan gì đến tổ chức RFA cũ từ những năm thập niên 50 … + +(Đoạn 2 - score=0.662) +Asia Times + +Asia Times (, tiếng Việt: "Thời … + +### Câu hỏi của người dùng: +Radio Free Asia là tên viết tắt của đài nào? + +### Hướng dẫn cho AI: +- Trả lời ngắn gọn, rõ ràng, đúng trọng tâm. +- Dựa hoàn toàn vào thông tin trong ngữ cảnh. +- Nếu thông tin không có trong ngữ cảnh, hãy nói rõ ràng rằng bạn chưa có dữ liệu để trả lời chính xác. +- Không bịa thêm, không suy diễn. + +### Trả lời: +... +2025-10-08 23:29:37,928 [INFO] rag_api - ✅ Đã trả lời: Radio Free Asia là tên viết tắt của đài nào? ... +2025-10-08 23:30:29,152 [INFO] rag_api - 📥 Câu hỏi: Đại học Hanover có bao nhiêu khoa? +2025-10-08 23:30:29,334 [INFO] httpx - HTTP Request: POST http://localhost:6333/collections/text_chunks/points/search "HTTP/1.1 200 OK" +2025-10-08 23:30:30,054 [INFO] root - 📤 Gửi prompt tới LLM: ### Vai trò hệ thống: +Bạn là trợ lý AI chuyên nghiệp, hiểu tiếng Việt, có khả năng trả lời tự nhiên, chính xác và ngắn gọn. Chỉ sử dụng thông tin trong phần ngữ cảnh để trả lời. Nếu không đủ dữ liệu, hãy nói 'Tôi chưa có thông tin để trả lời chính xác' và không phỏng đoán hoặc suy luận thêm. + +### Dữ liệu ngữ cảnh: +Dưới đây là các thông tin có liên quan: + +(Đoạn 1 - score=0.894) +Đại học Hanover + +Đại học Hanover, chính thức là Gottfried Wilhelm Leibniz Universität Hannover hoặc Luh, là một trường đại học nằm ở Hanover, Đức. Trường được thành lập vào năm 1831 và là tổ chức đào tạo đại học lớn thứ hai ở Niedersachsen. Đại học Leibniz Hannover là một thành viên của TU9, một hiệp hội của chín Viện Công nghệ hàng đầu tại Đức. +Lịch sử. +Trường đại học này được thành lập vào năm 1831 là một trường cao đẳng thương mại. Trường đã bắt đầu nghiên cứu toán học, kiến trúc, kỹ thuật, lịch sử tự nhiên, vật lý, hóa học, vẽ, công nghệ, nghiên cứu và kế toán. Năm 1879 trường đã được nâng cấp thành Trường Cao đẳng Công nghệ Hoàng gia, năm 1898 nó đã được trao quyền đào tạo tiến sĩ. +Lĩnh vực của trường đại học này, từ đầu của nó, tập trung vào khoa học và công nghệ. Trong thế kỷ 20, các ngành nghệ thuật và nhân văn đã được bổ sung, và trường đã được sáp nhập thêm Trường Cao đẳng Sư phạm trước đó là một trường độc lập. +Khoa. +Trường có 9 khoa với hơn 150 cấp độ độ đầu tiên toàn thời gian và các khóa học trình độ bán thời gian, khiến cho trường này là trường đại học lớn thứ hai của giáo dục đại học tổ chức ở Lower Saxony. Đội ngũ cán bộ trường đại học này bao gồm 1.120 nhân viên, bao gồm 340 giáo sư, 1.560 nhân viên trong các chức năng hành chính, và có thêm 900 người được tài trợ của bên thứ ba. + +(Đoạn 2 - score=0.630) +Hán học + +Hán học (chữ Hán: 漢學) hay Trung Quốc học (chữ Hán: 中國學) là ngành khoa học chuyên nghiên cứu về Trung Quốc, bao gồm lịch sử, chính trị, xã hội, triết học, kinh tế, thậm chí nghiên cứu cả về cộng đồng người Hoa ở nước ngoài. Đây là khái niệm do người nước ngoài đặt ra, tiếng Anh gọi môn khoa học này là Sinology hay Chinese Studies, còn người Trung Quốc gọi khoa học nghiên cứu về Trung Quốc là Quốc học 國學. +Lịch sử. +Ban đầu Hán học chỉ nghiên cứu về văn hoá cổ đại Trung Quốc, chủ yếu nghiên cứu cổ văn, triết học, văn học, hầu như không bao quát hết xã hội Trung Quốc hiện đại. Sau Chiến tranh thế giới thứ hai, Hán học mới bắt đầu nghiên cứu đến Trung Quốc hiện đại. +Hán học thường được chia làm hai thời kỳ là "Hán học cổ đại" và "Hán học hiện đại". Thời gian phân chia hai thời kỳ này không thống nhất, có ý kiến lấy năm 1850 (thời kỳ Trung Quốc suy yếu) hoặc năm 1911 (Cách mạng Tân Hợi) hoặc năm 1949 (Cộng hoà nhân dân Trung Hoa thành lập) từ về trước là Hán học cổ đại, các nghiên cứu sau này thuộc về Hán học hiện đại. +Hán học, Hoa học và Sinology. +Theo nhận định của học giả Trung Quốc Trương Kỳ Quân, thì danh từ Sinology mà người phương Tây thường dùng là chỉ Hoa học chứ không phải Hán học. Nhiều học giả phương Tây còn đề xướng Tạng học (nghiên cứu về Tây Tạng), Mãn học (nghiên cứu về Mãn Châu), theo quan điểm của các học giả Đại lục là phá hoại sự thống nhất của Trung Quốc. Theo đó thì Hoa học không phải là nghiên cứu về Trung Quốc mà chủ yếu nghiên cứu về các dân tộc thiểu số Trung Quốc. + +(Đoạn 3 - score=0.627) +Viện Thiên văn học của Đại học Hawaii + +Viện Thiên văn học của Đại học Hawaii (, viết tắt: IfA) là một đơn vị nghiên cứu trong hệ thống Đại học Hawaii, do Günther Hasinger làm giám đốc. Trụ sở chính của IfA đặt tại 2680 Woodlawn Drive ở Honolulu, Hawaii, , trong khuôn viên Đại học Hawaii tại Mānoa. Các cơ sở khác đặt tại Pukalani, Maui và Hilo trên đảo Hawaiʻi (Đảo Lớn). IfA tuyển dụng hơn 150 nhà thiên văn học và tình nguyện viên. Các nhà thiên văn IfA thực hiện nghiên cứu vật thể, sao, thiên hà và Hệ Mặt Trời. +Viện Thiên văn học được thành lập năm 1967 để nghiên cứu và quản lý các khu phức hợp quan sát tại Haleakalā, Maui và Đài Quan sát Mauna Kea trên đỉnh Mauna Kea. Nó có khoảng 55 giảng viên và hơn 300 nhân viên. + +(Đoạn 4 - score=0.623) +Đại học Khoa học Đời sống Warszawa + +Đại học Khoa học Đời sống Warszawa (, SGGW) là trường đại học nông nghiệp lớn nhất Ba Lan, được thành lập năm 1816 tại Warszawa. Trường có hơn 2.600 nhân viên bao gồm hơn 1.200 nhà giáo dục học thuật … + +### Câu hỏi của người dùng: +Đại học Hanover có bao nhiêu khoa? + +### Hướng dẫn cho AI: +- Trả lời ngắn gọn, rõ ràng, đúng trọng tâm. +- Dựa hoàn toàn vào thông tin trong ngữ cảnh. +- Nếu thông tin không có trong ngữ cảnh, hãy nói rõ ràng rằng bạn chưa có dữ liệu để trả lời chính xác. +- Không bịa thêm, không suy diễn. + +### Trả lời: +... +2025-10-08 23:30:30,055 [INFO] rag_api - ✅ Đã trả lời: Đại học Hanover có bao nhiêu khoa?... +2025-10-08 23:30:52,036 [INFO] rag_api - 📥 Câu hỏi: Đại học Hanover có bao nhiêu khoa? Gồm các khoa nào? +2025-10-08 23:30:52,244 [INFO] httpx - HTTP Request: POST http://localhost:6333/collections/text_chunks/points/search "HTTP/1.1 200 OK" +2025-10-08 23:30:53,129 [INFO] root - 📤 Gửi prompt tới LLM: ### Vai trò hệ thống: +Bạn là trợ lý AI chuyên nghiệp, hiểu tiếng Việt, có khả năng trả lời tự nhiên, chính xác và ngắn gọn. Chỉ sử dụng thông tin trong phần ngữ cảnh để trả lời. Nếu không đủ dữ liệu, hãy nói 'Tôi chưa có thông tin để trả lời chính xác' và không phỏng đoán hoặc suy luận thêm. + +### Dữ liệu ngữ cảnh: +Dưới đây là các thông tin có liên quan: + +(Đoạn 1 - score=0.901) +Đại học Hanover + +Đại học Hanover, chính thức là Gottfried Wilhelm Leibniz Universität Hannover hoặc Luh, là một trường đại học nằm ở Hanover, Đức. Trường được thành lập vào năm 1831 và là tổ chức đào tạo đại học lớn thứ hai ở Niedersachsen. Đại học Leibniz Hannover là một thành viên của TU9, một hiệp hội của chín Viện Công nghệ hàng đầu tại Đức. +Lịch sử. +Trường đại học này được thành lập vào năm 1831 là một trường cao đẳng thương mại. Trường đã bắt đầu nghiên cứu toán học, kiến trúc, kỹ thuật, lịch sử tự nhiên, vật lý, hóa học, vẽ, công nghệ, nghiên cứu và kế toán. Năm 1879 trường đã được nâng cấp thành Trường Cao đẳng Công nghệ Hoàng gia, năm 1898 nó đã được trao quyền đào tạo tiến sĩ. +Lĩnh vực của trường đại học này, từ đầu của nó, tập trung vào khoa học và công nghệ. Trong thế kỷ 20, các ngành nghệ thuật và nhân văn đã được bổ sung, và trường đã được sáp nhập thêm Trường Cao đẳng Sư phạm trước đó là một trường độc lập. +Khoa. +Trường có 9 khoa với hơn 150 cấp độ độ đầu tiên toàn thời gian và các khóa học trình độ bán thời gian, khiến cho trường này là trường đại học lớn thứ hai của giáo dục đại học tổ chức ở Lower Saxony. Đội ngũ cán bộ trường đại học này bao gồm 1.120 nhân viên, bao gồm 340 giáo sư, 1.560 nhân viên trong các chức năng hành chính, và có thêm 900 người được tài trợ của bên thứ ba. + +(Đoạn 2 - score=0.620) +Hán học + +Hán học (chữ Hán: 漢學) hay Trung Quốc học (chữ Hán: 中國學) là ngành khoa học chuyên nghiên cứu về Trung Quốc, bao gồm lịch sử, chính trị, xã hội, triết học, kinh tế, thậm chí nghiên cứu cả về cộng đồng người Hoa ở nước ngoài. Đây là khái niệm do người nước ngoài đặt ra, tiếng Anh gọi môn khoa học này là Sinology hay Chinese Studies, còn người Trung Quốc gọi khoa học nghiên cứu về Trung Quốc là Quốc học 國學. +Lịch sử. +Ban đầu Hán học chỉ nghiên cứu về văn hoá cổ đại Trung Quốc, chủ yếu nghiên cứu cổ văn, triết học, văn học, hầu như không bao quát hết xã hội Trung Quốc hiện đại. Sau Chiến tranh thế giới thứ hai, Hán học mới bắt đầu nghiên cứu đến Trung Quốc hiện đại. +Hán học thường được chia làm hai thời kỳ là "Hán học cổ đại" và "Hán học hiện đại". Thời gian phân chia hai thời kỳ này không thống nhất, có ý kiến lấy năm 1850 (thời kỳ Trung Quốc suy yếu) hoặc năm 1911 (Cách mạng Tân Hợi) hoặc năm 1949 (Cộng hoà nhân dân Trung Hoa thành lập) từ về trước là Hán học cổ đại, các nghiên cứu sau này thuộc về Hán học hiện đại. +Hán học, Hoa học và Sinology. +Theo nhận định của học giả Trung Quốc Trương Kỳ Quân, thì danh từ Sinology mà người phương Tây thường dùng là chỉ Hoa học chứ không phải Hán học. Nhiều học giả phương Tây còn đề xướng Tạng học (nghiên cứu về Tây Tạng), Mãn học (nghiên cứu về Mãn Châu), theo quan điểm của các học giả Đại lục là phá hoại sự thống nhất của Trung Quốc. Theo đó thì Hoa học không phải là nghiên cứu về Trung Quốc mà chủ yếu nghiên cứu về các dân tộc thiểu số Trung Quốc. + +(Đoạn 3 - score=0.616) +Viện Thiên văn học của Đại học Hawaii + +Viện Thiên văn học của Đại học Hawaii (, viết tắt: IfA) là một đơn vị nghiên cứu trong hệ thống Đại học Hawaii, do Günther Hasinger làm giám đốc. Trụ sở chính của IfA đặt tại 2680 Woodlawn Drive ở Honolulu, Hawaii, , trong khuôn viên Đại học Hawaii tại Mānoa. Các cơ sở khác đặt tại Pukalani, Maui và Hilo trên đảo Hawaiʻi (Đảo Lớn). IfA tuyển dụng hơn 150 nhà thiên văn học và tình nguyện viên. Các nhà thiên văn IfA thực hiện nghiên cứu vật thể, sao, thiên hà và Hệ Mặt Trời. +Viện Thiên văn học được thành lập năm 1967 để nghiên cứu và quản lý các khu phức hợp quan sát tại Haleakalā, Maui và Đài Quan sát Mauna Kea trên đỉnh Mauna Kea. Nó có khoảng 55 giảng viên và hơn 300 nhân viên. + +(Đoạn 4 - score=0.611) +Đại học Khoa học Đời sống Warszawa + +Đại học Khoa học Đời sống Warszawa (, SGGW) là trường đại học nông nghiệp lớn nhất Ba Lan, được thành lập năm 1816 tại Warszawa. Trường có hơn 2.600 nhân viên bao gồm hơn 1.200 nhà giáo dục học thuật … + +### Câu hỏi của người dùng: +Đại học Hanover có bao nhiêu khoa? Gồm các khoa nào? + +### Hướng dẫn cho AI: +- Trả lời ngắn gọn, rõ ràng, đúng trọng tâm. +- Dựa hoàn toàn vào thông tin trong ngữ cảnh. +- Nếu thông tin không có trong ngữ cảnh, hãy nói rõ ràng rằng bạn chưa có dữ liệu để trả lời chính xác. +- Không bịa thêm, không suy diễn. + +### Trả lời: +... +2025-10-08 23:30:53,130 [INFO] rag_api - ✅ Đã trả lời: Đại học Hanover có bao nhiêu khoa? Gồm các khoa nà... +2025-10-08 23:31:11,108 [INFO] rag_api - 📥 Câu hỏi: Đại học Hanover có bao nhiêu khoa? Có bao nhiêu nhân viên? +2025-10-08 23:31:11,185 [INFO] httpx - HTTP Request: POST http://localhost:6333/collections/text_chunks/points/search "HTTP/1.1 200 OK" +2025-10-08 23:31:12,190 [INFO] root - 📤 Gửi prompt tới LLM: ### Vai trò hệ thống: +Bạn là trợ lý AI chuyên nghiệp, hiểu tiếng Việt, có khả năng trả lời tự nhiên, chính xác và ngắn gọn. Chỉ sử dụng thông tin trong phần ngữ cảnh để trả lời. Nếu không đủ dữ liệu, hãy nói 'Tôi chưa có thông tin để trả lời chính xác' và không phỏng đoán hoặc suy luận thêm. + +### Dữ liệu ngữ cảnh: +Dưới đây là các thông tin có liên quan: + +(Đoạn 1 - score=0.886) +Đại học Hanover + +Đại học Hanover, chính thức là Gottfried Wilhelm Leibniz Universität Hannover hoặc Luh, là một trường đại học nằm ở Hanover, Đức. Trường được thành lập vào năm 1831 và là tổ chức đào tạo đại học lớn thứ hai ở Niedersachsen. Đại học Leibniz Hannover là một thành viên của TU9, một hiệp hội của chín Viện Công nghệ hàng đầu tại Đức. +Lịch sử. +Trường đại học này được thành lập vào năm 1831 là một trường cao đẳng thương mại. Trường đã bắt đầu nghiên cứu toán học, kiến trúc, kỹ thuật, lịch sử tự nhiên, vật lý, hóa học, vẽ, công nghệ, nghiên cứu và kế toán. Năm 1879 trường đã được nâng cấp thành Trường Cao đẳng Công nghệ Hoàng gia, năm 1898 nó đã được trao quyền đào tạo tiến sĩ. +Lĩnh vực của trường đại học này, từ đầu của nó, tập trung vào khoa học và công nghệ. Trong thế kỷ 20, các ngành nghệ thuật và nhân văn đã được bổ sung, và trường đã được sáp nhập thêm Trường Cao đẳng Sư phạm trước đó là một trường độc lập. +Khoa. +Trường có 9 khoa với hơn 150 cấp độ độ đầu tiên toàn thời gian và các khóa học trình độ bán thời gian, khiến cho trường này là trường đại học lớn thứ hai của giáo dục đại học tổ chức ở Lower Saxony. Đội ngũ cán bộ trường đại học này bao gồm 1.120 nhân viên, bao gồm 340 giáo sư, 1.560 nhân viên trong các chức năng hành chính, và có thêm 900 người được tài trợ của bên thứ ba. + +(Đoạn 2 - score=0.630) +Viện Thiên văn học của Đại học Hawaii + +Viện Thiên văn học của Đại học Hawaii (, viết tắt: IfA) là một đơn vị nghiên cứu trong hệ thống Đại học Hawaii, do Günther Hasinger làm giám đốc. Trụ sở chính của IfA đặt tại 2680 Woodlawn Drive ở Honolulu, Hawaii, , trong khuôn viên Đại học Hawaii tại Mānoa. Các cơ sở khác đặt tại Pukalani, Maui và Hilo trên đảo Hawaiʻi (Đảo Lớn). IfA tuyển dụng hơn 150 nhà thiên văn học và tình nguyện viên. Các nhà thiên văn IfA thực hiện nghiên cứu vật thể, sao, thiên hà và Hệ Mặt Trời. +Viện Thiên văn học được thành lập năm 1967 để nghiên cứu và quản lý các khu phức hợp quan sát tại Haleakalā, Maui và Đài Quan sát Mauna Kea trên đỉnh Mauna Kea. Nó có khoảng 55 giảng viên và hơn 300 nhân viên. + +(Đoạn 3 - score=0.607) +Đại học Khoa học Đời sống Warszawa + +Đại học Khoa học Đời sống Warszawa (, SGGW) là trường đại học nông nghiệp lớn nhất Ba Lan, được thành lập năm 1816 tại Warszawa. Trường có hơn 2.600 nhân viên bao gồm hơn 1.200 nhà giáo dục học thuật. Từ năm 2005, trường đại học này là một thành viên của tổ chức Euroleague cho Khoa học sự sống (ELLS) được thành lập năm 2001. SGGW cung cấp khoảng 37 lĩnh vực nghiên cứu khác nhau, 13 khoa Khoa học Nông nghiệp, Khoa học Kinh tế, Nhân văn, Kỹ thuật cũng như Khoa học Đời sống. +Khuôn viên. +Khuôn viên trường nằm ở quận cực nam của Warszawa, Ursynów. Khuôn viên có một phần lịch sử, với một cung điện từ thế kỷ 18, và một phần hiện đại nơi có hầu hết các tòa nhà văn phòng khoa và ký túc xá. Trên khuôn viên chính rộng 70 ha, có 12 ký túc xá, thư viện hiện đại, trung tâm thể thao (có sân tennis, phòng thể thao và hồ bơi) một trung tâm ngôn ngữ, phòng khám thú y. + +(Đoạn 4 - score=0.591) +Hán học + +Hán học (chữ Hán: 漢學) hay Trung Quốc học (chữ Hán: 中國學) là ngành khoa học chuyên nghiên cứu về Trung Quốc, bao gồm lịch sử, chính trị, xã hội, triết học, kinh tế, thậm chí nghiên cứu cả về cộng đồng người Hoa ở nước ngoài. Đây là khái niệm do người nước ngoài đặt ra, tiếng Anh gọi môn khoa học này là Sinology hay Chinese Studies, còn người Trung Quốc gọi khoa học nghiên cứu về Trung Quốc là Quốc học 國學. +Lịch sử. +Ban đầu Hán học chỉ nghiên cứu về văn hoá cổ đại Trung Quốc, chủ yếu nghiên cứu cổ văn, triết học, văn học, hầu như không bao quát hết xã hội Trung Quốc hiện đại. Sau Chiến tranh thế giới thứ hai, Hán học mới bắt đầu nghiên cứu đến Trung Quốc hiện đại. +Hán học thường được chia làm hai thời kỳ là "Hán học cổ đại" và "Hán học hiện đại" … + +### Câu hỏi của người dùng: +Đại học Hanover có bao nhiêu khoa? Có bao nhiêu nhân viên? + +### Hướng dẫn cho AI: +- Trả lời ngắn gọn, rõ ràng, đúng trọng tâm. +- Dựa hoàn toàn vào thông tin trong ngữ cảnh. +- Nếu thông tin không có trong ngữ cảnh, hãy nói rõ ràng rằng bạn chưa có dữ liệu để trả lời chính xác. +- Không bịa thêm, không suy diễn. + +### Trả lời: +... +2025-10-08 23:31:12,190 [INFO] rag_api - ✅ Đã trả lời: Đại học Hanover có bao nhiêu khoa? Có bao nhiêu nh... diff --git a/src/api/__pycache__/chat_api.cpython-313.pyc b/src/api/__pycache__/chat_api.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..cc4538c241586aa697aa38f446bc0b8a5e48ac31 GIT binary patch literal 4742 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 literal 0 HcmV?d00001 diff --git a/src/api/chat_api.py b/src/api/chat_api.py index 0eeefcb..062e288 100644 --- a/src/api/chat_api.py +++ b/src/api/chat_api.py @@ -6,37 +6,108 @@ FastAPI cho chatbot RAG. Nhận câu hỏi từ người dùng, trả lời bằng RAGPipeline. """ +import os +import logging from fastapi import FastAPI, HTTPException from pydantic import BaseModel -from src.chatbot.rag_pipeline import RAGPipeline +from datetime import datetime -app = FastAPI(title="RAG Chatbot API", version="1.0") +# ------------------------------------------------------------ +# 🧩 Cấu hình logging (ghi cả ra console và file) +# ------------------------------------------------------------ -rag_pipeline = RAGPipeline() # khởi tạo pipeline dùng chung +# Tạo thư mục logs nếu chưa tồn tại +LOG_DIR = "logs" +os.makedirs(LOG_DIR, exist_ok=True) + +# Tên file log có dạng: logs/api_2025-10-08.log +LOG_FILE = os.path.join(LOG_DIR, f"api_{datetime.now().strftime('%Y-%m-%d')}.log") + +# Định dạng log +log_format = "%(asctime)s [%(levelname)s] %(name)s - %(message)s" + +# Cấu hình handler ghi ra file +file_handler = logging.FileHandler(LOG_FILE, encoding="utf-8") +file_handler.setFormatter(logging.Formatter(log_format)) + +# Cấu hình handler ghi ra console +console_handler = logging.StreamHandler() +console_handler.setFormatter(logging.Formatter(log_format)) + +# Gắn cả hai handler vào root logger +logging.basicConfig( + level=logging.INFO, + handlers=[file_handler, console_handler], +) + +logger = logging.getLogger("rag_api") + +# ------------------------------------------------------------ +# 🚀 Khởi tạo FastAPI +# ------------------------------------------------------------ +app = FastAPI(title="RAG Chatbot API", version="1.3") + +rag_pipeline = None # Pipeline toàn cục +@app.on_event("startup") +async def startup_event(): + """Tải RAGPipeline khi FastAPI khởi động""" + global rag_pipeline + try: + from src.chatbot.rag_pipeline import RAGPipeline + rag_pipeline = RAGPipeline() + logger.info("✅ RAGPipeline đã khởi tạo thành công.") + except Exception as e: + logger.exception("❌ Lỗi khi khởi tạo RAGPipeline") + raise RuntimeError("Không thể khởi tạo RAGPipeline.") + + +# ------------------------------------------------------------ +# 📩 API Models +# ------------------------------------------------------------ class ChatRequest(BaseModel): query: str top_k: int = 5 +# ------------------------------------------------------------ +# 💬 Endpoint: /chat +# ------------------------------------------------------------ @app.post("/chat") async def chat_endpoint(req: ChatRequest): - """ - Nhận câu hỏi người dùng -> gọi RAGPipeline -> trả lời - """ + """Nhận câu hỏi người dùng -> gọi RAGPipeline -> trả lời""" + global rag_pipeline + if rag_pipeline is None: + raise HTTPException(status_code=503, detail="RAGPipeline chưa sẵn sàng.") + + logger.info(f"📥 Câu hỏi: {req.query}") + try: - result = rag_pipeline.query(req.query, top_k=req.top_k) - return { + result = rag_pipeline.run(req.query, top_k=req.top_k) + logging.info(f"📤 Gửi prompt tới LLM: {result['prompt']}...") + response = { "query": req.query, "answer": result["answer"], "context_count": len(result.get("context_used", [])), "context_used": result.get("context_used", []), } + + logger.info(f"✅ Đã trả lời: {req.query[:50]}...") + return response + + except ConnectionError as ce: + logger.error(f"⚠️ Không thể kết nối tới Qdrant: {ce}") + raise HTTPException(status_code=503, detail="Không thể kết nối tới Qdrant.") except Exception as e: - raise HTTPException(status_code=500, detail=str(e)) + logger.exception(f"❌ Lỗi xử lý truy vấn: {e}") + raise HTTPException(status_code=500, detail=f"Lỗi nội bộ: {e}") +# ------------------------------------------------------------ +# 🩺 Endpoint: / (root) +# ------------------------------------------------------------ @app.get("/") async def root(): + """Kiểm tra tình trạng API""" return {"message": "RAG Chatbot API is running 🚀"} diff --git a/src/chatbot/__pycache__/llm_client.cpython-313.pyc b/src/chatbot/__pycache__/llm_client.cpython-313.pyc index 94e0163e914f441364d589f42ec89dcc36f33b9a..49f8b3e1ee5d56cfa0f46fca2a6feeb6380b0348 100644 GIT binary patch delta 20 acmZ3>yOx*xGcPX}0}v#(Jln{yOx*xGcPX}0}!12@OUHlA~pa(7Y3IA diff --git a/src/chatbot/__pycache__/prompt_builder.cpython-313.pyc b/src/chatbot/__pycache__/prompt_builder.cpython-313.pyc index 61914a9760977767c0b05be73fb83c7bbff1e88b..9b8127ab03cf2610fde23d183812bc99760b426d 100644 GIT binary patch literal 5212 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 delta 1709 zcmZ`(PjC}e7=OE)&7Vy+X_6*wQyLaqETN@XYAsDbMW}#4b-Iaw6k|x1CjGNpb~gxI z%8Umyjt4WVGeyQB$OR9MMLm>eMwtnNcySVo)40PpX7J+0SuENE7r&R5QJC?Y+3$Vt z{l0(iz2Dorn|^3jf9rGK;KodQb%ZnjaKjPnsEr19-Zn}*#+mGw-NlcAk|TV^qkc zvyWBy-3D2*M{(t7ZQ-({eL(cOvr~eoDk1K4slc7e3i4U)N8%!}Q4`64_Az;&rMr$O zrG+G?mOf9Wd$X4kGY?P?wZRE4oSH6uEsk+& zM%3P-)@gg(n~6@XN`3l<69v0gkSWL*B*~s43<}xUJJx`~Aa3g&>$+;&=AW#AW#|;? zPFYapjBr{=#ZyvJ(akW=%3_kl=$cqzq~Kc~B{Z+4KSp}dzA1!6nm5Pj5sW+`yoI;+ zuVrw;$^MTQ!xN9ZMrci<11~#KpGh+>xfyQKGlIjY*y2F z=IG4cOs#k^!=>RmML7Ce@dB4B6*6`69Zr=?m&G)9`qo^nctwTlEnVhRX+jXWg9i`w zFgi-E^`hzX$RHFVVzczk}Q0NLWEA7QE(V1vq<~izH8=bm?(J5 z=h1xc{NaVL+yIkkh}5YG;jC_v;qGKbka2#UIHuc9W+sKWn3xiDOIDl^rMJa%`!Gx^3S&?K_Na@s=ph9`zz_d7;if&USH8B~7Tsj4m(&=Ox`p|9lp}y=KhonHbwKxTr}_NVF1(E=FE2hYyz< zkK~5#Hn+|WU1W0mtFGpXtD~SUbw(x~8!;4ZaZXe}IHZ0XB6s~-Q7r=#NOD7!ZnMy@)`odadp_Of-m*6->hPHM+p zL)|-xO|TykiY;#io;HezoE1H)sr;ul=9ws1vEhqbW1OWWA6r5E#W6_3gQag(*;Cz&u4 zBIT`s$e3jzdi9!n@q$~s>E_M-U@C{THqW;9C1SAb87!l)fv5;!m=WnX?*N-63>V`u z<;;d(oA9hB=k412o9&bmt r?wFEN*-7Df`9*NU4_0XbWl#h`+&7VgX~l|&;EH)C;r|nXs;B%13wqAf diff --git a/src/chatbot/__pycache__/rag_pipeline.cpython-313.pyc b/src/chatbot/__pycache__/rag_pipeline.cpython-313.pyc index 0c523b7ec208f5e1115fca97686dd55be55867b6..532bbdabd8da6a115660360d03dcd5dd0af604db 100644 GIT binary patch delta 697 zcmXX^PiWIn98U7yOWSO1x<3}|ss>gMS!IG-MPc^nNxj6XNTAf@(RFrd{3V%s+4Lgl zMI;Db2173%1l>iZ0}*=hI6-hkgw=!KPOTMo^}VdW!}s3zz2BGLm&e=BtYTsE6;RA18_5c5AmI8K@tCVzrnSmA;jD?@@ z@u_P}cp&Vl6HiwkuYOmHU)AEq%^kJ4qh1LA;Zt*axx#Ki+szgF37l1W0!}F~$virW zXUCc1m{)Z155H7>B&?9L`Ej<5kmo~$nvM^cQQ*g*g=^&4CH@H*dU3tifdXjr_bg&5TjfZMwA8bZA8G1QhOr x7OOx#x9xaLb%BSOVQTynae^qhu-vwT7Og-zJdkxo6_vigpr?g1i3QA~{s$%;vKasX delta 531 zcmX|7&ubGw6rSDrku^5inlwQIO%wuUv7i)NJk){(J&A`dxky0bW@sbn?D}?>(o5~B zRWC&bp%XtW+uzj8A`l ztew-38p>IfN#N&7cH0M!zqq$_$Y+}; zZtZ0WYAEq&J~p?L8+?RY`OFtCSM!c>0?^V;F@48~^D$sHpC>akZeZFWzirA}qax$= z{a{284uW$7P}95O^ucu$Wll7REdzf| diff --git a/src/chatbot/__pycache__/retriever.cpython-313.pyc b/src/chatbot/__pycache__/retriever.cpython-313.pyc index a375d3312f8704d75cf1595fb5e269f1124014f5..015c3c44a41d5bc2cde4530d84a1e99bf634b3d0 100644 GIT binary patch delta 1827 zcmbVMO>7%g5Ps|Z@$TAQJBgcrQYR!SZX*X#rzlAal$M{ORzltyg?fpxoK3RLW*t3m zDsUy7LnT}(qC%@m6{kpWh{UDkP~`#w1ouXXlxX1)qzWk!dsN!P$~_;G9BN@>0ItqQjs*bcYc zxq18MRye*Mj&GhE-w22cg@ z0B!6IJzvCH#9}ep>wL?{nG?=${F%OfwDNXgAv>4fuNCO<=e(N!;EW4{W%i(uDwDxB z@hHtUPI;tW));}Z9&V1hXG*GrLjpX#dvZtxFwLfYs&ACFxM5=PX|9F5xm+et@HC$a z{nHg^P<-X7+Q`4PDJ;MdQdyO2BoDEkz6$m~LMs0smK|9`h${TARsKO$Y~-j)3BGaY zF>>V-EEOC&-%sMQ^Sl3iq@=t94O*ZvQ@3X9*)eBWd_Q{{Qlarf%Lu%KI0bQCTAh1`c`Avfi+a1rAEgYKdU=dn2GU0i4{B-)FS z$8l9;|LI87BIBmT?}06mooM@3bYML?u%d57hbj{E^&_R{3wGtw=gOuyyyIM!+L<=T zkSfjCr_j-uV(n`7IHLUS3EGDWY*d$@hU9GTpIjF1B<0YAtxCt8iu_CmhNvZm?*T=I zcd@wad?UA>dlHK98nY8^tMUk{0%?j?{T>v_vG%IuL78-PR|6glg7yz@QMKPW9%w5^ z`Hp)RsszL;>xui^{i|!wt`*mwdoa2F{KY@fM7=C3oGuBk8>T)M^Xgg>#H;!THq1^t4+CFb zyNEkTwDD|vuYgw&`if`Kt;Knr=4{<%4Eidlygs0p5$zw8E1rd?Y|+$TqSwHH$rQhH zz7C#zVTkE?LV#5#8NvlCr46>@mq>>bSh}|A HIE?%^&|goL delta 1597 zcmaJ>O>7%g5Ps|Z@$TAQJGSHeJ8u49lPHa-n-VCc{Hjzcs=T-aWsz%~m&9dbN6+g5 z7E*FRkVAx2ts+`ZxgfbhLU7{9i5mx^Ak|tp6d@ty0$YW`m6>%MM2Z;go1LBc-u%3o zx8DwaFrXbqA}Rqo_2)0Ezsa|>Pp1vl2+eaWVT4)IOys7}`foCmXSufKs~0hS0$f)#`%n`$;}DE;JyaD!tZLj_&P z44V-Vyk!L=j25OH>!YS(#x))wKVo@lX!75Fuomab@y+pKcz-?8+)nC zTf%n8xhVd4dI%t{L@OBHmF%ijuGu=z(&%gyZTwAIs$rFxOok0RmnEGWcWh~HU<7of z0I&{)K=2Ro3+Fp&LWI-F1)NjC#K!R{bdZFA4NE#fdE6tPP{JpiHDBRRlZue%6Xeo1 zAr&z%71&qA*331nxGWr67mn?!jKm@Cz2k(E~e z>A5Qv*Vk!fiOr!oxL$nEsuq`AeudgFS?!iOpD7d1 z@Cdw{W6k>AsXtKk)VSDp`vs4{Yxl)wvRV4_Omp>adT;E>zfi~ggfUH5E)>>^C_;d3jMo?Jicjn(rziaHgZ=sd?8f8VBx?GuEK$W=8@YpYb+)ff3?aJrj z7gD$A1@=08Vmh^NocAM>vyXFq4+t>t8b^fiR%4&<`#ILP%k9NRHeYFl`!`=|X+8I} T^q!W!UEkNnomQkQVDWzgws$w_ diff --git a/src/chatbot/prompt_builder.py b/src/chatbot/prompt_builder.py index 7b0f4e6..d88a58f 100644 --- a/src/chatbot/prompt_builder.py +++ b/src/chatbot/prompt_builder.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """ -PromptBuilder: tạo prompt hoàn chỉnh để gửi đến LLM (RAG). +PromptBuilder: Tạo prompt hoàn chỉnh để gửi đến LLM trong mô hình RAG. """ from typing import List, Dict @@ -8,66 +8,107 @@ from typing import List, Dict class PromptBuilder: """ - Tạo prompt kết hợp giữa context (retrieved documents) và query người dùng. + Xây dựng prompt kết hợp giữa context (retrieved docs) và câu hỏi người dùng. """ def __init__( self, system_prompt: str | None = None, - max_context_len: int = 3000, - context_label: str = "Dưới đây là các thông tin có liên quan:", + max_context_len: int = 4000, + context_label: str = "Dưới đây là các thông tin có liên quan:" ): - # Prompt hệ thống có thể chỉnh để điều khiển phong cách trả lời self.system_prompt = system_prompt or ( - "Bạn là trợ lý AI hiểu tiếng Việt, có khả năng trả lời tự nhiên, chính xác, " - "và súc tích. Khi có thông tin trong ngữ cảnh, hãy dựa vào đó để trả lời. " - "Nếu không có thông tin, hãy nói 'Tôi chưa có dữ liệu để trả lời chính xác.'" + "Bạn là trợ lý AI chuyên nghiệp, hiểu tiếng Việt, " + "có khả năng trả lời tự nhiên, chính xác và ngắn gọn. " + "Chỉ sử dụng thông tin trong phần ngữ cảnh để trả lời. " + "Nếu không đủ dữ liệu, hãy nói 'Tôi chưa có thông tin để trả lời chính xác' " + "và không phỏng đoán hoặc suy luận thêm." ) self.max_context_len = max_context_len self.context_label = context_label + def _smart_truncate(self, text: str, limit: int) -> str: + """Cắt ngắn văn bản theo giới hạn ký tự, ưu tiên dừng ở dấu câu.""" + text = text.strip() + if len(text) <= limit: + return text + + cut = text.rfind(".", 0, limit) + if cut < int(limit * 0.6): # không tìm thấy dấu chấm hợp lý + cut = limit + + return text[:cut].rstrip() + " …" + + # ----------------------------------------------------- + # ----------------------------------------------------- def build_context_block(self, retrieved_docs: List[Dict]) -> str: """ Ghép các đoạn văn bản được truy xuất từ Qdrant thành block context. - Giới hạn độ dài để tránh vượt quá token LLM. + - Luôn đảm bảo có ít nhất một đoạn context. + - Cắt ngắn tự động để không vượt quá giới hạn max_context_len. """ if not retrieved_docs: - return "" + return "(Không có dữ liệu ngữ cảnh)" - # Ghép các đoạn text lại theo độ quan trọng (score cao trước) - sorted_docs = sorted(retrieved_docs, key=lambda x: x["score"], reverse=True) - context_texts = [] + sorted_docs = sorted(retrieved_docs, key=lambda x: x.get("score", 0), reverse=True) + + context_blocks = [] total_len = 0 + budget = self.max_context_len - len(self.context_label) - 50 # trừ phần tiêu đề - for doc in sorted_docs: - chunk = f"[{doc.get('file_name', 'unknown')}] {doc.get('text', '').strip()}" - chunk_len = len(chunk) - if total_len + chunk_len > self.max_context_len: + for i, doc in enumerate(sorted_docs, start=1): + text = (doc.get("text") or "").strip() + if not text: + continue + + header = f"(Đoạn {i} - score={doc.get('score', 0):.3f})\n" + chunk_len = len(header) + len(text) + + if total_len + chunk_len > budget: + remaining = budget - total_len - len(header) + if remaining <= 0: + break + text = self._smart_truncate(text, remaining) + + context_blocks.append(header + text) + total_len += len(header) + len(text) + + if total_len >= budget: break - context_texts.append(chunk) - total_len += chunk_len - joined_context = "\n\n".join(context_texts) - return f"{self.context_label}\n{joined_context}" + # Nếu vì lý do nào đó chưa có đoạn nào, lấy đoạn đầu tiên + if not context_blocks: + first = sorted_docs[0] + header = f"(Đoạn 1 - score={first.get('score', 0):.3f})\n" + text = self._smart_truncate(first.get("text", ""), budget - len(header)) + context_blocks.append(header + text) + return f"{self.context_label}\n\n" + "\n\n".join(context_blocks) + + # ----------------------------------------------------- + # Xây prompt hoàn chỉnh + # ----------------------------------------------------- def build_prompt(self, user_query: str, retrieved_docs: List[Dict]) -> str: """ - Tạo prompt hoàn chỉnh đưa cho LLM. + Tạo prompt hoàn chỉnh cho LLM. """ context_block = self.build_context_block(retrieved_docs) - prompt = f"""### Hệ thống: + prompt = f"""### Vai trò hệ thống: {self.system_prompt} -### Ngữ cảnh: -{context_block or "(Không có dữ liệu ngữ cảnh)"} +### Dữ liệu ngữ cảnh: +{context_block} ### Câu hỏi của người dùng: {user_query} +### Hướng dẫn cho AI: +- Trả lời ngắn gọn, rõ ràng, đúng trọng tâm. +- Dựa hoàn toàn vào thông tin trong ngữ cảnh. +- Nếu thông tin không có trong ngữ cảnh, hãy nói rõ ràng rằng bạn chưa có dữ liệu để trả lời chính xác. +- Không bịa thêm, không suy diễn. + ### Trả lời: """ return prompt - - - diff --git a/src/chatbot/rag_pipeline.py b/src/chatbot/rag_pipeline.py index 8990921..81ba8a2 100644 --- a/src/chatbot/rag_pipeline.py +++ b/src/chatbot/rag_pipeline.py @@ -21,11 +21,16 @@ class RAGPipeline: self.prompt_builder = PromptBuilder() self.llm = LLMClient() - def run(self, user_query: str) -> str: - docs = self.retriever.search(user_query) + def run(self, user_query: str, top_k: int = 5) -> Dict[str, Any]: + """Trả về cả câu trả lời và context dùng""" + docs = self.retriever.search(user_query, top_k=top_k) prompt = self.prompt_builder.build_prompt(user_query, docs) answer = self.llm.generate(prompt) - return answer + return { + "answer": answer, + "context_used": docs, + "prompt": prompt, + } if __name__ == "__main__": pipeline = RAGPipeline() query = "Bạn biết Mahola là ai không?" diff --git a/src/chatbot/retriever.py b/src/chatbot/retriever.py index 3ac6fb2..e3719ef 100644 --- a/src/chatbot/retriever.py +++ b/src/chatbot/retriever.py @@ -25,11 +25,13 @@ class Retriever: qdrant_url: str = QDRANT_URL, qdrant_api_key: str = QDRANT_API_KEY, collection: str = QDRANT_COLLECTION, - top_k: int = 5, + # top_k: int = 5, ): self.collection = collection - self.top_k = top_k + # self.top_k = top_k self.client = QdrantClient(url=qdrant_url, api_key=qdrant_api_key) + info = self.client.get_collection(QDRANT_COLLECTION) + print(info.config) # Model để encode query self.model = SentenceTransformer(model_name, device=device, trust_remote_code=True) @@ -39,13 +41,15 @@ class Retriever: vec = self.model.encode([query], normalize_embeddings=True) return vec[0].tolist() - def search(self, query: str) -> List[Dict[str, Any]]: + def search(self, query: str, top_k: int) -> List[Dict[str, Any]]: """Truy vấn các đoạn văn bản tương tự trong Qdrant""" query_vec = self.encode_query(query) + print("Vector length:", len(query_vec)) + results: List[ScoredPoint] = self.client.search( collection_name=self.collection, query_vector=query_vec, - limit=self.top_k, + limit=top_k, ) formatted = [] @@ -62,9 +66,9 @@ class Retriever: if __name__ == "__main__": # Test nhanh - retriever = Retriever(top_k=3) + retriever = Retriever() query = "Mahola la ai" - results = retriever.search(query) + results = retriever.search(query, top_k=3) for i, r in enumerate(results, 1): print(f"\n[{i}] Score={r['score']:.4f}") print(f"File: {r['file_name']}") diff --git a/src/ingest/__pycache__/ingest_semantic.cpython-313.pyc b/src/ingest/__pycache__/ingest_semantic.cpython-313.pyc index 165b8fa179aa3d742eb7160f0043206525acd441..1d242967fa89d6376f93fda2e915407139bed822 100644 GIT binary patch delta 20 acmZpXZIR{v%*)Hg00gYH&o**b@&N!d_yrIE delta 20 acmZpXZIR{v%*)Hg00dV|A8q8W