diff --git a/backend/danswer/direct_qa/qa_prompts.py b/backend/danswer/direct_qa/qa_prompts.py index d91f718031bc..af170df10743 100644 --- a/backend/danswer/direct_qa/qa_prompts.py +++ b/backend/danswer/direct_qa/qa_prompts.py @@ -106,6 +106,9 @@ def json_chat_processor(question: str, documents: list[str]) -> list[dict[str, s 'Start by reading the following documents and responding with "Acknowledged".' ) + complete_answer_not_found_response = ( + '{"answer": "' + UNCERTAINTY_PAT + '", "quotes": []}' + ) task_msg = ( "Now answer the next user query based on documents above and quote relevant sections.\n" "Respond with a JSON containing the answer and up to three most relevant quotes from the documents.\n" @@ -113,7 +116,7 @@ def json_chat_processor(question: str, documents: list[str]) -> list[dict[str, s "Your responses should be informative and concise.\n" "You MUST prioritize information from provided documents over internal knowledge.\n" "If the query cannot be answered based on the documents, respond with " - '{"answer": "Information not found", "quotes": []}\n' + f"{complete_answer_not_found_response}\n" "If the query requires aggregating whole documents, respond with " '{"answer": "Aggregations not supported", "quotes": []}\n' f"Sample response:\n{json.dumps(SAMPLE_JSON_RESPONSE)}" diff --git a/backend/danswer/direct_qa/question_answer.py b/backend/danswer/direct_qa/question_answer.py index 8d830a2dc02b..f873b71bd6d2 100644 --- a/backend/danswer/direct_qa/question_answer.py +++ b/backend/danswer/direct_qa/question_answer.py @@ -63,8 +63,8 @@ def extract_answer_quotes_freeform( ) # If model just gives back the uncertainty pattern to signify answer isn't found or nothing at all - if null_answer_check == UNCERTAINTY_PAT or not null_answer_check: - return None, None + # if null_answer_check == UNCERTAINTY_PAT or not null_answer_check: + # return None, None # If no answer section, don't care about the quote if answer_raw.lower().strip().startswith(QUOTE_PAT.lower()): diff --git a/web/package-lock.json b/web/package-lock.json index 50265188bc00..9954f33096fc 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -18,7 +18,7 @@ "eslint-config-next": "13.2.4", "formik": "^2.2.9", "js-cookie": "^3.0.5", - "next": "^13.2.4", + "next": "^13.4.4", "postcss": "^8.4.23", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -172,9 +172,9 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" }, "node_modules/@next/env": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.1.tgz", - "integrity": "sha512-eD6WCBMFjLFooLM19SIhSkWBHtaFrZFfg2Cxnyl3vS3DAdFRfnx5TY2RxlkuKXdIRCC0ySbtK9JXXt8qLCqzZg==" + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.4.tgz", + "integrity": "sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg==" }, "node_modules/@next/eslint-plugin-next": { "version": "13.2.4", @@ -185,9 +185,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.1.tgz", - "integrity": "sha512-eF8ARHtYfnoYtDa6xFHriUKA/Mfj/cCbmKb3NofeKhMccs65G6/loZ15a6wYCCx4rPAd6x4t1WmVYtri7EdeBg==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz", + "integrity": "sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==", "cpu": [ "arm64" ], @@ -200,9 +200,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.1.tgz", - "integrity": "sha512-7cmDgF9tGWTgn5Gw+vP17miJbH4wcraMHDCOHTYWkO/VeKT73dUWG23TNRLfgtCNSPgH4V5B4uLHoZTanx9bAw==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz", + "integrity": "sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==", "cpu": [ "x64" ], @@ -215,9 +215,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.1.tgz", - "integrity": "sha512-qwJqmCri2ie8aTtE5gjTSr8S6O8B67KCYgVZhv9gKH44yvc/zXbAY8u23QGULsYOyh1islWE5sWfQNLOj9iryg==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz", + "integrity": "sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==", "cpu": [ "arm64" ], @@ -230,9 +230,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.1.tgz", - "integrity": "sha512-qcC54tWNGDv/VVIFkazxhqH1Bnagjfs4enzELVRlUOoJPD2BGJTPI7z08pQPbbgxLtRiu8gl2mXvpB8WlOkMeA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz", + "integrity": "sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==", "cpu": [ "arm64" ], @@ -245,9 +245,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.1.tgz", - "integrity": "sha512-9TeWFlpLsBosZ+tsm/rWBaMwt5It9tPH8m3nawZqFUUrZyGRfGcI67js774vtx0k3rL9qbyY6+3pw9BCVpaYUA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz", + "integrity": "sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ==", "cpu": [ "x64" ], @@ -260,9 +260,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.1.tgz", - "integrity": "sha512-sNDGaWmSqTS4QRUzw61wl4mVPeSqNIr1OOjLlQTRuyInxMxtqImRqdvzDvFTlDfdeUMU/DZhWGYoHrXLlZXe6A==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz", + "integrity": "sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA==", "cpu": [ "x64" ], @@ -275,9 +275,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.1.tgz", - "integrity": "sha512-+CXZC7u1iXdLRudecoUYbhbsXpglYv8KFYsFxKBPn7kg+bk7eJo738wAA4jXIl8grTF2mPdmO93JOQym+BlYGA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz", + "integrity": "sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==", "cpu": [ "arm64" ], @@ -290,9 +290,9 @@ } }, "node_modules/@next/swc-win32-ia32-msvc": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.1.tgz", - "integrity": "sha512-vIoXVVc7UYO68VwVMDKwJC2+HqAZQtCYiVlApyKEeIPIQpz2gpufzGxk1z3/gwrJt/kJ5CDZjlhYDCzd3hdz+g==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz", + "integrity": "sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==", "cpu": [ "ia32" ], @@ -305,9 +305,9 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.1.tgz", - "integrity": "sha512-n8V5ImLQZibKTu10UUdI3nIeTLkliEXe628qxqW9v8My3BAH2a7H0SaCqkV2OgqFnn8sG1wxKYw9/SNJ632kSA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz", + "integrity": "sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==", "cpu": [ "x64" ], @@ -2742,11 +2742,11 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "node_modules/next": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.1.tgz", - "integrity": "sha512-JBw2kAIyhKDpjhEWvNVoFeIzNp9xNxg8wrthDOtMctfn3EpqGCmW0FSviNyGgOSOSn6zDaX48pmvbdf6X2W9xA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.4.tgz", + "integrity": "sha512-C5S0ysM0Ily9McL4Jb48nOQHT1BukOWI59uC3X/xCMlYIh9rJZCv7nzG92J6e1cOBqQbKovlpgvHWFmz4eKKEA==", "dependencies": { - "@next/env": "13.4.1", + "@next/env": "13.4.4", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", @@ -2761,20 +2761,19 @@ "node": ">=16.8.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "13.4.1", - "@next/swc-darwin-x64": "13.4.1", - "@next/swc-linux-arm64-gnu": "13.4.1", - "@next/swc-linux-arm64-musl": "13.4.1", - "@next/swc-linux-x64-gnu": "13.4.1", - "@next/swc-linux-x64-musl": "13.4.1", - "@next/swc-win32-arm64-msvc": "13.4.1", - "@next/swc-win32-ia32-msvc": "13.4.1", - "@next/swc-win32-x64-msvc": "13.4.1" + "@next/swc-darwin-arm64": "13.4.4", + "@next/swc-darwin-x64": "13.4.4", + "@next/swc-linux-arm64-gnu": "13.4.4", + "@next/swc-linux-arm64-musl": "13.4.4", + "@next/swc-linux-x64-gnu": "13.4.4", + "@next/swc-linux-x64-musl": "13.4.4", + "@next/swc-win32-arm64-msvc": "13.4.4", + "@next/swc-win32-ia32-msvc": "13.4.4", + "@next/swc-win32-x64-msvc": "13.4.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "fibers": ">= 3.1.0", - "node-sass": "^6.0.0 || ^7.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "sass": "^1.3.0" @@ -2786,9 +2785,6 @@ "fibers": { "optional": true }, - "node-sass": { - "optional": true - }, "sass": { "optional": true } @@ -4254,9 +4250,9 @@ } }, "@next/env": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.1.tgz", - "integrity": "sha512-eD6WCBMFjLFooLM19SIhSkWBHtaFrZFfg2Cxnyl3vS3DAdFRfnx5TY2RxlkuKXdIRCC0ySbtK9JXXt8qLCqzZg==" + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.4.tgz", + "integrity": "sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg==" }, "@next/eslint-plugin-next": { "version": "13.2.4", @@ -4267,57 +4263,57 @@ } }, "@next/swc-darwin-arm64": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.1.tgz", - "integrity": "sha512-eF8ARHtYfnoYtDa6xFHriUKA/Mfj/cCbmKb3NofeKhMccs65G6/loZ15a6wYCCx4rPAd6x4t1WmVYtri7EdeBg==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz", + "integrity": "sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==", "optional": true }, "@next/swc-darwin-x64": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.1.tgz", - "integrity": "sha512-7cmDgF9tGWTgn5Gw+vP17miJbH4wcraMHDCOHTYWkO/VeKT73dUWG23TNRLfgtCNSPgH4V5B4uLHoZTanx9bAw==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz", + "integrity": "sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==", "optional": true }, "@next/swc-linux-arm64-gnu": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.1.tgz", - "integrity": "sha512-qwJqmCri2ie8aTtE5gjTSr8S6O8B67KCYgVZhv9gKH44yvc/zXbAY8u23QGULsYOyh1islWE5sWfQNLOj9iryg==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz", + "integrity": "sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==", "optional": true }, "@next/swc-linux-arm64-musl": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.1.tgz", - "integrity": "sha512-qcC54tWNGDv/VVIFkazxhqH1Bnagjfs4enzELVRlUOoJPD2BGJTPI7z08pQPbbgxLtRiu8gl2mXvpB8WlOkMeA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz", + "integrity": "sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==", "optional": true }, "@next/swc-linux-x64-gnu": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.1.tgz", - "integrity": "sha512-9TeWFlpLsBosZ+tsm/rWBaMwt5It9tPH8m3nawZqFUUrZyGRfGcI67js774vtx0k3rL9qbyY6+3pw9BCVpaYUA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz", + "integrity": "sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ==", "optional": true }, "@next/swc-linux-x64-musl": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.1.tgz", - "integrity": "sha512-sNDGaWmSqTS4QRUzw61wl4mVPeSqNIr1OOjLlQTRuyInxMxtqImRqdvzDvFTlDfdeUMU/DZhWGYoHrXLlZXe6A==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz", + "integrity": "sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA==", "optional": true }, "@next/swc-win32-arm64-msvc": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.1.tgz", - "integrity": "sha512-+CXZC7u1iXdLRudecoUYbhbsXpglYv8KFYsFxKBPn7kg+bk7eJo738wAA4jXIl8grTF2mPdmO93JOQym+BlYGA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz", + "integrity": "sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==", "optional": true }, "@next/swc-win32-ia32-msvc": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.1.tgz", - "integrity": "sha512-vIoXVVc7UYO68VwVMDKwJC2+HqAZQtCYiVlApyKEeIPIQpz2gpufzGxk1z3/gwrJt/kJ5CDZjlhYDCzd3hdz+g==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz", + "integrity": "sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==", "optional": true }, "@next/swc-win32-x64-msvc": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.1.tgz", - "integrity": "sha512-n8V5ImLQZibKTu10UUdI3nIeTLkliEXe628qxqW9v8My3BAH2a7H0SaCqkV2OgqFnn8sG1wxKYw9/SNJ632kSA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz", + "integrity": "sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==", "optional": true }, "@nodelib/fs.scandir": { @@ -6034,20 +6030,20 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==" }, "next": { - "version": "13.4.1", - "resolved": "https://registry.npmjs.org/next/-/next-13.4.1.tgz", - "integrity": "sha512-JBw2kAIyhKDpjhEWvNVoFeIzNp9xNxg8wrthDOtMctfn3EpqGCmW0FSviNyGgOSOSn6zDaX48pmvbdf6X2W9xA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/next/-/next-13.4.4.tgz", + "integrity": "sha512-C5S0ysM0Ily9McL4Jb48nOQHT1BukOWI59uC3X/xCMlYIh9rJZCv7nzG92J6e1cOBqQbKovlpgvHWFmz4eKKEA==", "requires": { - "@next/env": "13.4.1", - "@next/swc-darwin-arm64": "13.4.1", - "@next/swc-darwin-x64": "13.4.1", - "@next/swc-linux-arm64-gnu": "13.4.1", - "@next/swc-linux-arm64-musl": "13.4.1", - "@next/swc-linux-x64-gnu": "13.4.1", - "@next/swc-linux-x64-musl": "13.4.1", - "@next/swc-win32-arm64-msvc": "13.4.1", - "@next/swc-win32-ia32-msvc": "13.4.1", - "@next/swc-win32-x64-msvc": "13.4.1", + "@next/env": "13.4.4", + "@next/swc-darwin-arm64": "13.4.4", + "@next/swc-darwin-x64": "13.4.4", + "@next/swc-linux-arm64-gnu": "13.4.4", + "@next/swc-linux-arm64-musl": "13.4.4", + "@next/swc-linux-x64-gnu": "13.4.4", + "@next/swc-linux-x64-musl": "13.4.4", + "@next/swc-win32-arm64-msvc": "13.4.4", + "@next/swc-win32-ia32-msvc": "13.4.4", + "@next/swc-win32-x64-msvc": "13.4.4", "@swc/helpers": "0.5.1", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001406", diff --git a/web/package.json b/web/package.json index 0998975031fd..1f59ddc5a134 100644 --- a/web/package.json +++ b/web/package.json @@ -19,7 +19,7 @@ "eslint-config-next": "13.2.4", "formik": "^2.2.9", "js-cookie": "^3.0.5", - "next": "^13.2.4", + "next": "^13.4.4", "postcss": "^8.4.23", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index 5eebf55aac82..2974f01aefdf 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -8,7 +8,7 @@ import { ApiKeyModal } from "@/components/openai/ApiKeyModal"; import { buildUrl } from "@/lib/utilsSS"; import { Connector, User } from "@/lib/types"; import { cookies } from "next/headers"; -import { SearchType } from "@/components/search/SearchTypeSelector"; +import { SearchType } from "@/lib/search/interfaces"; export default async function Home() { const tasks = [ @@ -35,13 +35,13 @@ export default async function Home() { // needs to be done in a non-client side component due to nextjs const storedSearchType = cookies().get("searchType")?.value as - | keyof typeof SearchType + | string | undefined; let searchTypeDefault: SearchType = storedSearchType !== undefined && SearchType.hasOwnProperty(storedSearchType) - ? SearchType[storedSearchType] - : SearchType.SEMANTIC; // default to semantic search + ? (storedSearchType as SearchType) + : SearchType.AUTOMATIC; // default to automatic return ( <> diff --git a/web/src/components/icons/icons.tsx b/web/src/components/icons/icons.tsx index 2e6e8a5195f0..0edc699ede51 100644 --- a/web/src/components/icons/icons.tsx +++ b/web/src/components/icons/icons.tsx @@ -9,6 +9,8 @@ import { LinkBreak, Link, Plug, + Bird, + Brain, } from "@phosphor-icons/react"; import { SiConfluence, SiGithub, SiGoogledrive, SiSlack } from "react-icons/si"; import { FaFile, FaGlobe } from "react-icons/fa"; @@ -117,3 +119,10 @@ export const InfoIcon = ({ }: IconProps) => { return ; }; + +export const BrainIcon = ({ + size = "16", + className = defaultTailwindCSS, +}: IconProps) => { + return ; +}; diff --git a/web/src/components/search/Filters.tsx b/web/src/components/search/Filters.tsx index 3a39a5ec057c..448a2c4b6655 100644 --- a/web/src/components/search/Filters.tsx +++ b/web/src/components/search/Filters.tsx @@ -35,7 +35,7 @@ export function SourceSelector({ }; return ( -
+

Filters

diff --git a/web/src/components/search/SearchBar.tsx b/web/src/components/search/SearchBar.tsx index a22038b5c5f8..278c519b2516 100644 --- a/web/src/components/search/SearchBar.tsx +++ b/web/src/components/search/SearchBar.tsx @@ -2,15 +2,19 @@ import React, { useState, KeyboardEvent, ChangeEvent } from "react"; import { MagnifyingGlass } from "@phosphor-icons/react"; interface SearchBarProps { - onSearch: (searchTerm: string) => void; + query: string; + setQuery: (query: string) => void; + onSearch: () => void; } -export const SearchBar: React.FC = ({ onSearch }) => { - const [searchTerm, setSearchTerm] = useState(""); - +export const SearchBar: React.FC = ({ + query, + setQuery, + onSearch, +}) => { const handleChange = (event: ChangeEvent) => { const target = event.target; - setSearchTerm(target.value); + setQuery(target.value); // Resize the textarea to fit the content target.style.height = "24px"; @@ -20,7 +24,7 @@ export const SearchBar: React.FC = ({ onSearch }) => { const handleKeyDown = (event: KeyboardEvent) => { if (event.key === "Enter" && !event.shiftKey) { - onSearch(searchTerm); + onSearch(); event.preventDefault(); } }; @@ -34,7 +38,7 @@ export const SearchBar: React.FC = ({ onSearch }) => { role="textarea" aria-multiline placeholder="Search..." - value={searchTerm} + value={query} onChange={handleChange} onKeyDown={handleKeyDown} suppressContentEditableWarning={true} diff --git a/web/src/components/search/SearchHelper.tsx b/web/src/components/search/SearchHelper.tsx new file mode 100644 index 000000000000..08a223ccaba6 --- /dev/null +++ b/web/src/components/search/SearchHelper.tsx @@ -0,0 +1,142 @@ +import { + FlowType, + SearchDefaultOverrides, + SearchRequestOverrides, + SearchResponse, + SearchType, +} from "@/lib/search/interfaces"; +import { BrainIcon } from "../icons/icons"; + +const CLICKABLE_CLASS_NAME = "text-blue-400 cursor-pointer"; +const NUM_DOCUMENTS_FED_TO_GPT = 5; + +interface Props { + isFetching: boolean; + searchResponse: SearchResponse | null; + selectedSearchType: SearchType; + setSelectedSearchType: (searchType: SearchType) => void; + defaultOverrides: SearchDefaultOverrides; + restartSearch: (overrides?: SearchRequestOverrides) => void; + forceQADisplay: () => void; + setOffset: (offset: number) => void; +} + +const getAssistantMessage = ({ + isFetching, + searchResponse, + selectedSearchType, + setSelectedSearchType, + defaultOverrides, + restartSearch, + forceQADisplay, + setOffset, +}: Props): string | JSX.Element | null => { + if (!searchResponse || !searchResponse.suggestedFlowType) { + return null; + } + + if ( + searchResponse.suggestedFlowType === FlowType.SEARCH && + !defaultOverrides.forceDisplayQA && + !isFetching && + searchResponse.answer + ) { + return ( +
+ This doesn't seem like a question for a Generative AI. Do you still + want to have{" "} + + GPT give a response? + +
+ ); + } + + console.log(searchResponse.suggestedSearchType); + console.log(selectedSearchType); + if ( + selectedSearchType !== SearchType.AUTOMATIC && + searchResponse.suggestedSearchType !== selectedSearchType + ) { + if (searchResponse.suggestedSearchType === SearchType.SEMANTIC) { + return ( +
+ Your query looks more like natural language, Semantic Search may yield + better results. Would you like to{" "} + { + setSelectedSearchType(SearchType.SEMANTIC); + restartSearch({ searchType: SearchType.SEMANTIC }); + }} + > + try AI search? + +
+ ); + } + return ( +
+ Your query seems to be a better fit for keyword search. Would you like + to{" "} + { + setSelectedSearchType(SearchType.KEYWORD); + restartSearch({ searchType: SearchType.KEYWORD }); + }} + > + try Keyword search? + +
+ ); + } + + if ( + (searchResponse.suggestedFlowType === FlowType.QUESTION_ANSWER || + defaultOverrides.forceDisplayQA) && + !isFetching && + searchResponse.answer === "" + ) { + return ( +
+ GPT was unable to find an answer in the most relevant{" "} + {` ${(defaultOverrides.offset + 1) * NUM_DOCUMENTS_FED_TO_GPT} `}{" "} + documents. Do you want to{" "} + { + const newOffset = defaultOverrides.offset + 1; + setOffset(newOffset); + restartSearch({ + offset: newOffset, + }); + }} + > + keep searching? + +
+ ); + } + + return null; +}; + +export const SearchHelper: React.FC = (props) => { + const message = getAssistantMessage(props); + + if (!message) { + return null; + } + + return ( +
+
+ + AI Assistant +
+ +

{message}

+
+ ); +}; diff --git a/web/src/components/search/SearchResultsDisplay.tsx b/web/src/components/search/SearchResultsDisplay.tsx index 0fd30be7be9a..dbe0ec53097a 100644 --- a/web/src/components/search/SearchResultsDisplay.tsx +++ b/web/src/components/search/SearchResultsDisplay.tsx @@ -6,8 +6,9 @@ import { DanswerDocument, SearchResponse, Quote, + FlowType, + SearchDefaultOverrides, } from "@/lib/search/interfaces"; -import { SearchType } from "./SearchTypeSelector"; const removeDuplicateDocs = (documents: DanswerDocument[]) => { const seen = new Set(); @@ -27,11 +28,13 @@ const removeDuplicateDocs = (documents: DanswerDocument[]) => { interface SearchResultsDisplayProps { searchResponse: SearchResponse | null; isFetching: boolean; + defaultOverrides: SearchDefaultOverrides; } export const SearchResultsDisplay: React.FC = ({ searchResponse, isFetching, + defaultOverrides, }) => { if (!searchResponse) { return null; @@ -66,58 +69,58 @@ export const SearchResultsDisplay: React.FC = ({ return ( <> - {answer && ( -
-
-
-

AI Answer

-
-

{answer}

+ {answer && + (searchResponse.suggestedFlowType !== FlowType.SEARCH || + defaultOverrides.forceDisplayQA) && ( +
+
+
+

AI Answer

+
+

{answer}

- {quotes !== null && ( - <> -

Sources

- {isFetching && dedupedQuotes.length === 0 ? ( - - ) : ( - - )} - - )} -
-
- )} - - {!answer && - !isFetching && - searchResponse.searchType === SearchType.SEMANTIC && ( -
- -
- GPT hurt itself in its confusion :( + {quotes !== null && ( + <> +

Sources

+ {isFetching && dedupedQuotes.length === 0 ? ( + + ) : ( + + )} + + )}
)} + {(answer === null || answer === undefined) && !isFetching && ( +
+ +
+ GPT hurt itself in its confusion :( +
+
+ )} + {documents && documents.length > 0 && (
diff --git a/web/src/components/search/SearchSection.tsx b/web/src/components/search/SearchSection.tsx index 6bc02382f73d..f9d57b70d447 100644 --- a/web/src/components/search/SearchSection.tsx +++ b/web/src/components/search/SearchSection.tsx @@ -5,15 +5,25 @@ import { SearchBar } from "./SearchBar"; import { SearchResultsDisplay } from "./SearchResultsDisplay"; import { SourceSelector } from "./Filters"; import { Connector } from "@/lib/types"; -import { SearchType, SearchTypeSelector } from "./SearchTypeSelector"; +import { SearchTypeSelector } from "./SearchTypeSelector"; import { DanswerDocument, Quote, SearchResponse, Source, + FlowType, + SearchType, + SearchDefaultOverrides, + SearchRequestOverrides, } from "@/lib/search/interfaces"; -import { aiSearchRequestStreamed } from "@/lib/search/ai"; +import { searchRequestStreamed } from "@/lib/search/streaming"; import Cookies from "js-cookie"; +import { SearchHelper } from "./SearchHelper"; + +const SEARCH_DEFAULT_OVERRIDES_START: SearchDefaultOverrides = { + forceDisplayQA: false, + offset: 0, +}; interface SearchSectionProps { connectors: Connector[]; @@ -24,6 +34,9 @@ export const SearchSection: React.FC = ({ connectors, defaultSearchType, }) => { + // Search Bar + const [query, setQuery] = useState(""); + // Search const [searchResponse, setSearchResponse] = useState( null @@ -37,12 +50,17 @@ export const SearchSection: React.FC = ({ const [selectedSearchType, setSelectedSearchType] = useState(defaultSearchType); - // helpers + // Overrides for default behavior that only last a single query + const [defaultOverrides, setDefaultOverrides] = + useState(SEARCH_DEFAULT_OVERRIDES_START); + + // Helpers const initialSearchResponse: SearchResponse = { answer: null, quotes: null, documents: null, - searchType: selectedSearchType, + suggestedSearchType: null, + suggestedFlowType: null, }; const updateCurrentAnswer = (answer: string) => setSearchResponse((prevState) => ({ @@ -59,10 +77,42 @@ export const SearchSection: React.FC = ({ ...(prevState || initialSearchResponse), documents, })); + const updateSuggestedSearchType = (suggestedSearchType: SearchType) => + setSearchResponse((prevState) => ({ + ...(prevState || initialSearchResponse), + suggestedSearchType, + })); + const updateSuggestedFlowType = (suggestedFlowType: FlowType) => + setSearchResponse((prevState) => ({ + ...(prevState || initialSearchResponse), + suggestedFlowType, + })); + + const onSearch = async ({ + searchType, + offset, + }: SearchRequestOverrides = {}) => { + setIsFetching(true); + setSearchResponse(initialSearchResponse); + + await searchRequestStreamed({ + query, + sources, + updateCurrentAnswer, + updateQuotes, + updateDocs, + updateSuggestedSearchType, + updateSuggestedFlowType, + selectedSearchType: searchType ?? selectedSearchType, + offset: offset ?? defaultOverrides.offset, + }); + + setIsFetching(false); + }; return ( -
-
+
+
{connectors.length > 0 && ( = ({ existingSources={connectors.map((connector) => connector.source)} /> )} + +
+ + setDefaultOverrides((prevState) => ({ + ...(prevState || SEARCH_DEFAULT_OVERRIDES_START), + forceDisplayQA: true, + })) + } + setOffset={(offset) => { + setDefaultOverrides((prevState) => ({ + ...(prevState || SEARCH_DEFAULT_OVERRIDES_START), + offset, + })); + }} + /> +
= ({ /> { - setIsFetching(true); - setSearchResponse({ - answer: null, - quotes: null, - documents: null, - searchType: selectedSearchType, - }); - - await aiSearchRequestStreamed({ - query, - sources, - updateCurrentAnswer, - updateQuotes, - updateDocs, - searchType: selectedSearchType, - }); - - setIsFetching(false); + query={query} + setQuery={setQuery} + onSearch={async () => { + setDefaultOverrides(SEARCH_DEFAULT_OVERRIDES_START); + await onSearch({ offset: 0 }); }} /> @@ -107,6 +166,7 @@ export const SearchSection: React.FC = ({
diff --git a/web/src/components/search/SearchTypeSelector.tsx b/web/src/components/search/SearchTypeSelector.tsx index 593e0b2d5dc0..cae254f2eb15 100644 --- a/web/src/components/search/SearchTypeSelector.tsx +++ b/web/src/components/search/SearchTypeSelector.tsx @@ -1,11 +1,8 @@ +import { SearchType } from "@/lib/search/interfaces"; + const defaultStyle = "py-1 px-2 border rounded border-gray-700 cursor-pointer font-bold "; -export enum SearchType { - SEMANTIC = "SEMANTIC", - KEYWORD = "KEYWORD", -} - interface Props { selectedSearchType: SearchType; setSelectedSearchType: (searchType: SearchType) => void; @@ -20,6 +17,19 @@ export const SearchTypeSelector: React.FC = ({
setSelectedSearchType(SearchType.AUTOMATIC)} + > + Auto +
+ +
| null; documents: DanswerDocument[] | null; @@ -29,11 +41,24 @@ export interface Source { internalName: ValidSources; } +export interface SearchDefaultOverrides { + forceDisplayQA: boolean; + offset: number; +} + export interface SearchRequestArgs { query: string; sources: Source[]; updateCurrentAnswer: (val: string) => void; updateQuotes: (quotes: Record) => void; updateDocs: (documents: DanswerDocument[]) => void; - searchType: SearchType; + updateSuggestedSearchType: (searchType: SearchType) => void; + updateSuggestedFlowType: (flowType: FlowType) => void; + selectedSearchType: SearchType | null; + offset: number | null; +} + +export interface SearchRequestOverrides { + searchType?: SearchType; + offset?: number; } diff --git a/web/src/lib/search/ai.ts b/web/src/lib/search/streaming.ts similarity index 84% rename from web/src/lib/search/ai.ts rename to web/src/lib/search/streaming.ts index d3d592fd74c5..efb4a4acddfe 100644 --- a/web/src/lib/search/ai.ts +++ b/web/src/lib/search/streaming.ts @@ -1,5 +1,9 @@ -import { SearchType } from "@/components/search/SearchTypeSelector"; -import { DanswerDocument, Quote, SearchRequestArgs } from "./interfaces"; +import { + DanswerDocument, + Quote, + SearchRequestArgs, + SearchType, +} from "./interfaces"; const processSingleChunk = ( chunk: string, @@ -45,14 +49,22 @@ const processRawChunkString = ( return [parsedChunkSections, currPartialChunk]; }; -export const aiSearchRequestStreamed = async ({ +export const searchRequestStreamed = async ({ query, sources, updateCurrentAnswer, updateQuotes, updateDocs, - searchType, + updateSuggestedSearchType, + updateSuggestedFlowType, + selectedSearchType, + offset, }: SearchRequestArgs) => { + let useKeyword = null; + if (selectedSearchType !== SearchType.AUTOMATIC) { + useKeyword = selectedSearchType === SearchType.KEYWORD ? true : false; + } + let answer = ""; let quotes: Record | null = null; let relevantDocuments: DanswerDocument[] | null = null; @@ -62,7 +74,7 @@ export const aiSearchRequestStreamed = async ({ body: JSON.stringify({ query, collection: "danswer_index", - use_keyword: searchType === SearchType.KEYWORD, + use_keyword: useKeyword, ...(sources.length > 0 ? { filters: [ @@ -72,6 +84,7 @@ export const aiSearchRequestStreamed = async ({ ], } : {}), + offset: offset, }), headers: { "Content-Type": "application/json", @@ -113,12 +126,15 @@ export const aiSearchRequestStreamed = async ({ // we're now looking for quotes updateQuotes({}); if ( + answer && !answer.endsWith(".") && !answer.endsWith("?") && !answer.endsWith("!") ) { answer += "."; updateCurrentAnswer(answer); + } else { + updateCurrentAnswer(""); } } else { if (Object.hasOwn(chunk, "top_documents")) { @@ -129,6 +145,13 @@ export const aiSearchRequestStreamed = async ({ ); updateDocs(relevantDocuments); } + + if (chunk.predicted_flow) { + updateSuggestedFlowType(chunk.predicted_flow); + } + if (chunk.predicted_search) { + updateSuggestedSearchType(chunk.predicted_search); + } } else { quotes = chunk as Record; updateQuotes(quotes);