diff --git a/client/index.html b/client/index.html index 73f0bb6..b700cd7 100644 --- a/client/index.html +++ b/client/index.html @@ -5,7 +5,7 @@ - AI-automated screening PoC + AiSysRev
diff --git a/client/package.json b/client/package.json index bc31a75..9f95bd2 100644 --- a/client/package.json +++ b/client/package.json @@ -1,5 +1,5 @@ { - "name": "ai-automated-screening-poc", + "name": "aisysrev", "private": true, "version": "1.0.0", "type": "module", diff --git a/client/src/App.tsx b/client/src/App.tsx index 58f4b95..1edb9d9 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -8,7 +8,6 @@ import { ProjectsPage } from "./pages/ProjectsPage"; import { NewProject } from "./pages/NewProjectPage"; import { AboutPage } from "./pages/AboutPage"; import { ProjectPage } from "./pages/ProjectPage"; -import { ScreeningPage } from "./pages/ScreeningPage"; import { SettingsPage } from "./pages/SettingPage"; import { ResultPage } from "./pages/ResultPage"; import "react-loading-skeleton/dist/skeleton.css"; @@ -62,7 +61,6 @@ function App() { path="/terms-and-conditions" component={TermsAndConditionsPage} /> - diff --git a/client/src/pages/AboutPage.tsx b/client/src/pages/AboutPage.tsx index 3d9c856..6fb42e1 100644 --- a/client/src/pages/AboutPage.tsx +++ b/client/src/pages/AboutPage.tsx @@ -25,13 +25,13 @@ export const AboutPage = () => ( className="text-blue-600 hover:underline flex flex-row gap-2 justify-start items-center w-fit" > - OpenAPI JSON + /openapi.json

AISysRev demonstrates the capabilities of AI-automated title-abstract screening of systematic reviews (SRs), which is subject - to further research and improvements. This PoC is based on the following + to further research and improvements. This tool is based on the following scientific contributions:

  • @@ -78,7 +78,7 @@ export const AboutPage = () => (

    Supported LLMs

    - We support all LLMs hosted by Openrouter,{" "} + We support models from Openrouter, OpenAI and local OpenAI SDK{" "} that support structured JSON response, along with configuring temperature, seed and top_p parameters. diff --git a/client/src/pages/ScreeningPage.tsx b/client/src/pages/ScreeningPage.tsx deleted file mode 100644 index 49a1eb3..0000000 --- a/client/src/pages/ScreeningPage.tsx +++ /dev/null @@ -1,526 +0,0 @@ -import { useCallback, useId, useState } from "react"; -import { - available_models, - DecisionType, - default_model, - isLeft, - type Criteria, - type Model, -} from "../llm/types"; -import { - exampleCriteria, - exampleTitle, - exampleAbstract, -} from "../example_data"; -import { query_llm } from "../llm/llm"; -import { generatePrompt } from "../llm/prompt"; -import { FileDropArea } from "../components/FileDropArea"; - -const AUTHORIZATION_TOKEN = "AUTHORIZATION_TOKEN"; -const TEMPERATURE = "TEMPERATURE"; -const SEED = "SEED"; -const AI_MODEL = "AI_MODEL"; - -const abortController = new AbortController(); - -function Header() { - return ( -

    -

    - AI-automated title-abstract screening PoC -

    -
    - ); -} - -const ErrorPopup: React.FC<{ - error: string; - setError: (v: string) => void; -}> = ({ error, setError }) => { - return ( -
    -
    -

    An error occured

    -
    {error}
    -
    { - e.preventDefault(); - setError(""); - }} - > - Close -
    -
    -
    - ); -}; - -const Subtitle: React.FC<{ title: string; description: string }> = ({ - title, - description, -}) => ( -
    - {title} - {description} -
    -); - -const AppInstructions: React.FC<{ loadExample: () => void }> = ({ - loadExample, -}) => { - return ( -
    -

    Introduction

    -

    - This proof-of-concept (PoC) demonstrates the capabilities of - AI-automated title-abstract screening of systematic reviews (SRs), which - is subject to further research and improvements. This PoC is based on a - conference paper{" "} - - "The Promise and Challenges of Using LLMs to Accelerate the Screening - Process of Systematic Reviews" - {" "} - by Huotala et al. -

    -

    Supported LLMs

    -

    - We support all foundational models listed in the Openrouter website. -

    -

    License

    -

    CC-BY-ND 4.0

    -

    Source code

    -

    Available by request.

    -

    Examples

    -

    - -

    -
    - ); -}; - -export const ScreeningPage = () => { - const [error, setError] = useState(""); - const [criterias, setCriterias] = useState>([]); - const currentId = - criterias.length === 0 ? 0 : Math.max(...criterias.map((c) => c.id)); - - const [selectedModel, setSelectedModel] = useState( - localStorage.getItem(AI_MODEL) || default_model - ); - - const [newCriteria, setNewCriteria] = useState(""); - - const [temperature, setTemperature] = useState( - parseFloat(localStorage.getItem(TEMPERATURE) || "0.0") - ); - const [seed, setSeed] = useState( - parseInt(localStorage.getItem(SEED) ?? "128", 10) - ); - const [title, setTitle] = useState(""); - const [abstract, setAbstract] = useState(""); - const [authorizationToken, setAuthorizationToken] = useState( - localStorage.getItem(AUTHORIZATION_TOKEN) || "" - ); - - const [enforceJSON, setEnforceJSON] = useState(false); - const [decisionType, setDecisionType] = - useState("IncludeExclude"); - const [pending, setPending] = useState(false); - - const [response, setResponse] = useState(undefined); - - const loadExample = useCallback(() => { - setCriterias(exampleCriteria); - setTemperature(0); - setSeed(128); - setTitle(exampleTitle); - setAbstract(exampleAbstract); - }, []); - - const onNewCriteria = useCallback< - (e: React.FormEvent) => void - >( - (e) => { - e.preventDefault(); - setCriterias((p) => [ - ...p, - { - id: currentId + 1, - criteria: newCriteria, - }, - ]); - setNewCriteria(""); - }, - [currentId, newCriteria] - ); - - const abort = useCallback(() => { - abortController.abort("Request has been aborted by the user"); - setPending(false); - }, []); - - const sendRequest = useCallback< - (e: React.MouseEvent) => void - >( - // eslint-disable-next-line @typescript-eslint/no-unused-vars - async (_e) => { - try { - setPending(true); - setResponse(undefined); - - const res = await query_llm( - generatePrompt(criterias, title, abstract, decisionType), - authorizationToken, - abortController, - selectedModel, - enforceJSON, - temperature, - seed, - decisionType - ); - if (isLeft(res)) { - setResponse(res.result.choices[0].message.content); - } else { - console.error("Error calling LLM"); - setError(res.error); - console.error(res); - } - } catch (err) { - console.error(err); - } finally { - setPending(false); - } - }, - [ - abstract, - authorizationToken, - criterias, - decisionType, - enforceJSON, - seed, - selectedModel, - temperature, - title, - ] - ); - - const id = useId(); - - return ( -
    - {error !== "" && } -
    -
    -
    - -
    -
    - -
    - -
    - -
    -
    - { - e.preventDefault(); - setNewCriteria(e.target.value); - }} - placeholder="Write a single criteria and press [Enter]" - className="p-2 rounded-lg w-full bg-slate-300" - /> -
    -
      - {[...criterias] - .sort((a, b) => a.id - b.id) - .map((c) => { - return ( -
    1. - - {c.criteria} - {" "} - { - e.preventDefault(); - const currentCriteria = [...criterias]; - const filteredCriterias = currentCriteria.filter( - (criteria) => criteria.id !== c.id - ); - setCriterias([...filteredCriterias]); - }} - role="button" - data-testid={`inclusion-criteria-${c.id}-delete`} - className="inline-block m-1 text-sm bg-red-800 text-white p-2 rounded-md hover:cursor-pointer" - > - Delete - -
    2. - ); - })} -
    -
    - -
    -
    { - e.preventDefault(); - }} - className="flex flex-col gap-4" - data-testid="title-abstract-form" - > - { - e.preventDefault(); - setTitle(e.target.value); - }} - /> -