Skip to content
Open
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
1 change: 0 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ jobs:
TURSO_DB_URL: ${{secrets.TURSO_DB_URL}}
TURSO_DB_AUTH_TOKEN: ${{secrets.TURSO_DB_AUTH_TOKEN}}
OPEN_AI_API_KEY: ${{secrets.OPEN_AI_API_KEY}}
LANGSMITH_API_KEY: ${{secrets.LANGSMITH_API_KEY}}
SENTRY_AUTH_TOKEN: ${{secrets.SENTRY_AUTH_TOKEN}}
SENTRY_ORG: ${{secrets.SENTRY_ORG}}
SENTRY_PROJECT: ${{secrets.SENTRY_PROJECT}}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"drizzle-zod": "^0.4.2",
"eslint": "8.37.0",
"eslint-config-next": "13.2.4",
"fornac": "^1.1.8",
"iconoir-react": "^6.8.0",
"langchain": "^0.0.121",
"langsmith": "^0.0.17",
Expand Down
15 changes: 1 addition & 14 deletions src/app/api/chatmodel/[chatid]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import { chats } from "@/lib/db/schema";
import { ChatEntry, ChatLog } from "@/lib/types";
import { auth } from "@clerk/nextjs";
import { generateTitle } from "../../generateTitle/[chatid]/[orgid]/route";
import { Client } from "langsmith";
import { LangChainTracer } from "langchain/callbacks";
export const revalidate = 0; // disable cache

export const jsonToLangchain = (
Expand Down Expand Up @@ -116,17 +114,6 @@ export async function POST(
// }
},
});

const client = new Client({
apiUrl: "https://api.smith.langchain.com",
apiKey: env.LANGSMITH_API_KEY,
});

const tracer = new LangChainTracer({
projectName: "echoes",
client,
});

