Context-aware Queries
In this example we make use of the LangChainJS integration, where we ask questions to our AI agent with respect to some context provided by Dria.
To try it yourself, see this example on GitHub (opens in a new tab)
The example is based on the RAG tutorial of LangChain (opens in a new tab)
Our prompt is constructed as follows:
const prompt = PromptTemplate.fromTemplate(`
Answer the question below based only on the following context.
If an answer is not found within the context, say "I don't know.".
Do not mention the context within your answer.
{context}
Question:
{question}
`);
Notice how we explicitly tell the AI to say "I don't know" if an answer is not available within the context. We create our DriaRetriever and pass it into the RunnableSequence of LangChain:
const retriever = new DriaRetriever(args);
const chain = RunnableSequence.from([
{
context: retriever.pipe(formatDocumentsAsString),
question: new RunnablePassthrough(),
},
prompt,
new ChatOpenAI({}),
new StringOutputParser(),
]);
const answer = await chain.invoke(query);
Example Queries
We will provide the context of 3 different knowledge separately:
- TypeScript Handbook v4.9 (opens in a new tab)
- The Rust Programming Language (opens in a new tab)
- Ethereum Whitepaper (opens in a new tab)
Let's denote them as TS, Rust and ETH for brevity. Now we ask some questions to each knowledge:
What does it mean to 'call'?
- TS: To 'call' typically refers to invoking a function or method in programming by using parentheses followed by any necessary arguments. It involves executing the code within the function or method and returning a result or performing a specific action.
- Rust: To 'call' means to execute a function or method in programming by using its name followed by a set of parentheses.
- ETH: In the context provided, "call" refers to running one step of a program and recording the change in storage.
What is this knowledge about?
- TS: This knowledge is about TypeScript, including conditional types, tuple types, object types, generic constraints, distributive conditional types, template literal types, and generic classes.
- Rust: Ownership rules and memory management in Rust programming.
- ETH: Smart contracts and Ethereum network.
What does the infer
keyword do?
- TS: The
infer
keyword is used to declaratively introduce a new generic type variable in conditional types, allowing us to infer types from types we compare against in the true branch of conditional types. - Rust: I don't know.
- ETH: I don't know.
Where is Merkle Tree used?
- TS: I don't know.
- Rust: I don't know.
- ETH: Merkle Trees are used in various applications including blockchain technology, data storage, decentralized file storage, financial derivatives contracts, and decentralized data feeds.
As we can see, the AI knows whether information is available or not within the context, and it can return relevant results for the given knowledge!