ਜ਼ਿਆਦਾਤਰ RAG ਡੈਮੋ ਲੈਪਟਾਪ 'ਤੇ ਬਹੁਤ ਸ਼ਾਨਦਾਰ ਲੱਗਦੇ ਹਨ। ਇੱਕ ਸਕ੍ਰਿਪਟ ਨੂੰ ਵੀਹ-ਪੰਨੇ ਦੀ PDF ਦਿਓ, ਇੱਕ ਸਵਾਲ ਪੁੱਛੋ, ਅਤੇ ਦੇਖੋ ਕਿ ਇਹ ਸਹੀ ਪੈਰਾਗ੍ਰਾਫ ਦਾ ਹਵਾਲਾ ਕਿਵੇਂ ਦਿੰਦਾ ਹੈ। ਪਰ ਉਸੇ ਪਾਈਪਲਾਈਨ ਨੂੰ ਪ੍ਰੋਡਕਸ਼ਨ ਵਿੱਚ ਲਿਜਾਣਾ ਉਹ ਜਗ੍ਹਾ ਹੈ ਜਿੱਥੇ ਰੋਮਾਂਸ ਖਤਮ ਹੋ ਜਾਂਦਾ ਹੈ। ਕਾਨੂੰਨੀ ਦਸਤਾਵੇਜ਼ ਵਾਕਾਂ ਦੇ ਪੱਧਰ 'ਤੇ ਅੱਧੇ-ਅੱਧੇ ਟੁਕੜੇ ਹੋ ਜਾਂਦੇ ਹਨ। ਭਾਰੀ API ਰੈਫਰੈਂਸ ਮਹੱਤਵਪੂਰਨ ਜਾਣਕਾਰੀ ਨੂੰ ਬੇਲੋੜੀ ਰੌਲੇ (boilerplate noise) ਵਿੱਚ ਡੋਬ ਦਿੰਦੇ ਹਨ। ਲੇਟੈਂਸੀ (Latency) ਵਧ ਜਾਂਦੀ ਹੈ। ਯੂਜ਼ਰ ਇੰਤਜ਼ਾਰ ਕਰਦੇ ਹਨ, ਪਰੇਸ਼ਾਨ ਹੁੰਦੇ ਹਨ ਅਤੇ ਚਲੇ ਜਾਂਦੇ ਹਨ। ਅਸੀਂ ਇਸ ਮੁਸ਼ਕਲ ਦਾ ਸਖ਼ਤ ਸਾਹਮਣਾ ਕੀਤਾ। ਇਸ ਲਈ ਅਸੀਂ ਰਿਟ੍ਰੀਵਲ ਲੇਅਰ (retrieval layer) ਨੂੰ ਪੂਰੀ ਤਰ੍ਹਾਂ ਖੋਲ੍ਹ ਦਿੱਤਾ ਅਤੇ ਇਸਨੂੰ ਇੱਕ ਮਾਪਯੋਗ ਅਤੇ ਟਿਊਨੇਬਲ (tunable) ਸਿਸਟਮ ਵਜੋਂ ਮੁੜ ਬਣਾਇਆ। ਨਤੀਜਾ ਇੱਕ ਅਜਿਹੀ ਪਾਈਪਲਾਈਨ ਸੀ ਜੋ ਯੂਜ਼ਰ ਐਕਸਪੀਰੀਅੰਸ ਨੂੰ ਸੁਸਤ ਬਣਾਏ ਬਿਨਾਂ 95% ਰੀਕਾਲ (recall) ਪ੍ਰਾਪਤ ਕਰਦੀ ਹੈ।
ਪ੍ਰੋਡਕਸ਼ਨ ਵਿੱਚ RAG ਡੈਮੋ ਕਿਉਂ ਫੇਲ੍ਹ ਹੋ ਜਾਂਦੇ ਹਨ
ਸ਼ੌਕੀਆ ਪ੍ਰੋਜੈਕਟਾਂ ਅਤੇ ਸ਼ੁਰੂਆਤੀ ਪੜਾਅ ਦੇ ਉਤਪਾਦਾਂ ਵਿੱਚ ਸਟੈਂਡਰਡ ਸਟੈਕ ਹੈਰਾਨੀਜਨਕ ਤੌਰ 'ਤੇ ਇੱਕੋ ਜਿਹਾ ਹੁੰਦਾ ਹੈ: ਫਿਕਸਡ ਟੋਕਨ ਚੰਕਸ (fixed token chunks), ਆਫ-ਦ-ਸ਼ੈਲਫ ਐਂਬੈਡਿੰਗਜ਼ (off-the-shelf embeddings), ਅਤੇ ਇੱਕ ਸਿੰਗਲ ਵੈਕਟਰ ਸਰਚ ਕਾਲ। ਉਹ ਸਾਦਗੀ ਆਕਰਸ਼ਕ ਲੱਗਦੀ ਹੈ, ਅਤੇ ਇਹ ਉਦੋਂ ਕੰਮ ਕਰਦੀ ਹੈ ਜਦੋਂ ਤੁਹਾਡਾ ਕੋਰਪਸ (corpus) ਸਾਫ਼, ਛੋਟਾ ਅਤੇ ਵਾਕ-ਰਚਨਾ ਦੇ ਅਨੁਸਾਰ ਅਨੁਮਾਨਯੋਗ ਹੋਵੇ। ਪ੍ਰੋਡਕਸ਼ਨ ਡੇਟਾ ਇਹਨਾਂ ਵਿੱਚੋਂ ਕੁਝ ਵੀ ਨਹੀਂ ਹੁੰਦਾ। 512 ਟੋਕਨਾਂ ਦਾ ਇੱਕ ਫਿਕਸਡ ਚੰਕ ਇੱਕ SaaS ਕੰਟਰੈਕਟ ਵਿੱਚ ਇੰਡੈਮਨੀਫਿਕੇਸ਼ਨ ਕਲਾਜ਼ (indemnification clause) ਦੇ ਵਿਚਕਾਰੋਂ ਹੀ ਕੱਟ ਦੇਵੇਗਾ। ਅਚਾਨਕ ਤੁਹਾਡੀ ਰਿਟ੍ਰੀਵਲ ਲੇਅਰ ਲੈਂਗੂਏਜ ਮਾਡਲ ਨੂੰ ਇੱਕ ਕਾਨੂੰਨੀ ਜ਼ਿੰਮੇਵਾਰੀ ਦਾ ਅੱਧਾ ਹਿੱਸਾ ਦੇ ਰਹੀ ਹੁੰਦੀ ਹੈ ਅਤੇ ਉਸਨੂੰ ਲਾਇਬਿਲਟੀ (liability) ਦੇ ਸਵਾਲ ਦਾ ਜਵਾਬ ਦੇਣ ਲਈ ਕਹਿੰਦੀ ਹੈ। ਮਾਡਲ ਹਲੂਸੀਨੇਟ (hallucinates) ਕਰਦਾ ਹੈ ਕਿਉਂਕਿ ਸੰਦਰਭ (context) ਟੁੱਟ ਚੁੱਕਾ ਹੁੰਦਾ ਹੈ।
ਵੱਡੇ ਤਕਨੀਕੀ ਦਸਤਾਵੇਜ਼ ਇਸ ਸਮੱਸਿਆ ਨੂੰ ਹੋਰ ਵਧਾ ਦਿੰਦੇ ਹਨ। API ਡਾਕੂਮੈਂਟੇਸ਼ਨ ਫੰਕਸ਼ਨ ਸਿਗਨੇਚਰਾਂ, ਟੇਬਲਾਂ ਅਤੇ ਕੋਡ ਬਲਾਕਾਂ ਨਾਲ ਭਰਪੂਰ ਹੁੰਦੀ ਹੈ। ਇੱਕ ਫਿਕਸਡ ਵਿੰਡੋ ਇੱਕ TypeScript ਇੰਟਰਫੇਸ ਦੇ ਵਿਚਕਾਰਲੇ ਹਿੱਸੇ ਨੂੰ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ ਪਰ ਇਸਦੇ ਉੱਪਰਲੇ ਫੰਕਸ਼ਨ ਦੇ ਨਾਮ ਅਤੇ ਇਸਦੇ ਹੇਠਾਂ ਦਿੱਤੇ ਵਰਤੋਂ ਦੇ ਉਦਾਹਰਣ ਨੂੰ ਛੱਡ ਸਕਦੀ ਹੈ। ਐਂਬੈਡਿੰਗ ਵੈਕਟਰ ਅੰਤ ਵਿੱਚ ਅਸਲ ਸਮਰੱਥਾ ਦੀ ਬਜਾਏ ਸਿੰਟੈਕਸ ਦੇ ਟੁਕੜਿਆਂ ਅਤੇ ਇਨਲਾਈਨ ਰੌਲੇ (
ਫਿਊਜ਼ਨ (fusion) ਤੋਂ ਬਾਅਦ, ਅਸੀਂ ਚੋਟੀ ਦੇ ਉਮੀਦਵਾਰਾਂ ਨੂੰ cross-encoder reranker ਰਾਹੀਂ ਚਲਾਉਂਦੇ ਹਾਂ। ਇਹ ਮੁਫ਼ਤ ਨਹੀਂ ਹੈ। ਇਹ ਲਗਭਗ 50 ਮਿਲੀਸਕਿੰਟ ਦਾ ਕੰਪਿਊਟ (compute) ਵਧਾ ਦਿੰਦਾ ਹੈ। ਇਹ recall ਨੂੰ 15% ਵੀ ਵਧਾਉਂਦਾ ਹੈ। cross-encoder ਪੂਰੀ ਕੁਐਰੀ ਅਤੇ ਹਰੇਕ ਉਮੀਦਵਾਰ ਚੰਕ (candidate chunk) ਦਾ ਇਕੱਠੇ ਮੁਲਾਂਕਣ ਕਰਦਾ ਹੈ, ਜਿਸ ਨਾਲ ਇੱਕ ਅਜਿਹਾ ਪ੍ਰਸੰਗਿਕ ਸਕੋਰ (relevance score) ਪ੍ਰਾਪਤ ਹੁੰਦਾ ਹੈ ਜੋ bi-encoder embedding ਨਾਲੋਂ ਕਿਤੇ ਜ਼ਿਆਦਾ ਸਟੀਕ ਹੁੰਦਾ ਹੈ। ਉਹ ਵਾਧੂ 50 ਮਿਲੀਸਕਿੰਟ ਇੱਕ ਬਹੁਤ ਹੀ ਫਾਇਦੇਮੰਦ ਸੌਦਾ ਹੈ। ਇਹ ਤੁਹਾਨੂੰ LLM ਨੂੰ ਗੈਰ-ਜ਼ਰੂਰੀ (garbage) context window ਭੇਜਣ ਅਤੇ ਇੱਕ ਭੁਲੇਖੇ ਜਾਂ hallucinated ਉੱਤਰ ਲਈ ਦੋ ਸੈਕਿੰਡ ਇੰਤਜ਼ਾਰ ਕਰਨ ਤੋਂ ਬਚਾਉਂਦਾ ਹੈ।
ਸਰਚ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਕੁਐਰੀ (Query) ਨੂੰ ਠੀਕ ਕਰੋ
ਯੂਜ਼ਰਸ ਸਰਚ ਇੰਜੀਨੀਅਰਾਂ ਵਾਂਗ ਕੁਐਰੀਆਂ ਨਹੀਂ ਲਿਖਦੇ। ਉਹ "app broken" ਟਾਈਪ ਕਰਦੇ ਹਨ। ਉਹ ਰਹੱਸਮਈ log fragments ਪੇਸਟ ਕਰਦੇ ਹਨ। ਉਹ ਅਸਪਸ਼ਟ ਅਤੇ ਦੁਬਿਧਾ ਵਾਲੇ ਸਵਾਲ ਪੁੱਛਦੇ ਹਨ। ਜੇਕਰ ਤੁਸੀਂ ਉਹਨਾਂ raw strings ਨੂੰ ਸਿੱਧਾ ਇੰਡੈਕਸ ਨੂੰ ਭੇਜ ਦਿੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਨੂੰ ਬਦਲ ਵਿੱਚ ਕੂੜਾ-ਕਰਕਟ ਹੀ ਮਿਲੇਗਾ।
ਅਸੀਂ ਰੀਟ੍ਰੀਵਲ ਇੰਜਣ (retrieval engine) ਤੱਕ ਪਹੁੰਚਣ ਤੋਂ ਪਹਿਲਾਂ ਹਰ ਕੁਐਰੀ ਨੂੰ ਬਦਲ ਦਿੰਦੇ ਹਾਂ।
ਪਹਿਲਾਂ, query expansion। ਸਿਸਟਮ ਇੱਕ ਸਿੰਗਲ ਛੋਟੇ ਸਵਾਲ ਤੋਂ ਕਈ ਸਰਚ ਸ਼ਬਦ ਤਿਆਰ ਕਰਦਾ ਹੈ। ਇੱਕ ਯੂਜ਼ਰ ਪੁੱਛਦਾ ਹੈ, "ਮੈਂ timeout ਕਿਵੇਂ ਠੀਕ ਕਰਾਂ?" ਇੰਜਣ ਇਸ ਨੂੰ connection timeouts, read timeouts, gateway timeouts, ਅਤੇ retry logic ਨੂੰ ਕਵਰ ਕਰਨ ਲਈ ਵਧਾ ਦਿੰਦਾ ਹੈ। ਸਿਰਫ਼ ਇਸੇ ਤਰੀਕੇ ਨੇ ਸਾਡੇ recall ਨੂੰ 78% ਤੋਂ ਵਧਾ ਕੇ 96% ਕਰ ਦਿੱਤਾ।
ਦੂਜਾ, query decomposition। ਗੁੰਝਲਦਾਰ ਸਵਾਲਾਂ ਨੂੰ ਛੋਟੇ ਉਪ-ਸਵਾਲਾਂ (sub-questions) ਵਿੱਚ ਤੋੜ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ। ਇੱਕ ਕੁਐਰੀ ਜਿਵੇਂ ਕਿ "90 ਦਿਨਾਂ ਤੋਂ ਪੁਰਾਣੇ enterprise ਗਾਹਕਾਂ ਲਈ ਰਿਫੰਡ ਪਾਲਿਸੀ ਕੀ ਹੈ ਅਤੇ ਇਹ ਮਹੀਨਾਵਾਰ ਯੋਜਨਾਵਾਂ ਤੋਂ ਕਿਵੇਂ ਵੱਖਰੀ ਹੈ?" ਇੱਕ ਭਾਰੀ embedding lookup ਦੀ ਬਜਾਏ ਦੋ ਕੇਂਦਰਿਤ ਸਰਚਾਂ ਵਿੱਚ ਬਦਲ ਜਾਂਦੀ ਹੈ। ਹਰ ਉਪ-ਸਵਾਲ ਸੁਤੰਤਰ ਤੌਰ 'ਤੇ ਇੰਡੈਕਸ ਨੂੰ ਹਿੱਟ ਕਰਦਾ ਹੈ। ਨਤੀਜਿਆਂ ਨੂੰ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਜੋੜ ਦਿੱਤਾ ਜਾਂਦਾ ਹੈ। ਇਹ ਰੀਟ੍ਰੀਵਲ ਨੂੰ ਸੁੰਗੜਿਆ ਹੋਇਆ ਅਤੇ ਸਟੀਕ ਰੱਖਦਾ ਹੈ, ਜੋ ਉਸ ਫੈਲਾਅ (dilution) ਨੂੰ ਰੋਕਦਾ ਹੈ ਜੋ ਉਦੋਂ ਹੁੰਦਾ ਹੈ ਜਦੋਂ ਇੱਕ ਸਿੰਗਲ embedding ਇੱਕੋ ਸਮੇਂ ਦਰਜਨਾਂ ਸੰਕਲਪਾਂ ਨਾਲ ਮੇਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰਦੀ ਹੈ।
Bayesian Search ਨੂੰ ਆਪਣੀ ਪਾਈਪਲਾਈਨ ਟਿਊਨ ਕਰਨ ਦਿਓ
ਜੇਕਰ ਤੁਸੀਂ ਅਜੇ ਵੀ chunk size, overlap ratios, ਅਤੇ retrieval weights ਨੂੰ ਹੱਥਾਂ ਨਾਲ ਟਿਊਨ ਕਰ ਰਹੇ ਹੋ, ਤਾਂ ਤੁਸੀਂ ਪ੍ਰਦਰਸ਼ਨ (performance) ਦਾ ਨੁਕਸਾਨ ਕਰ ਰਹੇ ਹੋ। ਅਸੀਂ ਅੰਦਾਜ਼ੇ ਲਗਾਉਣਾ ਬੰਦ ਕਰ ਦਿੱਤਾ।
ਅਸੀਂ ਇੱਕ ਸਰਚ ਸਪੇਸ (search space) ਪਰਿਭਾਸ਼ਿਤ ਕੀਤੀ ਜਿੱਥੇ chunk size, overlap percentage, vector-versus-BM25 weights, ਅਤੇ reranker thresholds ਸਾਰੇ ਵੇਰੀਏਬਲ ਹਨ। ਫਿਰ ਅਸੀਂ Bayesian optimization ਲਾਗੂ ਕੀਤੀ। ਸੈਂਕੜੇ ਰੈਂਡਮ ਕੌਂਫਿਗਰੇਸ਼ਨਾਂ ਰਾਹੀਂ grid-searching ਕਰਨ ਦੀ ਬਜਾਏ, Bayesian search ਇਸ ਗੱਲ ਦਾ ਇੱਕ ਸੰਭਾਵਨਾਤਮਕ ਮਾਡਲ (probabilistic model) ਬਣਾਉਂਦਾ ਹੈ ਕਿ ਕੀ ਕੰਮ ਕਰਦਾ ਹੈ। ਇਹ ਇੱਕ ਕੌਂਫਿਗਰੇਸ਼ਨ ਦਾ ਸੁਝਾਅ ਦਿੰਦਾ ਹੈ, recall ਅਤੇ latency ਨੂੰ ਦੇਖਦਾ ਹੈ, ਆਪਣੇ ਵਿਸ਼ਵਾਸਾਂ ਨੂੰ ਅਪਡੇਟ ਕਰਦਾ ਹੈ, ਅਤੇ ਅਗਲਾ ਸੁਝਾਅ ਦਿੰਦਾ ਹੈ। ਸਮੇਂ ਦੇ ਨਾਲ, ਇਹ ਅਜਿਹੇ ਸੰਤੁਲਨ 'ਤੇ ਪਹੁੰਚ ਜਾਂਦਾ ਹੈ ਜਿਸ ਤੱਕ ਕੋਈ ਇਨਸਾਨ ਮੈਨੂਅਲੀ ਕਦੇ ਨਹੀਂ ਪਹੁੰਚ ਸਕਦਾ।
ਇਸਨੇ ਅਜਿਹੇ ਸੁਮੇਲ (combinations) ਲੱਭੇ ਜੋ ਅਸੀਂ ਕਦੇ ਨਹੀਂ ਅਜ਼ਮਾਏ ਹੁੰਦੇ। ਜ਼ਿਆਦਾ overlap ਵਾਲੇ ਛੋਟੇ ਚੰਕਸ। ਡੈਂਸ ਵੈਕਟਰ ਸਰਚ 'ਤੇ ਥੋੜ੍ਹਾ ਘੱਟ ਵੇਟ ਅਤੇ ਨਾਲ ਹੀ ਇੱਕ ਵਧੇਰੇ ਅਗਰੈਸਿਵ reranker threshold। ਇਹਨਾਂ ਗੈਰ-ਸਪਸ਼ਟ ਸਮਝੌਤਿਆਂ (tradeoffs) ਨੇ ਸਾਨੂੰ ਉੱਚਾ recall ਅਤੇ ਘੱਟ latency ਦੋਵੇਂ ਦਿੱਤੇ।
ਇਹ ਕੋਈ ਇੱਕ ਵਾਰ ਦਾ ਸੈੱਟਅੱਪ ਕੰਮ ਨਹੀਂ ਹੈ। ਅਸੀਂ ਹਰ ਮਹੀਨੇ hyperparameter optimization ਦੁਬਾਰਾ ਚਲਾਉਂਦੇ ਹਾਂ। ਤੁਹਾਡਾ corpus ਬਦਲਦਾ ਰਹਿੰਦਾ ਹੈ। ਯੂਜ਼ਰ ਦਾ ਵਿਵਹਾਰ ਬਦਲਦਾ ਹੈ। ਤੁਹਾਡੀ ਪਾਈਪਲਾਈਨ ਨੂੰ ਇੱਕੋ ਜਗ੍ਹਾ ਖੜ੍ਹੀ ਰਹਿਣ ਦੀ ਬਜਾਏ ਅਨੁਕੂਲ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।
ਫਲ (The Payoff)
ਉਸ ਮੁੜ-ਨਿਰਮਾਣ (rebuild) ਦੇ ਸਿੱਧੇ ਨਤੀਜੇ ਅਸਮਰਥਨਯੋਗ ਹਨ।
ਦਸਵੇਂ ਸਥਾਨ 'ਤੇ recall 78% ਤੋਂ ਵਧ ਕੇ 95% ਹੋ ਗਿਆ। ਜਦੋਂ ਸਹੀ ਉੱਤਰ ਸਾਡੇ knowledge base ਵਿੱਚ ਹੁੰਦਾ ਹੈ, ਤਾਂ ਅਸੀਂ ਵੀਹ ਵਿੱਚੋਂ ਉਨ੍ਹੀੱਸ ਵਾਰ ਇਸਨੂੰ ਸਾਹਮਣੇ ਲਿਆਉਂਦੇ ਹਾਂ। 95ਵੇਂ percentile 'ਤੇ latency 850 ਮਿਲੀਸਕਿੰਟ ਤੋਂ ਘਟ ਕੇ 320 ਮਿਲੀਸਕਿੰਟ ਹੋ ਗਈ। ਚੈਟ ਹੁਣ ਸੁਸਤ ਹੋਣ ਦੀ ਬਜਾਏ ਤੁਰੰਤ ਮਹਿਸੂਸ ਹੁੰਦੀ ਹੈ।
ਬਿਹਤਰ ਰੀਟ੍ਰੀਵਲ ਨੇ language model ਨੂੰ ਬਿਹਤਰ grounding ਦਿੱਤੀ। Hallucination ਦੀ ਦਰ 12% ਤੋਂ ਘਟ ਕੇ 3% ਰਹਿ ਗਈ। ਜਦੋਂ ਮਾਡਲ ਦੇ ਸਾਹਮਣੇ ਸਹੀ context ਹੁੰਦਾ ਹੈ, ਤਾਂ ਇਹ ਤੱਥਾਂ ਦੀ ਕਲਪਨਾ ਕਰਨਾ ਬੰਦ ਕਰ ਦਿੰਦਾ ਹੈ। ਪ੍ਰਤੀ ਕੁਐਰੀ ਲਾਗਤ 38% ਘਟ ਗਈ। ਤੇਜ਼ ਅਤੇ ਸਪਸ਼ਟ ਰੀਟ੍ਰੀਵਲ ਦਾ ਮਤਲਬ ਹੈ ਕਿ ਗੈਰ-ਸੰਬੰਧਿਤ context, retry loops, ਅਤੇ ਵਾਧੂ ਪਰ ਬੇਕਾਰ prompts 'ਤੇ ਘੱਟ tokens ਖ਼ਰਚ ਹੁੰਦੇ ਹਨ।
ਇਸਨੂੰ ਇਨਫਰਾਸਟ੍ਰਕਚਰ ਵਾਂਗ ਬਣਾਓ
ਜੇਕਰ ਤੁਸੀਂ prototype ਤੋਂ production ਵੱਲ ਵਧ ਰਹੇ ਹੋ, ਤਾਂ ਰੀਟ੍ਰੀਵਲ ਨੂੰ ਕੌਂਫਿਗਰੇਸ਼ਨ ਦੀ ਬਜਾਏ ਇਨਫਰਾਸਟ੍ਰਕਚਰ ਕੋਡ (infrastructure code) ਵਜੋਂ ਮੰਨੋ।
