Skip to content

Commit

Permalink
code clean up so that it's simpler to extend the chat with advance sc…
Browse files Browse the repository at this point in the history
…enarios

- refactor chat folder
- move services and models into one folder
  • Loading branch information
thivy committed Aug 3, 2023
1 parent 861080e commit 063cbe0
Show file tree
Hide file tree
Showing 21 changed files with 228 additions and 202 deletions.
6 changes: 3 additions & 3 deletions src/app/chat/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FindAllChats } from "@/features/chat/chat-service";
import { FindChatThreadByID } from "@/features/chat/chat-thread-service";
import { ChatUI } from "@/features/chat/chat-ui";
import { FindAllChats } from "@/features/chat/chat-services/chat-service";
import { FindChatThreadByID } from "@/features/chat/chat-services/chat-thread-service";
import { ChatUI } from "@/features/chat/chat-ui/chat-ui";
import { notFound } from "next/navigation";

export default async function Home({ params }: { params: { id: string } }) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/chat/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Card } from "@/components/ui/card";
import { NewChat } from "@/features/chat/chat-menu/new-chat";
import { FindAllChatThreadForCurrentUser } from "@/features/chat/chat-thread-service";
import { FindAllChatThreadForCurrentUser } from "@/features/chat/chat-services/chat-thread-service";
import { redirect } from "next/navigation";

