Danswer assistant (#96)

Add helper!
This commit is contained in:
Chris Weaver
2023-06-11 17:54:41 -07:00
committed by GitHub
parent 2bfbf037ee
commit 8f5b9c0bcd
14 changed files with 468 additions and 193 deletions

View File

@@ -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)}"

View File

@@ -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()):

178
web/package-lock.json generated
View File

@@ -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",

View File

@@ -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",

View File

@@ -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 (
<>

View File

@@ -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 <Info size={size} className={className} />;
};
export const BrainIcon = ({
size = "16",
className = defaultTailwindCSS,
}: IconProps) => {
return <Brain size={size} className={className} />;
};

View File

@@ -35,7 +35,7 @@ export function SourceSelector({
};
return (
<div className="bg-gray-900 px-6">
<div className="bg-gray-900">
<div className="flex mb-2 pb-1 pl-2 border-b border-gray-800 mx-2">
<h2 className="font-bold my-auto">Filters</h2>
<Funnel className="my-auto ml-2" size="20" />

View File

@@ -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<SearchBarProps> = ({ onSearch }) => {
const [searchTerm, setSearchTerm] = useState<string>("");
export const SearchBar: React.FC<SearchBarProps> = ({
query,
setQuery,
onSearch,
}) => {
const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
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<SearchBarProps> = ({ onSearch }) => {
const handleKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {
if (event.key === "Enter" && !event.shiftKey) {
onSearch(searchTerm);
onSearch();
event.preventDefault();
}
};
@@ -34,7 +38,7 @@ export const SearchBar: React.FC<SearchBarProps> = ({ onSearch }) => {
role="textarea"
aria-multiline
placeholder="Search..."
value={searchTerm}
value={query}
onChange={handleChange}
onKeyDown={handleKeyDown}
suppressContentEditableWarning={true}

View File

@@ -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 (
<div>
This doesn&apos;t seem like a question for a Generative AI. Do you still
want to have{" "}
<span className={CLICKABLE_CLASS_NAME} onClick={forceQADisplay}>
GPT give a response?
</span>
</div>
);
}
console.log(searchResponse.suggestedSearchType);
console.log(selectedSearchType);
if (
selectedSearchType !== SearchType.AUTOMATIC &&
searchResponse.suggestedSearchType !== selectedSearchType
) {
if (searchResponse.suggestedSearchType === SearchType.SEMANTIC) {
return (
<div>
Your query looks more like natural language, Semantic Search may yield
better results. Would you like to{" "}
<span
className={CLICKABLE_CLASS_NAME}
onClick={() => {
setSelectedSearchType(SearchType.SEMANTIC);
restartSearch({ searchType: SearchType.SEMANTIC });
}}
>
try AI search?
</span>
</div>
);
}
return (
<div>
Your query seems to be a better fit for keyword search. Would you like
to{" "}
<span
className={CLICKABLE_CLASS_NAME}
onClick={() => {
setSelectedSearchType(SearchType.KEYWORD);
restartSearch({ searchType: SearchType.KEYWORD });
}}
>
try Keyword search?
</span>
</div>
);
}
if (
(searchResponse.suggestedFlowType === FlowType.QUESTION_ANSWER ||
defaultOverrides.forceDisplayQA) &&
!isFetching &&
searchResponse.answer === ""
) {
return (
<div>
GPT was unable to find an answer in the most relevant{" "}
<b>{` ${(defaultOverrides.offset + 1) * NUM_DOCUMENTS_FED_TO_GPT} `}</b>{" "}
documents. Do you want to{" "}
<span
className={CLICKABLE_CLASS_NAME}
onClick={() => {
const newOffset = defaultOverrides.offset + 1;
setOffset(newOffset);
restartSearch({
offset: newOffset,
});
}}
>
keep searching?
</span>
</div>
);
}
return null;
};
export const SearchHelper: React.FC<Props> = (props) => {
const message = getAssistantMessage(props);
if (!message) {
return null;
}
return (
<div className="border border-gray-800 rounded p-3 text-sm">
<div className="flex">
<BrainIcon size="20" />
<b className="ml-2">AI Assistant</b>
</div>
<p className="mt-1 text-gray-300">{message}</p>
</div>
);
};

View File

@@ -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<string>();
@@ -27,11 +28,13 @@ const removeDuplicateDocs = (documents: DanswerDocument[]) => {
interface SearchResultsDisplayProps {
searchResponse: SearchResponse | null;
isFetching: boolean;
defaultOverrides: SearchDefaultOverrides;
}
export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
searchResponse,
isFetching,
defaultOverrides,
}) => {
if (!searchResponse) {
return null;
@@ -66,8 +69,10 @@ export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
return (
<>
{answer && (
<div className="h-56">
{answer &&
(searchResponse.suggestedFlowType !== FlowType.SEARCH ||
defaultOverrides.forceDisplayQA) && (
<div className="min-h-[14rem]">
<div className="p-4 border-2 rounded-md border-gray-700">
<div className="flex mb-1">
<h2 className="text font-bold my-auto">AI Answer</h2>
@@ -104,9 +109,7 @@ export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
</div>
)}
{!answer &&
!isFetching &&
searchResponse.searchType === SearchType.SEMANTIC && (
{(answer === null || answer === undefined) && !isFetching && (
<div className="flex">
<InfoIcon
size="20"

View File

@@ -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<any>[];
@@ -24,6 +34,9 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
connectors,
defaultSearchType,
}) => {
// Search Bar
const [query, setQuery] = useState<string>("");
// Search
const [searchResponse, setSearchResponse] = useState<SearchResponse | null>(
null
@@ -37,12 +50,17 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
const [selectedSearchType, setSelectedSearchType] =
useState<SearchType>(defaultSearchType);
// helpers
// Overrides for default behavior that only last a single query
const [defaultOverrides, setDefaultOverrides] =
useState<SearchDefaultOverrides>(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<SearchSectionProps> = ({
...(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 (
<div className="relative max-w-[1500px] mx-auto">
<div className="absolute left-0 ml-24 hidden 2xl:block">
<div className="relative max-w-[2000px] xl:max-w-[1400px] mx-auto">
<div className="absolute left-0 hidden 2xl:block w-64">
{connectors.length > 0 && (
<SourceSelector
selectedSources={sources}
@@ -70,6 +120,29 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
existingSources={connectors.map((connector) => connector.source)}
/>
)}
<div className="mt-10">
<SearchHelper
isFetching={isFetching}
searchResponse={searchResponse}
selectedSearchType={selectedSearchType}
setSelectedSearchType={setSelectedSearchType}
defaultOverrides={defaultOverrides}
restartSearch={onSearch}
forceQADisplay={() =>
setDefaultOverrides((prevState) => ({
...(prevState || SEARCH_DEFAULT_OVERRIDES_START),
forceDisplayQA: true,
}))
}
setOffset={(offset) => {
setDefaultOverrides((prevState) => ({
...(prevState || SEARCH_DEFAULT_OVERRIDES_START),
offset,
}));
}}
/>
</div>
</div>
<div className="w-[800px] mx-auto">
<SearchTypeSelector
@@ -81,25 +154,11 @@ export const SearchSection: React.FC<SearchSectionProps> = ({
/>
<SearchBar
onSearch={async (query) => {
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<SearchSectionProps> = ({
<SearchResultsDisplay
searchResponse={searchResponse}
isFetching={isFetching}
defaultOverrides={defaultOverrides}
/>
</div>
</div>

View File

@@ -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<Props> = ({
<div
className={
defaultStyle +
(selectedSearchType === SearchType.AUTOMATIC
? "bg-blue-500"
: "bg-gray-800 hover:bg-gray-600")
}
onClick={() => setSelectedSearchType(SearchType.AUTOMATIC)}
>
Auto
</div>
<div
className={
defaultStyle +
"ml-2 " +
(selectedSearchType === SearchType.SEMANTIC
? "bg-blue-500"
: "bg-gray-800 hover:bg-gray-600")

View File

@@ -1,6 +1,17 @@
import { SearchType } from "@/components/search/SearchTypeSelector";
import { ValidSources } from "../types";
export const FlowType = {
SEARCH: "search",
QUESTION_ANSWER: "question-answer",
};
export type FlowType = (typeof FlowType)[keyof typeof FlowType];
export const SearchType = {
SEMANTIC: "semantic",
KEYWORD: "keyword",
AUTOMATIC: "automatic",
};
export type SearchType = (typeof SearchType)[keyof typeof SearchType];
export interface Quote {
document_id: string;
link: string;
@@ -18,7 +29,8 @@ export interface DanswerDocument {
}
export interface SearchResponse {
searchType: SearchType;
suggestedSearchType: SearchType | null;
suggestedFlowType: FlowType | null;
answer: string | null;
quotes: Record<string, Quote> | 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<string, Quote>) => 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;
}

View File

@@ -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<string, Quote> | 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<string, Quote>;
updateQuotes(quotes);