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

Test #61

Merged
merged 4 commits into from
Mar 27, 2024
Merged

Test #61

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
5 changes: 3 additions & 2 deletions api/handlers/chat.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import { getValue } from "../utils";
import { CHAT_PARAMS } from "./../../presentation/src/constants";

export class ChatHandler
implements IRequestHandler<IChatRequestDTO, Result<IChatResponseDTO>>
implements
IRequestHandler<IChatRequestDTO, Result<Partial<IChatResponseDTO>>>
{
private readonly apiKey: string = getValue("API_KEY");
async handle({
question,
chatHistory,
}: IChatRequestDTO): Promise<Result<IChatResponseDTO>> {
}: IChatRequestDTO): Promise<Result<Partial<IChatResponseDTO>>> {
try {
const embeddingService: EmbeddingService = new EmbeddingService(
this.apiKey
Expand Down
20 changes: 11 additions & 9 deletions api/services/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ export class ChatService extends GenerativeAIService {
If it's possible to deduce how MyBid intends to solve the issues, provide that information. If not, respond with "I don't know".
Avoid External Sources: Do not search for information outside of the given context to formulate your response.
If you cannot find any relevent information in relating to the Question, just answer I am sorry I dont know.
Here is the context: ${conversation.context}
Here is the context: ${conversation.context}
Reminder: Please answer the following questions based solely on the context provided. Do not search for information outside of the given context.
Reminder: If you cannot find any relevent information in relating to the Question, just answer I am sorry I dont know.
`}`,
},
],
Expand All @@ -63,18 +65,18 @@ export class ChatService extends GenerativeAIService {
return model.startChat(this.initialConvo);
};

async run(): Promise<IChatResponseDTO> {
async run(): Promise<Partial<IChatResponseDTO>> {
const question = `${this.conversation.questions[0]}`;
this.displayChatTokenCount(question);
const chat: ChatSession = await this.initChat();
const result: GenerateContentResult = await chat.sendMessage(question);
const response: EnhancedGenerateContentResponse = result.response;
const answer = response.text();
const chatHistory = JSON.stringify(await chat.getHistory(), null, 2);
const result = await chat.sendMessageStream(question);
let text = "";
for await (const chunk of result.stream) {
const chunkText = chunk.text();
text += chunkText;
}
return {
question,
answer,
chatHistory,
answer: text,
};
}

Expand Down
107 changes: 68 additions & 39 deletions presentation/src/components/ChatForm.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import DOMPurify from "dompurify";
import { useState } from "react";
import {
Button,
Expand All @@ -9,22 +10,8 @@ import {
Stack,
} from "react-bootstrap";
import useAxiosPrivate from "../hooks/useAxiosPrivate";
import DOMPurify from "dompurify";
import { formatText } from "../utils";

// interface Message {
// text: string;
// metaData?: {
// documentId: number;
// pageNumber: number;
// };
// }

// interface Iresponse {
// history: { role: string; parts: { text: string }[] }[];
// question: string;
// answer: string;
// }
import { formatCodeBlocks, formatText } from "../utils";
import NavBar from "./NavBar";

interface IHistory {
role: string;
Expand All @@ -36,19 +23,21 @@ export function Thread() {
const [error, setError] = useState("");
const [question, setQuestion] = useState("");
const [chatHistory, setChatHistory] = useState<IHistory[]>([]);
const [loading, setLoading] = useState(false);

const formAction = async () => {
if (!question) {
setError("Please enter a question");
return;
}
try {
setLoading(true);
setQuestion("");
const response = await axiosPrivate.post("/chat", {
question,
chatHistory: JSON.stringify(chatHistory),
});
const data = response.data;
console.log(JSON.stringify(data.data.chatHistory));
setChatHistory((oldChat) => [
{
role: "user",
Expand All @@ -60,12 +49,13 @@ export function Thread() {
},
...oldChat,
]);
setQuestion("");
setLoading(false);
return data;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
console.error(error);
setError(error.message);
setLoading(false);
}
};

Expand All @@ -82,9 +72,12 @@ export function Thread() {

return (
<Container>
<Row>
<NavBar />
</Row>
<Row>
<Col></Col>
<Col xs={8}>
<Col xs={6}>
<div style={{ marginTop: "20px" }}>
<Form onSubmit={handleSubmit}>
<Stack direction="horizontal" gap={3}>
Expand All @@ -96,37 +89,73 @@ export function Thread() {
value={question}
onChange={(e) => setQuestion(e.target.value)}
/>
<Button variant="outline-success" onClick={formAction}>
<Button variant="dark" onClick={formAction} disabled={loading}>
Send
</Button>
<div className="vr" />
<Button variant="outline-danger" onClick={clearChat}>
<Button
variant="outline-danger"
onClick={clearChat}
disabled={loading}
>
Reset
</Button>
</Stack>
</Form>
</div>

<div>
<div style={{ color: "red" }}>
<p>{error}</p>
</div>
{chatHistory.map((chatItem, index) => (
<Card
style={{ marginBottom: "10px", marginTop: "10px" }}
key={index}
>
<Card.Header>{chatItem.role}</Card.Header>
{chatItem.parts.map((part, i) => (
<Card.Body key={i}>
<Card.Text
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(formatText(part.text)),
}}
></Card.Text>
</Card.Body>
))}
</Card>
))}
<div>
{loading ? (
<>
<div
className="loading-skeleton"
style={{
marginBottom: "10px",
marginTop: "10px",
height: "70px",
}}
></div>
<div
className="loading-skeleton"
style={{
marginBottom: "10px",
marginTop: "10px",
height: "140px",
}}
></div>
</>
) : (
""
)}
</div>
<div>
{chatHistory.map((chatItem, index) => (
<Card
style={{ marginBottom: "10px", marginTop: "10px" }}
key={index}
>
<Card.Header>
{chatItem.role && chatItem.role === "user"
? "Question"
: "Answer"}
</Card.Header>
{chatItem.parts.map((part, i) => (
<Card.Body key={i}>
<Card.Text
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(
formatCodeBlocks(formatText(part.text))
),
}}
></Card.Text>
</Card.Body>
))}
</Card>
))}
</div>
</Col>
<Col></Col>
</Row>
Expand Down
20 changes: 20 additions & 0 deletions presentation/src/components/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import Container from 'react-bootstrap/Container';
import Nav from 'react-bootstrap/Nav';
import Navbar from 'react-bootstrap/Navbar';

function NavBar() {
return (
<Navbar bg="light" data-bs-theme="light">
<Container style={{justifyContent: "right"}}>
<Nav >
<Nav.Link href="#home">Books</Nav.Link>
<Nav.Link href="#features">Documents</Nav.Link>
<Nav.Link href="#pricing">API Keys</Nav.Link>
<Nav.Link href="#pricing">Settings</Nav.Link>
</Nav>
</Container>
</Navbar>
);
}

export default NavBar;
25 changes: 25 additions & 0 deletions presentation/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.loading-skeleton {
background-color: #f0f0f0;
border-radius: 4px;
animation: loading 1s infinite ease-in-out;
}

@keyframes loading {
0% { opacity: 0.5; }
50% { opacity: 1; }
100% { opacity: 0.5; }
}

.straight-line {
position: fixed;
top: 0;
left: 50%;
width: 1px;
height: 100vh;
background-color: black;
z-index: 999;
}

body{
background-color: #f8f9fa;
}
13 changes: 13 additions & 0 deletions presentation/src/interfaces/generic.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export interface Message {
text: string;
metaData?: {
documentId: number;
pageNumber: number;
};
}

export interface Iresponse {
history: { role: string; parts: { text: string }[] }[];
question: string;
answer: string;
}
13 changes: 9 additions & 4 deletions presentation/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ export const formatText = (text: string) => {
if (i % 2 === 0) {
formattedText += `<p>${paragraph}</p>`;
} else {
const startIndex = paragraph.indexOf(" ");
const boldText = paragraph.substring(0, startIndex);
const restOfParagraph = paragraph.substring(startIndex).trim();
formattedText += `<p><b>${boldText}</b> ${restOfParagraph}</p>`;
const boldText = paragraph;
formattedText += `<p><b>${boldText}</b> `;
}
}
return formattedText.replace(/\*/g, "");
};

export const formatCodeBlocks = (text: string) => {
const regex = /```([^`]+)```/g;
return text.replace(regex, (_, context) => {
return `<pre><code>${context}</code></pre>`;
});
};
Loading