// change model type based on isFast variable and OPEN_AI_API_KEY as well
const chatmodel: ChatOpenAI = new ChatOpenAI({
modelName: isFast ? "gpt-4" : "gpt-3.5-turbo-16k",
Expand All @@ -135,6 +122,6 @@ export async function POST(
openAIApiKey: env.OPEN_AI_API_KEY,
streaming: true,
});
chatmodel.call(msgs, {}, [handlers, tracer]);
chatmodel.call(msgs, {}, [handlers]);
return new StreamingTextResponse(stream);
}
2 changes: 0 additions & 2 deletions src/app/env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export const env = createEnv({
server: {
// OpenAI
OPEN_AI_API_KEY: z.string().min(10),
LANGSMITH_API_KEY: z.string().min(10),
// Clerk
CLERK_SECRET_KEY: z.string().min(10),
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: z.string().min(10),
Expand Down Expand Up @@ -40,7 +39,6 @@ export const env = createEnv({
REDIS_URL: process.env.REDIS_URL,
// OpenAI
OPEN_AI_API_KEY: process.env.OPEN_AI_API_KEY,
LANGSMITH_API_KEY: process.env.LANGSMITH_API_KEY,
// turso db
TURSO_DB_URL: process.env.TURSO_DB_URL,
TURSO_DB_AUTH_TOKEN: process.env.TURSO_DB_AUTH_TOKEN,
Expand Down
48 changes: 46 additions & 2 deletions src/components/chat.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"use client";
import { useState, useEffect } from "react";
import { useState, useEffect, useRef } from "react";
import ChatMessage from "@/components/chatmessage";
import { ChatEntry, ChatLog } from "@/lib/types";
import InputBar from "@/components/inputBar";
import { Message, useChat } from "ai/react";
import { useMutation } from "../../liveblocks.config";

import React from "react";
interface ChatProps {
orgId: string;
uid: string;
Expand All @@ -19,8 +19,36 @@ export default function Chat(props: ChatProps) {
const updateRoomData = useMutation(({ storage }, data) => {
storage.set("chat", data);
}, []);
// const tempAdd = useMutation(({ storage }) => {
// // storage.set("chat", data);
// const list = storage.get("chat");
// const data = {
// "role": "assistant",
// "content": null,
// "function_call": {
// "name": "get_current_weather",
// "arguments": "{ \"location\": \"Boston, MA\"}"
// }
// }
// }, []);

const divRef = useRef<HTMLDivElement>(null);

// useEffect(() => {
// const element = divRef.current as Element;
// const Forna = new fornac.FornaContainer(element, {'initialSize':[800,600]});
// let options = {
// structure: "..((..((...[)).(((..].))).))..",
// sequence: "AACGCUUCAUAUAAUCCUAAUGACCUAUAA",
// };
// Forna.addRNA(options.structure, options);
// // element.appendChild(el)
// }, [divRef.current])
// console.log("typeof fornac", fornac)

// let firstUrl = `/api/chatmodel/${props.chatId}`
const [isFast, setIsFast] = useState<boolean>(true);
// const [apiUrl, setApiUrl] = useState(firstUrl)
const {
messages,
input,
Expand All @@ -30,7 +58,9 @@ export default function Chat(props: ChatProps) {
append,
setMessages,
} = useChat({
// api: isFast ? `/api/chatmodel/${props.chatId}` : `https://technoculture-echoes--bioinformatics-ai-web.modal.run?prompt=fold ATGCGCGC`,
api: `/api/chatmodel/${props.chatId}`,
// api: apiUrl,
// initialMessages: props.chat.log as Message[],
initialMessages:
props.liveChat !== null
Expand All @@ -43,6 +73,17 @@ export default function Chat(props: ChatProps) {
}, // some conflicts in role
});

// useEffect(() => {
// if(apiUrl.startsWith('/api')){
// // setApiUrl(`https://technoculture-echoes--bioinformatics-ai-web.modal.run?prompt=fold ${messages[messages.length -1].content}`)
// setApiUrl(`https://technoculture-echoes--bioinformatics-ai-web.modal.run?prompt=fold ATGCGCGC`)
// console.log("isFast changing", apiUrl)
// } else {
// setApiUrl(`/api/chatmodel/${props.chatId}`)
// console.log("inside else")
// }
// },[isFast])

useEffect(() => {
if (props.liveChat !== null) {
updateRoomData(messages);
Expand Down Expand Up @@ -76,7 +117,10 @@ export default function Chat(props: ChatProps) {
);
}
})}
{/* <div id="#forna" ref={divRef} ></div> */}
<InputBar
messages={messages}
setMessages={setMessages}
username={props.username}
userId={props.uid}
isFast={isFast}
Expand Down
3 changes: 2 additions & 1 deletion src/components/chatcard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import { useState } from "react";
import { Chat } from "@/lib/db/schema";
import Link from "next/link";
import { ArrowRight } from "lucide-react";
// import { ArrowRight } from "lucide-react";
import { ArrowRight } from "@phosphor-icons/react";
import { buttonVariants } from "@/components/button";
import {
Card,
Expand Down
51 changes: 44 additions & 7 deletions src/components/chatmessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,11 @@ import { SpecialComponents } from "react-markdown/lib/ast-to-react";
import { PluggableList } from "react-markdown/lib/react-markdown";
import { Badge } from "@/components/badge";
import { ScrollArea } from "@/components/scrollarea";
// import Plugable
// totally Message with an optional createdBy property
interface OrganizationChatMessage extends Message {
createdBy?: string;
}
import RenderRNA from "./functionUI/renderrna";

interface ChatMessageProps {
name: string;
chat: OrganizationChatMessage;
chat: Message;
uid: string;
}

Expand All @@ -41,6 +37,45 @@ const ChatMessage = (props: ChatMessageProps) => {
}
}

// if(props.chat.role === "user"){
// (
// <ReactMarkdown
// className="text-primary text-sm group-hover:text-gray-100"
// remarkPlugins={[remarkGfm]}
// rehypePlugins={[remarkRehype] as PluggableList}
// remarkRehypeOptions={{}}
// components={components}
// >
// {props.chat.content}
// </ReactMarkdown>
// )
// } else if(props.chat.role === "assistant" && props.chat.content !== null){
// (
// <ReactMarkdown
// className="text-primary text-sm max-w-full p-4 overflow-x-auto "
// remarkPlugins={[remarkGfm]}
// rehypePlugins={[remarkRehype] as PluggableList}
// components={components}
// >
// {props.chat.content}
// </ReactMarkdown>
// )
// } else if(props.chat.role === "assistant" && props.chat.content === null){
// if(props.chat.function_call){
// if(typeof props.chat.function_call === "string"){
// <p>{props.chat.function_call}</p>
// } else{
// <div>
// <p>{props.chat.function_call.name}</p>
// <p>{props.chat.function_call.arguments}</p>
// </div>
// }
// }
// } else if(props.chat.role === 'function'){
// const fuctionName = props.chat.name
// const fuctionResultJson = JSON.parse(props.chat.content)
// }

return (
<div
className={
Expand Down Expand Up @@ -69,7 +104,7 @@ const ChatMessage = (props: ChatMessageProps) => {
>
{props.chat.content}
</ReactMarkdown>
) : (
) : props.chat.role === "assistant" ? (
<ReactMarkdown
className="text-primary text-sm max-w-full p-4 overflow-x-auto "
remarkPlugins={[remarkGfm]}
Expand All @@ -78,6 +113,8 @@ const ChatMessage = (props: ChatMessageProps) => {
>
{props.chat.content}
</ReactMarkdown>
) : (
<RenderRNA chat={props.chat} />
)}
</div>
);
Expand Down
43 changes: 43 additions & 0 deletions src/components/functionUI/renderrna.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { useEffect, useRef } from "react";
import * as fornac from "fornac";
import { Message } from "ai";

type Props = {
chat: Message;
};

const RenderRNA = (props: Props) => {
const divRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const element = divRef.current as Element;
const Forna = new fornac.FornaContainer(element, {
animation: false,
zoomable: false,
initialSize: [800, 600],
});
let structure = null;
let sequence = null;
if (props.chat.role === ("function" as const)) {
console.log(JSON.parse(props.chat.content));
console.log("parsable");
let json = JSON.parse(props.chat.content);
structure = json.structure;
sequence = json.sequence;
}
let options = {
structure: structure, //? structure : "..((..((...[)).(((..].))).))..",
sequence: sequence, //? sequence : "AACGCUUCAUAUAAUCCUAAUGACCUAUAA",
};
Forna.addRNA(options.structure, options);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current]);

return (
<div id="#forna" ref={divRef}>
{props.chat.content}
</div>
);
};

export default RenderRNA;
35 changes: 31 additions & 4 deletions src/components/inputBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import TextareaAutosize from "react-textarea-autosize";
import { ChangeEvent, Dispatch, FormEvent, SetStateAction } from "react";
import { ChatRequestOptions, CreateMessage, Message } from "ai";
import { ChatRequestOptions, CreateMessage, Message, nanoid } from "ai";
import { Toggle } from "@/components/toogle";
import { Brain, Lightning } from "@phosphor-icons/react";

Expand All @@ -20,17 +20,44 @@ interface InputBarProps {
chatRequestOptions?: ChatRequestOptions | undefined,
) => Promise<string | null | undefined>;
setInput: Dispatch<SetStateAction<string>>;
messages: Message[];
setMessages: (messages: Message[]) => void;
}

const InputBar = (props: InputBarProps) => {
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
const message = {
role: "user",
role: "user" as const,
content: props.value,
name: `${props.username},${props.userId}`,
};
props.append(message as Message);
if (props.isFast) {
console.log("appendin");
props.append(message as Message);
} else {
props.setMessages([...props.messages, { ...message, id: nanoid() }]);
console.log("setting");
const res = await fetch(
`https://technoculture-echoes--bioinformatics-ai-web.modal.run?prompt=${props.value}`,
);
const data = await res.json();
const structure = "........";
const sequence = "ATGCGCGC";
const minFreeEnergy = 0.0;
const rna = {
structure,
sequence,
minFreeEnergy,
};
const newMessage = {
id: nanoid(),
role: "function" as const,
content: JSON.stringify(data),
};
props.setMessages([...props.messages, newMessage]);
console.log("data", data);
}
props.setInput("");
};

Expand Down
3 changes: 2 additions & 1 deletion src/components/room.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { ChatEntry, ChatLog } from "@/lib/types";
import { Chat as ChatSchema } from "@/lib/db/schema";

import { Button } from "@/components/button";
import { ArrowLeft } from "lucide-react";
// import { ArrowLeft } from "lucide-react";
import { ArrowLeft } from "@phosphor-icons/react";
import Link from "next/link";
import Chatusers from "@/components/chatusersavatars";
import Chat from "@/components/chat";
Expand Down
6 changes: 4 additions & 2 deletions src/components/startnewchatbutton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"use client";
import { useState } from "react";
import { PlusIcon } from "lucide-react";
// import { PlusIcon } from "lucide-react";
import { Plus } from "@phosphor-icons/react";
// import Link from 'next/link';
import { buttonVariants } from "@/components/button";
import { useRouter } from "next/navigation";
Expand Down Expand Up @@ -37,7 +38,8 @@ const Startnewchatbutton = (props: Props) => {
</>
) : (
<>
<PlusIcon className="w-4 h-4 mr-4" />
{/* <PlusIcon className="w-4 h-4 mr-4" /> */}
<Plus className="w-4 h-4 mr-4" />
Start a new Chat
</>
)}
Expand Down
1 change: 1 addition & 0 deletions src/utils/types/imports.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
declare module "fornac";