Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added text starter question generation #71

Merged
merged 61 commits into from
Dec 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
d1c7518
chat with docs
shreyaskarnik Nov 7, 2023
1e1f474
Merge branch 'main' of github.com:shreyaskarnik/DistiLlama into talk-…
shreyaskarnik Nov 7, 2023
a4c25a4
fix deps
shreyaskarnik Nov 7, 2023
85c1322
sort imports
shreyaskarnik Nov 7, 2023
303ae10
pnpm
shreyaskarnik Nov 7, 2023
1273800
better code organization
shreyaskarnik Nov 8, 2023
291db81
better code organization
shreyaskarnik Nov 8, 2023
bc1e7a3
chat function
shreyaskarnik Nov 9, 2023
c71f46f
simplification
shreyaskarnik Nov 9, 2023
a08fd20
merge
shreyaskarnik Nov 14, 2023
69de73b
Merge branch 'main' of github.com:shreyaskarnik/DistiLlama into talk-…
shreyaskarnik Nov 14, 2023
7c73b4f
more enhancements
shreyaskarnik Nov 14, 2023
0f35a62
more enhancements
shreyaskarnik Nov 15, 2023
a3acb8a
more docs
shreyaskarnik Nov 15, 2023
29bef00
more docs
shreyaskarnik Nov 15, 2023
a51bc2a
more docs
shreyaskarnik Nov 15, 2023
f5c14b5
stashing
shreyaskarnik Nov 16, 2023
6e88d70
stashing
shreyaskarnik Nov 16, 2023
3e6dd25
more UI enhancements
shreyaskarnik Nov 16, 2023
28bc130
more UI enhancements
shreyaskarnik Nov 16, 2023
33fa20c
more UI enhancements
shreyaskarnik Nov 17, 2023
7bd6fcc
more UI enhancements
shreyaskarnik Nov 17, 2023
ef4059a
more UI enhancements
shreyaskarnik Nov 17, 2023
2ba953b
streaming output when possible
shreyaskarnik Nov 17, 2023
5cd8515
Merge branch 'main' of github.com:shreyaskarnik/DistiLlama into talk-…
shreyaskarnik Nov 17, 2023
bf989fb
more changes
shreyaskarnik Nov 17, 2023
35d0da6
more changes
shreyaskarnik Nov 17, 2023
44c29fb
more changes
shreyaskarnik Nov 17, 2023
98a6c01
pass in metadata
shreyaskarnik Nov 18, 2023
49655d1
Merge branch 'main' into talk-to-doc
shreyaskarnik Nov 18, 2023
d11265b
Merge branch 'main' of github.com:shreyaskarnik/DistiLlama into talk-…
Nov 20, 2023
81ada68
stashing
shreyaskarnik Nov 21, 2023
c7f656f
Merge branch 'talk-to-doc' of github.com:shreyaskarnik/DistiLlama int…
shreyaskarnik Nov 21, 2023
afbb299
shelving
shreyaskarnik Nov 21, 2023
bdd0f4a
shelving
shreyaskarnik Nov 21, 2023
39f5171
save default settings and add refresh
shreyaskarnik Nov 22, 2023
d0034e2
Merge branch 'main' of github.com:shreyaskarnik/DistiLlama into talk-…
shreyaskarnik Nov 22, 2023
5d47724
Merge branch 'main' of github.com:shreyaskarnik/DistiLlama into talk-…
Dec 4, 2023
7d2e0e4
Bump @xenova/transformers from 2.8.0 to 2.9.0 (#52)
shreyaskarnik Dec 5, 2023
95f35f5
Bump @types/react from 18.2.37 to 18.2.42 (#55)
shreyaskarnik Dec 5, 2023
7566914
Bump @commitlint/config-conventional from 17.8.0 to 18.4.3 (#54)
shreyaskarnik Dec 5, 2023
9e5e7c4
Bump ts-loader from 9.5.0 to 9.5.1 (#53)
shreyaskarnik Dec 5, 2023
63820e9
Bump prettier from 3.0.3 to 3.1.0 (#51)
shreyaskarnik Dec 5, 2023
3b87c8e
Bump @mui/material from 5.14.18 to 5.14.20 (#60)
shreyaskarnik Dec 12, 2023
552fdf4
Bump lint-staged from 15.1.0 to 15.2.0 (#59)
shreyaskarnik Dec 12, 2023
0040e7d
Bump react-icons from 4.11.0 to 4.12.0 (#58)
shreyaskarnik Dec 12, 2023
8983d0a
Bump @types/react-dom from 18.2.16 to 18.2.17 (#57)
shreyaskarnik Dec 12, 2023
e4f1700
Bump pdfjs-dist from 4.0.189 to 4.0.269 (#56)
shreyaskarnik Dec 12, 2023
91e1a9f
Bump @types/node from 20.9.2 to 20.10.5 (#65)
shreyaskarnik Dec 19, 2023
b5f0c2b
Bump typescript from 5.3.2 to 5.3.3 (#64)
shreyaskarnik Dec 19, 2023
6db70d2
Bump langchain from 0.0.186 to 0.0.209 (#63)
shreyaskarnik Dec 19, 2023
31e15f1
Bump @types/react-dom from 18.2.17 to 18.2.18 (#62)
shreyaskarnik Dec 19, 2023
97c5122
Bump eslint-plugin-import from 2.29.0 to 2.29.1 (#61)
shreyaskarnik Dec 19, 2023
c99ff64
Bump eslint-plugin-prettier from 5.0.1 to 5.1.2 (#70)
shreyaskarnik Dec 26, 2023
448f9e9
Bump @emotion/react from 11.11.1 to 11.11.3 (#69)
shreyaskarnik Dec 26, 2023
26a9112
Bump @mui/material from 5.14.20 to 5.15.2 (#68)
shreyaskarnik Dec 26, 2023
6a9004d
Bump vite-plugin-wasm from 3.2.2 to 3.3.0 (#67)
shreyaskarnik Dec 26, 2023
26884cf
Bump fs-extra from 11.1.1 to 11.2.0 (#66)
shreyaskarnik Dec 26, 2023
528cf04
generate starter questions and use contextual compression
shreyaskarnik Dec 30, 2023
b85b0d4
enhancements
shreyaskarnik Dec 30, 2023
396c725
Merge branch 'main' into talk-to-doc
shreyaskarnik Dec 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 77 additions & 12 deletions src/pages/sidePanel/QandA.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { RunnablePassthrough, RunnableSequence } from 'langchain/schema/runnable
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import { formatDocumentsAsString } from 'langchain/util/document';
import { VoyVectorStore } from 'langchain/vectorstores/voy';
import { ContextualCompressionRetriever } from 'langchain/retrievers/contextual_compression';
import { EmbeddingsFilter } from 'langchain/retrievers/document_compressors/embeddings_filter';
import { type TextItem } from 'pdf-parse/lib/pdf.js/v1.10.100/build/pdf.js';
import * as PDFLib from 'pdfjs-dist';
import { Voy as VoyClient } from 'voy-search';
Expand All @@ -37,6 +39,7 @@ export type EmbedDocsOutput = {
pageURL?: string;
tabID?: number;
fileName?: string;
starterQuestions?: string[];
};
export async function embedDocs(selectedModel, localFile): Promise<EmbedDocsOutput> {
console.log('Embedding documents');
Expand Down Expand Up @@ -71,12 +74,53 @@ export async function embedDocs(selectedModel, localFile): Promise<EmbedDocsOutp
const splitDocs = await splitter.splitDocuments(documents);
await vectorstore.addDocuments(splitDocs);
console.log('Added documents to vectorstore');

return pageContent
? ({ vectorstore, pageURL: pageContent.pageURL, tabID: pageContent.tabID } as EmbedDocsOutput)
: ({ vectorstore, fileName: localFile.name } as EmbedDocsOutput);
}

export async function getDefaultStarterQuestions(selectedParams, vectorStore) {
try {
console.log('getDefaultStarterQuestions', selectedParams);
const llm = new Ollama({
baseUrl: OLLAMA_BASE_URL,
model: selectedParams.model.name,
temperature: selectedParams.temperature,
});
console.log('vectorStore', vectorStore);
const retriever = vectorStore.asRetriever();

const generateStarterQuestionsPrompt = `
Given the following context and metadata, generate 1-2 questions that can be asked about the context.
Return the questions as a list of strings. No additional output is needed. No numbers needed. Format output as JSON array of strings.

{context}

Metadata:
{metadata}
`;

const starterQPrompt = PromptTemplate.fromTemplate(generateStarterQuestionsPrompt);
const chain = RunnableSequence.from([
{
context: retriever.pipe(formatDocumentsAsString),
metadata: retriever.pipe(documents => getMetadataString(documents)),
},
starterQPrompt,
llm,
new StringOutputParser(),
]);

const resultString = await chain.invoke('');
const resultArray = JSON.parse(resultString); // Parse the JSON string to an array
return resultArray;
} catch (error) {
console.error('Error in getDefaultStarterQuestions:', error);
// Handle the error or return an empty array/fallback value
return [];
}
}

export async function* talkToDocument(selectedParams, vectorStore, input: ConversationalRetrievalQAChainInput) {
console.log('talkToDocument', selectedParams);
const llm = new Ollama({
Expand All @@ -87,7 +131,19 @@ export async function* talkToDocument(selectedParams, vectorStore, input: Conver
console.log('question', input.question);
console.log('chat_history', input.chat_history);
console.log('vectorStore', vectorStore);
const retriever = vectorStore.asRetriever();
let retriever = vectorStore.asRetriever();
if (input.chat_history.length !== 0) {
const baseCompressor = new EmbeddingsFilter({
embeddings: new HuggingFaceTransformersEmbeddings({
modelName: 'Xenova/jina-embeddings-v2-small-en',
}),
similarityThreshold: 0.6,
});
retriever = new ContextualCompressionRetriever({
baseCompressor,
baseRetriever: vectorStore.asRetriever(),
});
}
const condenseQuestionTemplate = `Given the following conversation and a follow up question, rephrase the follow up question to be a standalone question.

Chat History:
Expand Down Expand Up @@ -125,7 +181,7 @@ export async function* talkToDocument(selectedParams, vectorStore, input: Conver
{
context: retriever.pipe(formatDocumentsAsString),
question: new RunnablePassthrough(),
metadata: retriever.pipe(documents => getMetadataString(documents[0].metadata)),
metadata: retriever.pipe(documents => getMetadataString(documents)),
},
prompt,
llm,
Expand All @@ -139,18 +195,27 @@ export async function* talkToDocument(selectedParams, vectorStore, input: Conver
}
}

function getMetadataString(metadata) {
const result = [];
function getMetadataString(documents: Document[]) {
try {
const metadata = documents[0].metadata;
if (!metadata) {
return '';
}
const result = [];

for (const key in metadata) {
// Check if the property is not an object and not an array
if (Object.prototype.hasOwnProperty.call(metadata, key) && typeof metadata[key] !== 'object') {
result.push(`${key}: ${metadata[key]}`);
for (const key in metadata) {
// Check if the property is not an object and not an array
if (Object.prototype.hasOwnProperty.call(metadata, key) && typeof metadata[key] !== 'object') {
result.push(`${key}: ${metadata[key]}`);
}
}
}
console.log('result', result);
console.log('result', result);

return result.join(' ');
return result.join(' ');
} catch (e) {
console.log('error', e);
return '';
}
}

export const formatChatHistory = (chatHistory: { question: string; answer: string }[]) => {
Expand Down
39 changes: 33 additions & 6 deletions src/pages/sidePanel/QandABubble.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import LinearProgress from '@mui/material/LinearProgress';
import { talkToDocument, chatWithLLM } from '@root/src/pages/sidePanel/QandA';
import { talkToDocument, chatWithLLM, getDefaultStarterQuestions } from '@root/src/pages/sidePanel/QandA';
import { useEffect, useRef, useState } from 'react';
import { BsFillArrowRightSquareFill } from 'react-icons/bs';
import PageMetadata from '@root/src/pages/sidePanel/PageMetadata';
Expand Down Expand Up @@ -45,15 +45,24 @@ export function QandABubble({ taskType, selectedParams, vectorstore }) {
e.target.style.height = 'auto'; // Reset the height
e.target.style.height = `${e.target.scrollHeight}px`; // Set the height equal to the scroll height
};
const [starterQuestions, setStarterQuestions] = useState([]);
const handleKeyPress = e => {
if (e.key === 'Enter' && !e.shiftKey) {
// Check if Enter was pressed without the shift key
e.preventDefault(); // Prevent the default action to avoid inserting a new line
handleQandAAction(e); // Call your existing form submission handler
}
};
const fetchStarterQuestions = async () => {
console.log('getting default starter questions');
if (taskType === 'docs' || taskType === 'qanda') {
const defaultStarterQuestions = await getDefaultStarterQuestions(selectedParams, vectorstore.vectorstore);
setStarterQuestions(defaultStarterQuestions);
}
};

useEffect(() => {
fetchStarterQuestions();
setAnswer('');
setQuestion('');
setAnswering(false);
Expand Down Expand Up @@ -136,6 +145,28 @@ export function QandABubble({ taskType, selectedParams, vectorstore }) {
)}
</div>
<div className="form-container" ref={formContainerRef}>
{chat_history.length === 0 && (
<div className="starter-questions">
<ul>
{starterQuestions.map((question, index) => (
<li
key={index}
role="button"
tabIndex={0}
onClick={() => {
setQuestion(question);
}}
onKeyDown={e => {
if (e.key === 'Enter' || e.key === ' ') {
setQuestion(question);
}
}}>
{question}
</li>
))}
</ul>
</div>
)}
<form onSubmit={handleQandAAction} className="qna-form">
<div className="input-button-wrapper">
<textarea
Expand All @@ -147,11 +178,7 @@ export function QandABubble({ taskType, selectedParams, vectorstore }) {
className="question-input"
disabled={answering}
/>
<button
type="submit"
className={`real-button ${question ? 'has-text' : ''}`}
disabled={answering} // this will disable the button when answering is true
>
<button type="submit" className={`real-button ${question ? 'has-text' : ''}`} disabled={answering}>
<BsFillArrowRightSquareFill size="2rem" className={answering ? 'spin' : ''} />
</button>
</div>
Expand Down
84 changes: 84 additions & 0 deletions src/pages/sidePanel/SidePanel.css
Original file line number Diff line number Diff line change
Expand Up @@ -663,3 +663,87 @@
background-color: #0056b3;
/* Darker green */
}

.starter-questions {
margin: 20px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
justify-content: center;
}

.starter-questions h3 {
color: #61dafb;
margin-bottom: 20px;
}

.starter-questions li {
background: rgba(255, 255, 255, 0.05);
color: white;
padding: 15px;
border-radius: 10px;
margin-bottom: 10px;
border: 1px solid rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
text-align: center;
cursor: pointer;
transition: background-color 0.2s, box-shadow 0.2s;
backdrop-filter: blur(10px);
}

.starter-questions li:not(:last-child) {
margin-bottom: 10px;
}

.starter-questions li:hover {
background: rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
}

/* If you have a title or description under the list, you might add something like this: */
.description-text {
color: white;
font-size: 1rem;
margin: 20px;
text-align: center;
}

/* Style for the input field and submit button */
.input-container {
max-width: 600px;
margin: 20px auto;
background: #333;
border-radius: 10px;
overflow: hidden;
/* To ensure the border-radius applies to children elements as well */
}

.input-container textarea {
width: calc(100% - 40px);
/* Adjust the width based on your padding */
padding: 20px;
border: none;
background: transparent;
color: white;
resize: none;
/* Disables resize handle */
}

.input-container button {
padding: 10px 15px;
border: none;
background: #61dafb;
/* Light blue to match the theme */
color: #282c34;
/* Dark text for contrast */
cursor: pointer;
}

.input-container button:hover {
background: #409ed2;
/* Slightly darker on hover */
}

/* You may need to adjust the max-width and padding based on your layout */