@@ -3,19 +3,28 @@ import log from '../log.js';
33import config from '../config.js' ;
44import { type RedisVectorStore } from 'langchain/vectorstores/redis' ;
55import { type ApiConfig } from './index.js' ;
6- import { type Prompt } from './prompt.js' ;
6+ import { type AnswerDocument , type Prompt } from './prompt.js' ;
77
88export interface SearchConfig extends Pick < ApiConfig , 'prefix' > {
99 vectorStore : RedisVectorStore ;
1010 answerVectorStore : RedisVectorStore ;
1111 prompt : Prompt ;
1212}
1313
14+ export interface VideoSearchOptions {
15+ useCache ?: boolean ;
16+ }
17+
1418export interface Search {
1519 searchVideos : (
1620 question : string ,
21+ options ?: VideoSearchOptions ,
1722 ) => Promise <
18- Record < string , any > | { videos : VideoDocument [ ] ; answer : string }
23+ Array < {
24+ videos : VideoDocument [ ] ;
25+ answer : string ;
26+ isOriginal ?: boolean | undefined ;
27+ } >
1928 > ;
2029}
2130
@@ -56,41 +65,68 @@ export default function initialize({
5665 /**
5766 * Scores will be between 0 and 1, where 0 is most accurate and 1 is least accurate
5867 */
59- const [ result ] = await answerVectorStore . similaritySearchWithScore (
68+ let results = ( await answerVectorStore . similaritySearchWithScore (
6069 question ,
61- 1 ,
62- ) ;
70+ config . searches . KNN ,
71+ ) ) as Array < [ AnswerDocument , number ] > ;
6372
64- if ( Array . isArray ( result ) && result . length > 0 ) {
65- log . debug ( `Found closest answer with score: ${ String ( result [ 1 ] ) } ` , {
66- location : ` ${ prefix } .search.getAnswer` ,
67- score : result [ 1 ] ,
68- } ) ;
73+ if ( Array . isArray ( results ) && results . length > 0 ) {
74+ // Filter out results with too high similarity score
75+ results = results . filter (
76+ ( result ) => result [ 1 ] <= config . searches . maxSimilarityScore ,
77+ ) ;
6978
70- if ( result [ 1 ] < config . searches . maxSimilarityScore ) {
71- log . debug ( `Found answer to question ${ question } ` , {
72- location : `${ prefix } .search.getAnswer` ,
73- } ) ;
79+ const inaccurateResults = results . filter (
80+ ( result ) => result [ 1 ] > config . searches . maxSimilarityScore ,
81+ ) ;
7482
75- return result [ 0 ] . metadata ;
83+ if (
84+ Array . isArray ( inaccurateResults ) &&
85+ inaccurateResults . length > 0
86+ ) {
87+ log . debug (
88+ `Rejected ${ inaccurateResults . length } similar answers that have a score > ${ config . searches . maxSimilarityScore } ` ,
89+ {
90+ location : `${ prefix } .search.getAnswer` ,
91+ scores : inaccurateResults . map ( ( result ) => result [ 1 ] ) ,
92+ } ,
93+ ) ;
7694 }
95+ }
96+
97+ if ( Array . isArray ( results ) && results . length > 0 ) {
98+ log . debug (
99+ `Accepted ${ results . length } similar answers that have a score <= ${ config . searches . maxSimilarityScore } ` ,
100+ {
101+ location : `${ prefix } .search.getAnswer` ,
102+ scores : results . map ( ( result ) => result [ 1 ] ) ,
103+ } ,
104+ ) ;
77105
78- log . debug ( `Score too low for question ${ question } ` , {
79- location : `${ prefix } .search.getAnswer` ,
80- score : result [ 1 ] ,
106+ return results . map ( ( result ) => {
107+ return {
108+ ...result [ 0 ] . metadata ,
109+ question : result [ 0 ] . pageContent ,
110+ isOriginal : false ,
111+ } ;
81112 } ) ;
82113 }
83114 }
84115
85- async function searchVideos ( question : string ) {
116+ async function searchVideos (
117+ question : string ,
118+ { useCache = config . searches . answerCache } : VideoSearchOptions = { } ,
119+ ) {
86120 log . debug ( `Original question: ${ question } ` , {
87121 location : `${ prefix } .search.search` ,
88122 } ) ;
89123
90- const existingAnswer = await checkAnswerCache ( question ) ;
124+ if ( useCache ) {
125+ const existingAnswer = await checkAnswerCache ( question ) ;
91126
92- if ( typeof existingAnswer !== 'undefined' ) {
93- return existingAnswer ;
127+ if ( typeof existingAnswer !== 'undefined' ) {
128+ return existingAnswer ;
129+ }
94130 }
95131
96132 const semanticQuestion = await prompt . getSemanticQuestion ( question ) ;
@@ -115,14 +151,19 @@ export default function initialize({
115151 location : `${ prefix } .search.search` ,
116152 } ) ;
117153
118- // TODO: modify the prompt to ask both questions
119154 const answerDocument = await prompt . answerQuestion ( question , videos ) ;
120155
121156 if ( config . searches . answerCache ) {
122157 await answerVectorStore . addDocuments ( [ answerDocument ] ) ;
123158 }
124159
125- return answerDocument . metadata ;
160+ return [
161+ {
162+ ...answerDocument . metadata ,
163+ question : answerDocument . pageContent ,
164+ isOriginal : true ,
165+ } ,
166+ ] ;
126167 }
127168
128169 return {
0 commit comments