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

nextjs chat fix #972

Merged
merged 5 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
32 changes: 24 additions & 8 deletions backend/chat/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,36 @@ def __init__(

def create_agent(self):
"""Create React Agent Graph"""
#If not vector store, split and talk to the report
llm_provider_name = getattr(self.config, "llm_provider")
fast_llm_model = getattr(self.config, "fast_llm_model")
temperature = getattr(self.config, "temperature")
fast_token_limit = getattr(self.config, "fast_token_limit")
cfg = Config()

provider = get_llm(llm_provider_name, model=fast_llm_model, temperature=temperature, max_tokens=fast_token_limit, **self.config.llm_kwargs).llm
# Retrieve LLM using get_llm with settings from config
provider = get_llm(
llm_provider=cfg.smart_llm_provider,
model=cfg.smart_llm_model,
temperature=0.35,
max_tokens=cfg.smart_token_limit,
**self.config.llm_kwargs
).llm

# If vector_store is not initialized, process documents and add to vector_store
if not self.vector_store:
documents = self._process_document(self.report)
self.chat_config = {"configurable": {"thread_id": str(uuid.uuid4())}}
self.embedding = Memory(getattr(self.config, 'embedding_provider', None), self.headers).get_embeddings()
self.embedding = Memory(
cfg.embedding_provider,
cfg.embedding_model,
**cfg.embedding_kwargs
).get_embeddings()
self.vector_store = InMemoryVectorStore(self.embedding)
self.vector_store.add_texts(documents)
graph = create_react_agent(provider, tools=[self.vector_store_tool(self.vector_store)], checkpointer=MemorySaver())

# Create the React Agent Graph with the configured provider
graph = create_react_agent(
provider,
tools=[self.vector_store_tool(self.vector_store)],
checkpointer=MemorySaver()
)

return graph

def vector_store_tool(self, vector_store) -> Tool:
Expand Down
6 changes: 6 additions & 0 deletions frontend/nextjs/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ html {
scroll-behavior: smooth;
}

textarea {
max-height: 300px; /* Set an appropriate max height */
overflow-y: auto; /* Enable internal scrolling */
/* transition: height 0.2s ease-in-out; */
}

.log-message {
word-wrap: break-word; /* For handling long URLs or text */
overflow-wrap: break-word; /* For handling overflow in modern browsers */
Expand Down
95 changes: 77 additions & 18 deletions frontend/nextjs/components/InputArea.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Image from "next/image";
import { FC } from "react";
import { FC, useRef } from "react";
import TypeAnimation from "./TypeAnimation";

type TInputAreaProps = {
Expand All @@ -11,38 +11,92 @@ type TInputAreaProps = {
reset?: () => void;
};

// Debounce function to limit the rate at which a function can fire
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}

const InputArea: FC<TInputAreaProps> = ({
promptValue,
setPromptValue,
handleSubmit: handleSubmit,
handleSecondary: handleSecondary,
handleSubmit,
handleSecondary,
disabled,
reset,
}) => {
const placeholder = handleSecondary ? "Follow up questions..." : "What would you like to research next?"
const placeholder = handleSecondary
? "Follow up questions..."
: "What would you like to research next?";

const textareaRef = useRef<HTMLTextAreaElement>(null);

const resetHeight = () => {
if (textareaRef.current) {
textareaRef.current.style.height = '3em'; // Reset to base height
}
};

const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter') {
if (e.shiftKey) {
return; // Allow new line on Shift+Enter
} else {
e.preventDefault();
if (!disabled) {
if (reset) reset();
handleSubmit(promptValue);
setPromptValue(''); // Clear prompt value
resetHeight(); // Reset height after submit
}
}
}
};

// Debounced version of the height adjustment function
const adjustHeight = debounce((target) => {
target.style.height = 'auto'; // Reset height to auto to allow shrinking
target.style.height = `${target.scrollHeight}px`; // Adjust height
}, 100); // Adjust the delay as needed

const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
const target = e.target;
adjustHeight(target); // Use debounced function
setPromptValue(target.value);
};

return (
<form
className="mx-auto flex h-[66px] w-full items-center justify-between rounded-lg border bg-white px-3 shadow-[2px_2px_38px_0px_rgba(0,0,0,0.25),0px_-2px_4px_0px_rgba(0,0,0,0.25)_inset,1px_2px_4px_0px_rgba(0,0,0,0.25)_inset]"
className="mx-auto flex pt-2 pb-2 w-full items-center justify-between rounded-lg border bg-white px-3 shadow-[2px_2px_38px_0px_rgba(0,0,0,0.25),0px_-2px_4px_0px_rgba(0,0,0,0.25)_inset,1px_2px_4px_0px_rgba(0,0,0,0.25)_inset]"
onSubmit={(e) => {
e.preventDefault();
if (reset) reset();
handleSubmit(promptValue);
setPromptValue(''); // Clear prompt value
resetHeight();
}}
>
{
handleSecondary &&
{handleSecondary && (
<div
role="button"
role="button"
aria-disabled={disabled}
className="relative flex h-[50px] w-[50px] shrink-0 items-center justify-center rounded-[3px] bg-[linear-gradient(154deg,#1B1B16_23.37%,#565646_91.91%)] disabled:pointer-events-none disabled:opacity-75"
onClick={(e) =>{
if (!disabled){
onClick={(e) => {
if (!disabled) {
e.preventDefault();
if (reset) reset();
handleSecondary(promptValue);
}
setPromptValue(''); // Clear prompt value
resetHeight();
}
}
}}
>
{disabled && (
<div className="absolute inset-0 flex items-center justify-center">
Expand All @@ -59,15 +113,20 @@ const InputArea: FC<TInputAreaProps> = ({
className={disabled ? "invisible" : ""}
/>
</div>
}
<input
type="text"
)}

<textarea
placeholder={placeholder}
className="focus-visible::outline-0 my-1 w-full pl-5 font-light not-italic leading-[normal] text-[#1B1B16]/30 text-black outline-none focus-visible:ring-0 focus-visible:ring-offset-0 sm:text-xl"
ref={textareaRef}
className="focus-visible::outline-0 my-1 w-full pl-5 font-light not-italic leading-[normal]
text-[#1B1B16]/30 text-black outline-none focus-visible:ring-0 focus-visible:ring-offset-0
sm:text-xl min-h-[3em] resize-none"
disabled={disabled}
value={promptValue}
required
onChange={(e) => setPromptValue(e.target.value)}
rows={2}
onKeyDown={handleKeyDown}
onChange={handleTextareaChange}
/>
<button
disabled={disabled}
Expand All @@ -93,4 +152,4 @@ const InputArea: FC<TInputAreaProps> = ({
);
};

export default InputArea;
export default InputArea;
4 changes: 2 additions & 2 deletions frontend/nextjs/components/Question.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ const Question: React.FC<QuestionProps> = ({ question }) => {
/>
<p className="font-bold uppercase leading-[152%] text-white">
Question:
</p>
</p><br/>
</div>
<div className="grow text-white break-words max-w-full sm:truncate">&quot;{question}&quot;</div>
<div className="grow text-white break-words max-w-full log-message">&quot;{question}&quot;</div>
</div>
);
};
Expand Down