export default async function Home() {
Expand Down
4 changes: 2 additions & 2 deletions src/components/chat/chat-row.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { chatRole } from "@/features/chat/chat-service";
import { ChatRole } from "@/features/chat/chat-services/models";
import { cn } from "@/lib/utils";
import { FC } from "react";
import remarkGfm from "remark-gfm";
Expand All @@ -11,7 +11,7 @@ interface ChatRowProps {
name: string;
profilePicture: string;
message: string;
type: chatRole;
type: ChatRole;
}

const ChatRow: FC<ChatRowProps> = (props) => {
Expand Down
38 changes: 0 additions & 38 deletions src/features/chat/chat-api-utils.ts

This file was deleted.

67 changes: 8 additions & 59 deletions src/features/chat/chat-api.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,11 @@
import { LangChainStream, StreamingTextResponse } from "ai";
import { ConversationChain } from "langchain/chains";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { BufferWindowMemory } from "langchain/memory";
import {
ChatPromptTemplate,
HumanMessagePromptTemplate,
MessagesPlaceholder,
SystemMessagePromptTemplate,
} from "langchain/prompts";
import { userHashedId } from "../auth/helpers";
import { CosmosDBChatMessageHistory } from "../langchain/memory/cosmosdb/cosmosdb";
import { PromptGPTProps, initAndGuardChatSession } from "./chat-api-utils";
import { ChatData } from "./chat-data/chat-data-api";
import { PromptGPTProps } from "./chat-services/models";
import { ChatSimple } from "./chat-simple/chat-simple-api";

export const PromptGPT = async (props: PromptGPTProps) => {
const { lastHumanMessage, id } = await initAndGuardChatSession(props);

const { stream, handlers } = LangChainStream();

const userId = await userHashedId();

const chat = new ChatOpenAI({
temperature: 0,
streaming: true,
});

const memory = new BufferWindowMemory({
k: 100,
returnMessages: true,
memoryKey: "history",
chatHistory: new CosmosDBChatMessageHistory({
sessionId: id,
userId: userId,
config: {
db: process.env.AZURE_COSMOSDB_DB_NAME,
container: process.env.AZURE_COSMOSDB_CONTAINER_NAME,
endpoint: process.env.AZURE_COSMOSDB_URI,
key: process.env.AZURE_COSMOSDB_KEY,
partitionKey: "id",
},
}),
});

const chatPrompt = ChatPromptTemplate.fromPromptMessages([
SystemMessagePromptTemplate.fromTemplate(
`-You are Azure ChatGPT who is a helpful AI Assistant.
- You will provide clear and concise queries, and you will respond with polite and professional answers.
- You will answer questions truthfully and accurately.`
),
new MessagesPlaceholder("history"),
HumanMessagePromptTemplate.fromTemplate("{input}"),
]);
const chain = new ConversationChain({
llm: chat,
memory,
prompt: chatPrompt,
});

chain.call({ input: lastHumanMessage.content }, [handlers]);

return new StreamingTextResponse(stream);
if (props.chatType === "simple") {
return await ChatSimple(props);
} else if (props.chatType === "data") {
return await ChatData(props);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ import {
import {
AzureCogDocument,
AzureCogSearch,
} from "../langchain/vector-stores/azure-cog-search/azure-cog-vector-store";
import { PromptGPTProps, initAndGuardChatSession } from "./chat-api-utils";
import { ChatMessageModel, inertPromptAndResponse } from "./chat-service";
} from "../../langchain/vector-stores/azure-cog-search/azure-cog-vector-store";
import { insertPromptAndResponse } from "../chat-services/chat-service";
import { initAndGuardChatSession } from "../chat-services/chat-thread-service";
import { ChatMessageModel, PromptGPTProps } from "../chat-services/models";

export interface FaqDocumentIndex extends AzureCogDocument {
id: string;
Expand All @@ -23,7 +24,7 @@ export interface FaqDocumentIndex extends AzureCogDocument {
metadata: any;
}

export const PromptDataGPT = async (props: PromptGPTProps) => {
export const ChatData = async (props: PromptGPTProps) => {
const { lastHumanMessage, id, chats } = await initAndGuardChatSession(props);

const chatModel = new ChatOpenAI({
Expand All @@ -40,7 +41,7 @@ export const PromptDataGPT = async (props: PromptGPTProps) => {
});
const { stream, handlers } = LangChainStream({
onCompletion: async (completion: string) => {
await inertPromptAndResponse(id, lastHumanMessage.content, completion);
await insertPromptAndResponse(id, lastHumanMessage.content, completion);
},
});

Expand Down
2 changes: 1 addition & 1 deletion src/features/chat/chat-menu/chat-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Menu, MenuContent, MenuFooter, MenuHeader } from "@/components/menu";
import { FindAllChatThreadForCurrentUser } from "@/features/chat/chat-thread-service";
import { FindAllChatThreadForCurrentUser } from "@/features/chat/chat-services/chat-thread-service";
import { ThemeToggle } from "@/features/theme/theme-toggle";
import { MenuItems } from "./menu-items";
import { NewChat } from "./new-chat";
Expand Down
6 changes: 2 additions & 4 deletions src/features/chat/chat-menu/menu-items.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
"use client";
import { MenuItem } from "@/components/menu";
import { Button } from "@/components/ui/button";
import {
ChatThreadModel,
SoftDeleteChatThreadByID,
} from "@/features/chat/chat-thread-service";
import { SoftDeleteChatThreadByID } from "@/features/chat/chat-services/chat-thread-service";
import { MessageCircle, Trash } from "lucide-react";
import { useParams, useRouter } from "next/navigation";
import { FC } from "react";
import { ChatThreadModel } from "../chat-services/models";

interface Prop {
menuItems: Array<ChatThreadModel>;
Expand Down
2 changes: 1 addition & 1 deletion src/features/chat/chat-menu/new-chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Button } from "@/components/ui/button";
import { PlusCircle } from "lucide-react";
import { useRouter } from "next/navigation";
import { CreateChatThread } from "../chat-thread-service";
import { CreateChatThread } from "../chat-services/chat-thread-service";

export const NewChat = () => {
const router = useRouter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import "server-only";

import { SqlQuerySpec } from "@azure/cosmos";
import { nanoid } from "nanoid";
import { memoryContainer } from "../common/cosmos";
import { MESSAGE_ATTRIBUTE } from "./models";
import { memoryContainer } from "../../common/cosmos";
import { ChatMessageModel, MESSAGE_ATTRIBUTE } from "./models";

export const FindAllChats = async (chatThreadID: string) => {
const container = await memoryContainer();
Expand Down Expand Up @@ -48,7 +48,7 @@ export const UpsertChat = async (chatModel: ChatMessageModel) => {
await container.items.upsert(modelToSave);
};

export const inertPromptAndResponse = async (
export const insertPromptAndResponse = async (
threadID: string,
userQuestion: string,
assistantResponse: string
Expand Down Expand Up @@ -79,16 +79,3 @@ export const newChatModel = (): ChatMessageModel => {
isDeleted: false,
};
};

export interface ChatMessageModel {
id: string;
createdAt: Date;
isDeleted: boolean;
threadId: string;
userId: string;
content: string;
role: chatRole;
type: "CHAT_MESSAGE";
}

export type chatRole = "system" | "user" | "assistant" | "function";
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@
import "server-only";

import { userHashedId, userSession } from "@/features/auth/helpers";
import { ChatMessageModel, FindAllChats } from "@/features/chat/chat-service";
import { FindAllChats } from "@/features/chat/chat-services/chat-service";
import { SqlQuerySpec } from "@azure/cosmos";
import { nanoid } from "nanoid";
import { memoryContainer } from "../common/cosmos";
import { CHAT_THREAD_ATTRIBUTE } from "./models";
import { memoryContainer } from "../../common/cosmos";
import {
CHAT_THREAD_ATTRIBUTE,
ChatMessageModel,
ChatThreadModel,
PromptGPTProps,
} from "./models";

export const FindAllChatThreadForCurrentUser = async () => {
const container = await memoryContainer();
Expand Down Expand Up @@ -135,6 +140,7 @@ export const CreateChatThread = async () => {
id: nanoid(),
createdAt: new Date(),
isDeleted: false,
chatType: "simple",
type: CHAT_THREAD_ATTRIBUTE,
};

Expand All @@ -143,13 +149,25 @@ export const CreateChatThread = async () => {
return response.resource;
};

export interface ChatThreadModel {
id: string;
name: string;
model: string;
createdAt: Date;
userId: string;
useName: string;
isDeleted: boolean;
type: "CHAT_THREAD";
}
export const initAndGuardChatSession = async (props: PromptGPTProps) => {
const { messages, id, model } = props;

//last message
const lastHumanMessage = messages[messages.length - 1];

const chatThread = await EnsureChatThreadIsForCurrentUser(id);
const chats = await FindAllChats(id);

await updateChatThreadTitle(
chatThread,
chats,
model,
lastHumanMessage.content
);

return {
id,
lastHumanMessage,
chats,
};
};
41 changes: 41 additions & 0 deletions src/features/chat/chat-services/models.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Message } from "ai";

export const CHAT_THREAD_ATTRIBUTE = "CHAT_THREAD";
export const MESSAGE_ATTRIBUTE = "CHAT_MESSAGE";

export interface ChatMessageModel {
id: string;
createdAt: Date;
isDeleted: boolean;
threadId: string;
userId: string;
content: string;
role: ChatRole;
type: "CHAT_MESSAGE";
}

export type ChatRole = "system" | "user" | "assistant" | "function";

export type ChatType = "simple" | "data" | "mssql";

export interface ChatThreadModel {
id: string;
name: string;
model: string;
createdAt: Date;
userId: string;
useName: string;
isDeleted: boolean;
chatType: ChatType;
type: "CHAT_THREAD";
}

export interface PromptGPTBody {
id: string; // thread id
model: string; // model name
chatType: ChatType;
}

export interface PromptGPTProps extends PromptGPTBody {
messages: Message[];
}
15 changes: 15 additions & 0 deletions src/features/chat/chat-services/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Message } from "ai";
import { ChatMessageModel } from "./models";

export const transformCosmosToAIModel = (
chats: Array<ChatMessageModel>
): Array<Message> => {
return chats.map((chat) => {
return {
role: chat.role,
content: chat.content,
id: chat.id,
createdAt: chat.createdAt,
};
});
};
Loading

0 comments on commit 063cbe0

Please sign in to comment.