From 064ecd7483ec4b631446b883963383b23390e99a Mon Sep 17 00:00:00 2001 From: Harry Li Date: Wed, 25 Sep 2024 12:26:38 -0400 Subject: [PATCH] added formatURI, added absolute imports, fixed demo data, added workflows (#7) * added formatURI, added absolute imports, fixed demo data * added github actions * added environment variables --------- Co-authored-by: Harry Li --- .github/workflows/client-build.yml | 48 +++++++++++++++ .github/workflows/deploy.yml | 57 ++++++++++++++++++ package-lock.json | 51 +++++++++++++++- package.json | 3 +- src/App.tsx | 26 +++++---- src/components/ApiKeyWarning.tsx | 8 ++- src/components/Chat/Chat.tsx | 23 ++++---- src/components/DemoModeModal.tsx | 6 +- src/components/IDTable/IDTable.tsx | 10 +++- src/components/QueryEditor/QueryEditor.tsx | 11 ++-- .../QueryGraph/QueryGraph.tsx | 16 +++-- .../QueryVisualization/QueryVisualization.tsx | 10 ++-- src/components/ResultsTable/ResultsTable.tsx | 7 ++- src/hooks/useGetNewChatId.ts | 6 +- src/hooks/useMakeChatGPTAPIInstance.tsx | 8 ++- src/hooks/useRunQuery.tsx | 19 +++--- src/redux/chatHistorySlice.ts | 5 +- src/redux/queryHistorySlice.ts | 6 +- src/redux/queryValueSlice.ts | 3 +- src/redux/resultsSlice.ts | 6 +- src/redux/settingsSlice.ts | 2 +- src/redux/store.ts | 1 + src/utils/demoData.ts | 58 +++++++++++++++++++ src/utils/graphin.ts | 4 +- src/utils/knowledgeBase/formatURI.ts | 20 +++++++ src/utils/knowledgeBase/fuzzySearch.ts | 4 +- src/utils/knowledgeBase/getEntityData.ts | 6 +- src/utils/knowledgeBase/runQuery.ts | 5 +- src/utils/parseSparqlQuery.ts | 3 +- src/utils/summarizeQueryResults.ts | 3 +- src/utils/transformTripleDataToGraphin.ts | 5 +- tsconfig.json | 4 +- vite.config.ts | 5 +- 33 files changed, 368 insertions(+), 81 deletions(-) create mode 100644 .github/workflows/client-build.yml create mode 100644 .github/workflows/deploy.yml create mode 100644 src/utils/knowledgeBase/formatURI.ts diff --git a/.github/workflows/client-build.yml b/.github/workflows/client-build.yml new file mode 100644 index 0000000..b8b2173 --- /dev/null +++ b/.github/workflows/client-build.yml @@ -0,0 +1,48 @@ +# Simple workflow for ensuring the site builds properly +name: Ensure the site builds properly + +on: + # Runs on pushes targeting the default branch + push: + branches: ['main'] + + pull_request: + branches: [ "main" ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages +permissions: + contents: read + +# Allow one concurrent deployment +concurrency: + group: 'build' + cancel-in-progress: true + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Set env + shell: bash + run: | + echo "VITE_OPENAI_API_KEY=test" >> $GITHUB_ENV + echo "VITE_DEMO_MODE=true" >> $GITHUB_ENV + echo "GITHUB_PAGES=true" >> $GITHUB_ENV + - name: Build + run: npm run build \ No newline at end of file diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..c11fbd9 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,57 @@ +# Simple workflow for deploying static content to GitHub Pages +name: Deploy site to GitHub Pages + +on: + # Runs on pushes targeting the default branch + push: + branches: ['main'] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets the GITHUB_TOKEN permissions to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow one concurrent deployment +concurrency: + group: 'pages' + cancel-in-progress: true + +jobs: + # Single deploy job since we're just deploying + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Set env + shell: bash + run: | + echo "VITE_OPENAI_API_KEY=test" >> $GITHUB_ENV + echo "VITE_DEMO_MODE=true" >> $GITHUB_ENV + echo "GITHUB_PAGES=true" >> $GITHUB_ENV + - name: Build + run: npm run build + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + # Upload build folder + path: './build' + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0e280c8..c9ff12b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,8 @@ "typescript": "^5.2.2", "undici": "^6.19.8", "vite": "^5.1.0", - "vite-plugin-commonjs": "^0.10.1" + "vite-plugin-commonjs": "^0.10.1", + "vite-tsconfig-paths": "^5.0.1" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -3421,6 +3422,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true, + "license": "MIT" + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -5755,6 +5763,27 @@ "typescript": ">=4.2.0" } }, + "node_modules/tsconfck": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.3.tgz", + "integrity": "sha512-ulNZP1SVpRDesxeMLON/LtWM8HIgAJEIVpVVhBM6gsmvQ8+Rh+ZG7FWGvHh7Ah3pRABwVJWklWCr/BTZSv0xnQ==", + "dev": true, + "license": "MIT", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -6126,6 +6155,26 @@ "magic-string": "^0.30.1" } }, + "node_modules/vite-tsconfig-paths": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-5.0.1.tgz", + "integrity": "sha512-yqwv+LstU7NwPeNqajZzLEBVpUFU6Dugtb2P84FXuvaoYA+/70l9MHE+GYfYAycVyPSDYZ7mjOFuYBRqlEpTig==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "tsconfck": "^3.0.3" + }, + "peerDependencies": { + "vite": "*" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, "node_modules/w3c-keyname": { "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", diff --git a/package.json b/package.json index 9214ebf..fe3b483 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "typescript": "^5.2.2", "undici": "^6.19.8", "vite": "^5.1.0", - "vite-plugin-commonjs": "^0.10.1" + "vite-plugin-commonjs": "^0.10.1", + "vite-tsconfig-paths": "^5.0.1" } } diff --git a/src/App.tsx b/src/App.tsx index 996686b..41ba1ae 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,17 +1,21 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { QueryEditor } from './components/QueryEditor/QueryEditor' -import { ResultsTable } from './components/ResultsTable/ResultsTable'; -import { Chat } from './components/Chat/Chat'; -import { IDTableContainer } from './components/IDTable/IDTable'; import { Title } from '@mantine/core'; -import { ErrorMessage } from './components/ErrorMessage'; -import { useRunQuery, RunQueryProvider } from './hooks/useRunQuery'; -import {QueryVisualization} from "./components/QueryVisualization/QueryVisualization"; -import { useAppSelector } from './redux/store'; -import styles from './App.module.scss' -import { DemoModeModal } from './components/DemoModeModal'; -import { ApiKeyWarning } from './components/ApiKeyWarning'; + +import { ApiKeyWarning } from 'components/ApiKeyWarning'; +import { Chat } from 'components/Chat/Chat'; +import { DemoModeModal } from 'components/DemoModeModal'; +import { ErrorMessage } from 'components/ErrorMessage'; +import { IDTableContainer } from 'components/IDTable/IDTable'; +import { QueryEditor } from 'components/QueryEditor/QueryEditor' +import { QueryVisualization } from "components/QueryVisualization/QueryVisualization"; +import { ResultsTable } from 'components/ResultsTable/ResultsTable'; + +import { useAppSelector } from 'redux/store'; + +import { useRunQuery, RunQueryProvider } from 'hooks/useRunQuery'; + +import styles from 'App.module.scss' function App() { diff --git a/src/components/ApiKeyWarning.tsx b/src/components/ApiKeyWarning.tsx index bc920de..47985a0 100644 --- a/src/components/ApiKeyWarning.tsx +++ b/src/components/ApiKeyWarning.tsx @@ -1,5 +1,9 @@ -import { useAppSelector } from "../redux/store" -import { IS_DEMO_MODE } from "../utils/demoData" +// Copyright (c) 2024 Massachusetts Institute of Technology +// SPDX-License-Identifier: MIT + +import { useAppSelector } from "redux/store" + +import { IS_DEMO_MODE } from "utils/demoData" export function ApiKeyWarning() { const apiKey = useAppSelector((state) => state.settings.apiKey) diff --git a/src/components/Chat/Chat.tsx b/src/components/Chat/Chat.tsx index 0576369..905e54b 100644 --- a/src/components/Chat/Chat.tsx +++ b/src/components/Chat/Chat.tsx @@ -6,20 +6,23 @@ import { StreamLanguage } from '@codemirror/language'; import { sparql } from '@codemirror/legacy-modes/mode/sparql'; import { ActionIcon, Button, Checkbox, Modal, TextInput } from "@mantine/core"; import { useEffect, useMemo, useRef, useState } from "react"; -import styles from "./Chat.module.scss" import { useMutation } from "@tanstack/react-query"; import { IconCaretRight, IconSettings, IconZoomCode } from '@tabler/icons-react'; -import { ErrorMessage } from '../ErrorMessage'; -import { useRunQuery } from '../../hooks/useRunQuery'; -import { useAppDispatch, useAppSelector } from '../../redux/store'; -import { setQueryValue } from '../../redux/queryValueSlice'; -import { useMakeChatGPTAPIInstance } from '../../hooks/useMakeChatGPTAPIInstance'; -import { addMessageToSimpleChatHistory, toggleShowFullChatHistory } from '../../redux/chatHistorySlice'; -import { INITIAL_SYSTEM_MESSAGE } from '../../utils/knowledgeBase/prompts'; -import { handleUserChat } from '../../utils/handleUserChat'; -import { tryParsingOutQuery } from '../../utils/tryParsingOutQuery'; +import { ErrorMessage } from 'components/ErrorMessage'; + +import { useMakeChatGPTAPIInstance } from 'hooks/useMakeChatGPTAPIInstance'; +import { useRunQuery } from 'hooks/useRunQuery'; + +import { addMessageToSimpleChatHistory, toggleShowFullChatHistory } from 'redux/chatHistorySlice'; +import { setQueryValue } from 'redux/queryValueSlice'; +import { useAppDispatch, useAppSelector } from 'redux/store'; +import { handleUserChat } from 'utils/handleUserChat'; +import { INITIAL_SYSTEM_MESSAGE } from 'utils/knowledgeBase/prompts'; +import { tryParsingOutQuery } from 'utils/tryParsingOutQuery'; + +import styles from "./Chat.module.scss" export function Chat() { diff --git a/src/components/DemoModeModal.tsx b/src/components/DemoModeModal.tsx index 57d1990..5417453 100644 --- a/src/components/DemoModeModal.tsx +++ b/src/components/DemoModeModal.tsx @@ -1,7 +1,11 @@ +// Copyright (c) 2024 Massachusetts Institute of Technology +// SPDX-License-Identifier: MIT + import { Button, Modal } from "@mantine/core"; import { useDisclosure } from "@mantine/hooks"; import { IconBrandGithub } from "@tabler/icons-react"; -import { IS_DEMO_MODE } from "../utils/demoData"; + +import { IS_DEMO_MODE } from "utils/demoData"; export function DemoModeModal() { const [opened, { close }] = useDisclosure(true); diff --git a/src/components/IDTable/IDTable.tsx b/src/components/IDTable/IDTable.tsx index b791fbe..b29ffc2 100644 --- a/src/components/IDTable/IDTable.tsx +++ b/src/components/IDTable/IDTable.tsx @@ -1,11 +1,15 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { useQueryGetIDTableEntitiesFromQuery } from "../../utils/knowledgeBase/getEntityData"; import { createColumnHelper, flexRender, getCoreRowModel, useReactTable } from "@tanstack/react-table"; import { Table, Title } from "@mantine/core"; -import { useAppSelector } from "../../redux/store"; -import { IDTableEntitiesType } from "../../types/idTable"; + +import { useAppSelector } from "redux/store"; + +import { IDTableEntitiesType } from "types/idTable"; + +import { useQueryGetIDTableEntitiesFromQuery } from "utils/knowledgeBase/getEntityData"; + import styles from "./IDTable.module.scss" export function IDTableContainer () { diff --git a/src/components/QueryEditor/QueryEditor.tsx b/src/components/QueryEditor/QueryEditor.tsx index 32cc932..72d8bbc 100644 --- a/src/components/QueryEditor/QueryEditor.tsx +++ b/src/components/QueryEditor/QueryEditor.tsx @@ -8,12 +8,13 @@ import { useDisclosure } from '@mantine/hooks'; import { ActionIcon, Button, Divider, Modal, Title } from '@mantine/core'; import { IconCaretRight, IconHistory } from '@tabler/icons-react'; -import styles from "./QueryEditor.module.scss" -import { useAppDispatch, useAppSelector } from '../../redux/store'; -import { setQueryValue } from '../../redux/queryValueSlice'; -import { setResults } from '../../redux/resultsSlice'; -import { useRunQuery } from '../../hooks/useRunQuery'; +import { setResults } from 'redux/resultsSlice'; +import { setQueryValue } from 'redux/queryValueSlice'; +import { useAppDispatch, useAppSelector } from 'redux/store'; + +import { useRunQuery } from 'hooks/useRunQuery'; +import styles from "./QueryEditor.module.scss" export function QueryEditor() { const dispatch = useAppDispatch() diff --git a/src/components/QueryVisualization/QueryGraph/QueryGraph.tsx b/src/components/QueryVisualization/QueryGraph/QueryGraph.tsx index 78a49ea..b69f30e 100644 --- a/src/components/QueryVisualization/QueryGraph/QueryGraph.tsx +++ b/src/components/QueryVisualization/QueryGraph/QueryGraph.tsx @@ -1,13 +1,17 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import Graphin, {Components, LegendChildrenProps} from "@antv/graphin"; -import {parseSparqlQuery} from "../../../utils/parseSparqlQuery.ts"; -import {useQueryGetIDTableEntitiesFromQuery} from "../../../utils/knowledgeBase/getEntityData.ts"; -import {transformTripleQueryToGraphin} from "../../../utils/transformTripleDataToGraphin.ts"; + import {useMemo} from "react"; -import { Title } from '@mantine/core'; + +import Graphin, {Components, LegendChildrenProps} from "@antv/graphin"; import '@antv/graphin/dist/index.css'; -import { useAppSelector } from "../../../redux/store.ts"; +import { Title } from '@mantine/core'; + +import { useAppSelector } from "redux/store.ts"; + +import { parseSparqlQuery } from "utils/parseSparqlQuery.ts"; +import { transformTripleQueryToGraphin } from "utils/transformTripleDataToGraphin.ts"; +import { useQueryGetIDTableEntitiesFromQuery } from "utils/knowledgeBase/getEntityData.ts"; const { Legend } = Components; diff --git a/src/components/QueryVisualization/QueryVisualization.tsx b/src/components/QueryVisualization/QueryVisualization.tsx index 501748c..135162e 100644 --- a/src/components/QueryVisualization/QueryVisualization.tsx +++ b/src/components/QueryVisualization/QueryVisualization.tsx @@ -1,9 +1,11 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import {QueryGraph} from "./QueryGraph/QueryGraph.tsx"; -import {ErrorBoundary} from "react-error-boundary"; -import {useEffect, useState} from "react"; -import { useAppSelector } from "../../redux/store.ts"; +import { ErrorBoundary } from "react-error-boundary"; +import { useEffect, useState } from "react"; + +import { useAppSelector } from "redux/store.ts"; + +import { QueryGraph } from "./QueryGraph/QueryGraph.tsx"; const QueryVisualizationFallback = () => { return (<>) diff --git a/src/components/ResultsTable/ResultsTable.tsx b/src/components/ResultsTable/ResultsTable.tsx index d388330..6604a6a 100644 --- a/src/components/ResultsTable/ResultsTable.tsx +++ b/src/components/ResultsTable/ResultsTable.tsx @@ -1,9 +1,10 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { SparqlBindingType, SparqlValueObjectType, SparqlResultsJsonType } from "../../types/sparql"; +import { SparqlBindingType, SparqlValueObjectType, SparqlResultsJsonType } from "types/sparql"; import { useReactTable, flexRender, createColumnHelper, getCoreRowModel } from "@tanstack/react-table" -import { downloadJson } from "../../utils/downloadJson"; +import { downloadJson } from "utils/downloadJson"; +import { formatURI, getHrefFromURI } from "utils/knowledgeBase/formatURI"; import { ActionIcon, Table } from '@mantine/core'; import { IconDownload } from '@tabler/icons-react'; @@ -84,7 +85,7 @@ function renderCell(cell:SparqlValueObjectType):React.ReactNode { return } if(cell.type === "uri") { - return {cell.value.replace("http://www.wikidata.org/","")} + return {formatURI(cell.value)} } return cell.value } \ No newline at end of file diff --git a/src/hooks/useGetNewChatId.ts b/src/hooks/useGetNewChatId.ts index fbbe533..97a0f7a 100644 --- a/src/hooks/useGetNewChatId.ts +++ b/src/hooks/useGetNewChatId.ts @@ -1,8 +1,9 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import { useDispatch } from "react-redux"; -import { useAppSelector } from "../redux/store"; -import { incrementChatIdCounter } from "../redux/chatHistorySlice"; + +import { incrementChatIdCounter } from "redux/chatHistorySlice"; +import { useAppSelector } from "redux/store"; //This hook returns a function that returns the current chat id counter //and increments the counter for the next usage @@ -11,7 +12,6 @@ export function useGetNewChatId() { const chatIdCounter = useAppSelector(state => state.chatHistory.chatIdCounter) return () => { - console.log("I RUN") dispatch(incrementChatIdCounter()) return chatIdCounter } diff --git a/src/hooks/useMakeChatGPTAPIInstance.tsx b/src/hooks/useMakeChatGPTAPIInstance.tsx index 362d4e6..75f698b 100644 --- a/src/hooks/useMakeChatGPTAPIInstance.tsx +++ b/src/hooks/useMakeChatGPTAPIInstance.tsx @@ -1,8 +1,10 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { useAppDispatch, useAppSelector } from "../redux/store" -import { ChatGPTAPI, ChatGPTAPIConstructorArgsType, ChatHistoryType } from "../utils/ChatGPTAPI" -import { addMessagesToFullChatHistory } from "../redux/chatHistorySlice" +import { addMessagesToFullChatHistory } from "redux/chatHistorySlice" +import { useAppDispatch, useAppSelector } from "redux/store" + +import { ChatGPTAPI, ChatGPTAPIConstructorArgsType, ChatHistoryType } from "utils/ChatGPTAPI" + import { useGetNewChatId } from "./useGetNewChatId" diff --git a/src/hooks/useRunQuery.tsx b/src/hooks/useRunQuery.tsx index 1d3defa..53f9930 100644 --- a/src/hooks/useRunQuery.tsx +++ b/src/hooks/useRunQuery.tsx @@ -1,14 +1,19 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { UseMutateFunction, useMutation } from "@tanstack/react-query"; import { createContext, useContext } from "react"; -import { runQuery as runQueryFunction } from '../utils/knowledgeBase/runQuery.ts'; -import { summarizeQueryResults } from '../utils/summarizeQueryResults.ts'; -import { setResults } from '../redux/resultsSlice.ts'; -import { pushQueryHistory } from '../redux/queryHistorySlice.ts'; -import { useAppDispatch } from "../redux/store.ts"; + +import { UseMutateFunction, useMutation } from "@tanstack/react-query"; + +import { pushQueryHistory } from 'redux/queryHistorySlice.ts'; +import { setResults } from 'redux/resultsSlice.ts'; +import { useAppDispatch } from "redux/store.ts"; + +import { runQuery as runQueryFunction } from 'utils/knowledgeBase/runQuery.ts'; +import { summarizeQueryResults } from 'utils/summarizeQueryResults.ts'; + +import { SparqlResultsJsonType } from "types/sparql.ts"; + import { useMakeChatGPTAPIInstance } from "./useMakeChatGPTAPIInstance.tsx"; -import { SparqlResultsJsonType } from "../types/sparql.ts"; //this sets up a context so we can define one runQuery function for the whole app const RunQueryContext = createContext<{ diff --git a/src/redux/chatHistorySlice.ts b/src/redux/chatHistorySlice.ts index f0ff086..1e365e9 100644 --- a/src/redux/chatHistorySlice.ts +++ b/src/redux/chatHistorySlice.ts @@ -1,8 +1,9 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import { PayloadAction, createSlice } from '@reduxjs/toolkit' -import { ChatHistoryType, ChatMessageType } from '../utils/ChatGPTAPI' -import { DEMO_FULL_HISTORY, DEMO_SIMPLE_HISTORY, IS_DEMO_MODE } from '../utils/demoData' + +import { ChatHistoryType, ChatMessageType } from 'utils/ChatGPTAPI' +import { DEMO_FULL_HISTORY, DEMO_SIMPLE_HISTORY, IS_DEMO_MODE } from 'utils/demoData' const initialState: { diff --git a/src/redux/queryHistorySlice.ts b/src/redux/queryHistorySlice.ts index dc42b31..5db6128 100644 --- a/src/redux/queryHistorySlice.ts +++ b/src/redux/queryHistorySlice.ts @@ -1,8 +1,10 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import { PayloadAction, createSlice } from '@reduxjs/toolkit' -import { DEMO_QUERY_HISTORY, IS_DEMO_MODE } from '../utils/demoData' -import { SparqlResultsJsonType } from '../types/sparql' + +import { DEMO_QUERY_HISTORY, IS_DEMO_MODE } from 'utils/demoData' + +import { SparqlResultsJsonType } from 'types/sparql' type QueryRecordType = { diff --git a/src/redux/queryValueSlice.ts b/src/redux/queryValueSlice.ts index 3dc7f27..9667003 100644 --- a/src/redux/queryValueSlice.ts +++ b/src/redux/queryValueSlice.ts @@ -1,7 +1,8 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import { PayloadAction, createSlice } from '@reduxjs/toolkit' -import { DEMO_QUERY, IS_DEMO_MODE } from '../utils/demoData' + +import { DEMO_QUERY, IS_DEMO_MODE } from 'utils/demoData' // const GET_GOOGLE_FOUNDERS_AND_BIRTHDAYS = `SELECT ?founder ?founderLabel ?birthdate diff --git a/src/redux/resultsSlice.ts b/src/redux/resultsSlice.ts index e9cbc61..ec73aee 100644 --- a/src/redux/resultsSlice.ts +++ b/src/redux/resultsSlice.ts @@ -1,8 +1,10 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import { PayloadAction, createSlice } from '@reduxjs/toolkit' -import { DEMO_RESULTS, IS_DEMO_MODE } from '../utils/demoData' -import { SparqlResultsJsonType } from '../types/sparql' + +import { DEMO_RESULTS, IS_DEMO_MODE } from 'utils/demoData' + +import { SparqlResultsJsonType } from 'types/sparql' type ResultsType = {error: string | null, data: SparqlResultsJsonType | null, summary: string | null} | null diff --git a/src/redux/settingsSlice.ts b/src/redux/settingsSlice.ts index f5d085a..b8a3310 100644 --- a/src/redux/settingsSlice.ts +++ b/src/redux/settingsSlice.ts @@ -1,6 +1,6 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { PayloadAction, createSlice } from '@reduxjs/toolkit' +import { createSlice } from '@reduxjs/toolkit' const initialState: { apiKey: string, diff --git a/src/redux/store.ts b/src/redux/store.ts index 8696035..b112f35 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: MIT import { useDispatch, useSelector } from 'react-redux' import { configureStore } from '@reduxjs/toolkit' + import { chatHistorySliceReducer } from './chatHistorySlice' import { queryValueReducer } from './queryValueSlice' import { resultsReducer } from './resultsSlice' diff --git a/src/utils/demoData.ts b/src/utils/demoData.ts index 2da754b..c32b795 100644 --- a/src/utils/demoData.ts +++ b/src/utils/demoData.ts @@ -263,18 +263,26 @@ export const DEMO_RESULTS = { export const DEMO_SIMPLE_HISTORY:ChatHistoryType = [ { + "chatId": 0, + "name": "user", "role": "user", "content": "Can you tell me about interesting movies?" }, { + "chatId": 0, + "name": "system", "content": "I can help you create a SPARQL query to find interesting movies from Wikidata. Could you specify what makes a movie interesting for you? For example, are you interested in movies by a certain director, within a specific genre, or those that have won specific awards?", "role": "assistant" }, { + "chatId": 0, + "name": "user", "role": "user", "content": "Between 2022 and 2024, which movies won the Academy Award for Best Picture? Also tell me who was the movie director, and when it won the award." }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "content": "```sparql\nSELECT ?movie ?movieLabel ?director ?directorLabel ?awardDate\nWHERE {\n ?movie p:P166 ?statement. # P166 is the property for 'award received'\n ?statement ps:P166 wd:Q102427; # Q102427 represents 'Academy Award for Best Picture'\n pq:P585 ?awardDate. # P585 is the property for 'point in time'\n ?movie wdt:P57 ?director. # P57 is the property for 'director'\n \n FILTER(YEAR(?awardDate) >= 2022 && YEAR(?awardDate) <= 2024)\n \n SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". }\n}\nORDER BY ?awardDate\n```\nThis query fetches movies that won the Academy Award for Best Picture between 2022 and 2024, including each movie's director and the date when the award was won. It filters the awards by the given years and orders the results by the date when the award was received.", "role": "assistant" } @@ -282,102 +290,152 @@ export const DEMO_SIMPLE_HISTORY:ChatHistoryType = [ export const DEMO_FULL_HISTORY:ChatHistoryType = [ { + "chatId": 0, + "name": "system", "role": "system", "content": "You are a helpful chat assistant. This system will give you access to data in the WikiData Knowledge Graph, that contains encyclopedic data similar to Wikipedia, but in knowledge graph format using the RDF framework. \n\nIf users ask questions that can be answered via WikiData, your job is not to directly answer their questions, but instead to help them write a SPARQL query to find that data. You can ask the user to clarify their questions if the questions are vague, open-ended, or subjective in nature. \n\nIf you ever need to suggest data to the user, you should only provide recommendations that are directly accessible from Wikidata. Do not ask the user if they would like to proceed with generating the corresponding query unless absolutely necessary.\n\nWhen you are ready to start building a query, respond with 'BUILD QUERY'. The system will walk you through a guided workflow to get the necessary entity and property IDs from WikiData.\n\nCurrent date: Mon Jun 10 2024." }, { + "chatId": 0, + "name": "user", "content": "Can you tell me about interesting movies?", "role": "user" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "I can help you create a SPARQL query to find interesting movies from Wikidata. Could you specify what makes a movie interesting for you? For example, are you interested in movies by a certain director, within a specific genre, or those that have won specific awards?" }, { + "chatId": 0, + "name": "user", "content": "Between 2022 and 2024, which movies won the Academy Award for Best Picture? Also tell me who was the movie director, and when it won the award.", "role": "user" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "BUILD QUERY" }, { + "chatId": 0, + "name": "system", "content": "Your goal is to find the necessary entity and property IDs to construct a SPARQL query that answers the user's question. Do not respond with a trailing period. Do not assume you already know the correct entity and property IDs; you should search for them. Make sure to filter the IDs for the ones that are most relevant to the question. Respond in one of these ways:\n- To fuzzy search for an entity, start the response with 'ENTITY SEARCH:', followed by an entity name you want to search for. The system will respond with possible entity resolutions in Wikidata. \n- To get all the properties for an entity, start the response with 'PROPERTIES SEARCH:', followed by the ID of the entity. The user will respond with all the properties associated with that entity.\n- To find what entities are connected to the original entity via a property, start the response with 'ENTITY PROPERTY SEARCH:', followed by the entity ID then the property ID. Ex: 'ENTITY PROPERTY SEARCH: Q123 P456'\n- Respond with 'STOP' if and only if you have searched for and successfully identified all necessary IDs from Wikidata to construct the query.", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "ENTITY SEARCH: Academy Award for Best Picture" }, { + "chatId": 0, + "name": "system", "content": "ID: Q102427, label: Academy Award for Best Picture, description: annual award from the Academy of Motion Picture Arts and Sciences\nID: Q14943591, label: Academy Award for Best Picture (1980s), description: undefined\nID: Q14943588, label: Academy Award for Best Picture (1950s), description: undefined\nID: Q14943585, label: Academy Award for Best Picture (1930s), description: undefined\nID: Q14943586, label: Academy Award for Best Picture (1940s), description: undefined", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "PROPERTIES SEARCH: Q102427" }, { + "chatId": 0, + "name": "system", "content": "ID: P1346, label: winner, description: winner of a competition or similar event, not to be used for awards (instead use \"award received\" (P166) on awardee's item, possibly qualified with \"for work\" (P1686)) or for wars or battles\nID: P2910, label: icon, description: pictogram suitable to represent the item. For logos of a subject, use \"logo image\" (P154); for favicons, use \"small logo or icon\" (P8972)\nID: P1417, label: Encyclopædia Britannica Online ID, description: identifier for an article in the online version of Encyclopædia Britannica\nID: P8115, label: eligible recipient, description: party that is eligible to receive something, like an award, grant or prize\nID: P12086, label: WikiKids ID, description: identifier of the article on WikiKids\nID: P31, label: instance of, description: that class of which this subject is a particular example and member; different from P279 (subclass of); for example: K2 is an instance of mountain; volcano is a subclass of mountain (and an instance of volcanic landform)\nID: P6262, label: Fandom article ID, description: identifier of an article on Fandom (Wikia). Format: subdomain:Page_title (language-code.subdomain:Page_title for non-English wikis)\nID: P17, label: country, description: sovereign state that this item is in (not to be used for human beings)\nID: P2257, label: event interval, description: standard nominal interval between scheduled or regularly recurring events. Include unit of time, e.g. \"year\" (Q577). 1/(event frequency). time period of periodically occurring event\nID: P1424, label: topic's main template, description: the main template relating to a topic\nID: P2517, label: category for recipients of this award, description: link to Wikimedia category for recipients of this award\nID: P154, label: logo image, description: graphic mark or emblem commonly used by commercial enterprises, organizations and products\nID: P8408, label: KBpedia ID, description: identifier for the KBpedia knowledge graph, which provides consistent mappings across seven large-scale public knowledge bases including Wikidata, and is used to promote data interoperability and extraction of training sets for machine learning\nID: P1705, label: native label, description: label for the items in their official language (P37) or their original language (P364)\nID: P373, label: Commons category, description: name of the Wikimedia Commons category containing files related to this item (without the prefix \"Category:\")\nID: P910, label: topic's main category, description: main Wikimedia category\nID: P646, label: Freebase ID, description: identifier for a page in the Freebase database. Format: \"/m/0\" followed by 2 to 7 characters. For IDs starting with \"/g/\", use Google Knowledge Graph ID (P2671)\nID: P571, label: inception, description: time when an entity begins to exist; for date of official opening use P1619\nID: P856, label: official website, description: URL of the official page of an item (current or former). Usage: If a listed URL no longer points to the official website, do not remove it, but see the \"Hijacked or dead websites\" section of the Talk page\nID: P1027, label: conferred by, description: person or organization who grants an award, certification, grant, or role", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "ENTITY SEARCH: Academy Award winner" }, { + "chatId": 0, + "name": "system", "content": "ID: Q976472, label: Sings Days of Wine and Roses, Moon River and Other Academy Award Winners, description: 1964 studio album by Frank Sinatra", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "ENTITY SEARCH: Academy Awards" }, { + "chatId": 0, + "name": "system", "content": "ID: Q19020, label: Academy Awards, description: annual awards for cinematic achievements\nID: Q16913666, label: Academy Awards ceremony, description: annual event at which Academy Awards are presented\nID: Q83532676, label: Academy awards, description: scientific article published on 01 February 1968\nID: Q73105727, label: Academy Awards Database, description: database about Academy Award winners and nominées\nID: Q51954858, label: The animation Showcase - Best Of 2017, description: Best animated Short films, Oscars predictive screening for the 90th Academy Awards Ceremony.", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "PROPERTIES SEARCH: Q19020" }, { + "chatId": 0, + "name": "system", "content": "ID: P1296, label: Gran Enciclopèdia Catalana ID (former scheme), description: identifier for an item in the Gran Enciclopèdia Catalana. Replaced with \"Gran Enciclopèdia Catalana ID (P12385)\".\nID: P1368, label: National Library of Latvia ID, description: identifier assigned by the National Library of Latvia\nID: P1417, label: Encyclopædia Britannica Online ID, description: identifier for an article in the online version of Encyclopædia Britannica\nID: P345, label: IMDb ID, description: identifier for the IMDb [with prefix 'tt', 'nm', 'co', 'ev', 'ch' or 'ni']\nID: P2013, label: Facebook username, description: identifier for an official (preferably) Facebook person, product or organization page (everything that follows URL part 'https://www.facebook.com/')\nID: P2347, label: YSO ID, description: identifier for a concept in the General Finnish Ontology YSO\nID: P373, label: Commons category, description: name of the Wikimedia Commons category containing files related to this item (without the prefix \"Category:\")\nID: P2003, label: Instagram username, description: item's username on Instagram\nID: P527, label: has part(s), description: part of this subject; inverse property of \"part of\" (P361). See also \"has parts of the class\" (P2670).\nID: P279, label: subclass of, description: this item is a subclass (subset) of that item; all instances of this item are instances of that item; different from P31 (instance of), e.g.: K2 is an instance of mountain; volcano is a subclass of mountain (and an instance of volcanic landform)\nID: P1343, label: described by source, description: work where this item is described\nID: P910, label: topic's main category, description: main Wikimedia category\nID: P691, label: NL CR AUT ID, description: identifier in the Czech National Authority Database of National Library of the Czech Republic (NL CR)\nID: P269, label: IdRef ID, description: identifier for authority control in the French collaborative library catalog (see also P1025). Format: 8 digits followed by a digit or \"X\"\nID: P935, label: Commons gallery, description: name of the Wikimedia Commons gallery page(s) related to this item (is suitable to allow multiple links to more gallery pages)\nID: P646, label: Freebase ID, description: identifier for a page in the Freebase database. Format: \"/m/0\" followed by 2 to 7 characters. For IDs starting with \"/g/\", use Google Knowledge Graph ID (P2671)\nID: P571, label: inception, description: time when an entity begins to exist; for date of official opening use P1619\nID: P2163, label: FAST ID, description: authority control identifier in WorldCat's “FAST Linked Data” authority file\nID: P1889, label: different from, description: item that is different from another item, with which it may be confused\nID: P1407, label: MusicBrainz series ID, description: identifier for a series per the MusicBrainz open music encyclopedia\nID: P1424, label: topic's main template, description: the main template relating to a topic\nID: P2397, label: YouTube channel ID, description: ID of the YouTube channel of a person or organisation (not to be confused with the name of the channel) The ID can also be used for music.youtube.com IDs\nID: P2002, label: X username, description: this item's username on X (formerly Twitter); do not include the “@” symbol\nID: P2517, label: category for recipients of this award, description: link to Wikimedia category for recipients of this award\nID: P268, label: Bibliothèque nationale de France ID, description: identifier for the subject issued by BNF (Bibliothèque nationale de France). Format: 8 digits followed by a check-digit or letter, do not include the initial 'cb'.\nID: P856, label: official website, description: URL of the official page of an item (current or former). Usage: If a listed URL no longer points to the official website, do not remove it, but see the \"Hijacked or dead websites\" section of the Talk page\nID: P1027, label: conferred by, description: person or organization who grants an award, certification, grant, or role\nID: P349, label: NDL Authority ID, description: identifier for authority control per the National Diet Library of Japan\nID: P1225, label: U.S. National Archives Identifier, description: identifier for the United States National Archives and Records Administration's online catalog\nID: P1705, label: native label, description: label for the items in their official language (P37) or their original language (P364)\nID: P31, label: instance of, description: that class of which this subject is a particular example and member; different from P279 (subclass of); for example: K2 is an instance of mountain; volcano is a subclass of mountain (and an instance of volcanic landform)\nID: P159, label: headquarters location, description: city or town, where an organization's headquarters is or has been situated. Use P276 qualifier for specific building\nID: P244, label: Library of Congress authority ID, description: Library of Congress name authority (persons, families, corporate bodies, events, places, works and expressions) and subject authority identifier [Format: 1-2 specific letters followed by 8-10 digits (see regex). For manifestations, use P1144]\nID: P17, label: country, description: sovereign state that this item is in (not to be used for human beings)\nID: P227, label: GND ID, description: identifier from an international authority file of names, subjects, and organizations (please don't use type n = name, disambiguation) - Deutsche Nationalbibliothek\nID: P4013, label: Giphy username, description: this item's username on Giphy\nID: P12384, label: Letterboxd user ID, description: identifier for a user on Letterboxd\nID: P2910, label: icon, description: pictogram suitable to represent the item. For logos of a subject, use \"logo image\" (P154); for favicons, use \"small logo or icon\" (P8972)\nID: P9100, label: GitHub topic, description: GitHub topic for a repository or subject\nID: P12399, label: TheTVDB award ID, description: identifier for an award on the website TheTVDB.com\nID: P9629, label: Armeniapedia ID, description: identifier for a topic in the online encyclopedia Armeniapedia\nID: P6058, label: Larousse ID, description: identifier for a subject on the 'Encyclopédie Larousse'\nID: P6181, label: Disney A to Z ID, description: ID of article in online version of Disney A to Z\nID: P4342, label: Store norske leksikon ID, description: identifier of an article in the online encyclopedia snl.no\nID: P6449, label: Douban site name, description: domain name of Douban site written in Latin alphabet\nID: P6385, label: Krugosvet article, description: link to article of Russian-language online encyclopedia\nID: P10234, label: Der Spiegel topic ID, description: identifier for topics in the German news portal \"Der Spiegel\"\nID: P6760, label: Know Your Meme ID, description: identifier for a Know Your Meme article\nID: P10565, label: Encyclopedia of China (Third Edition) ID, description: identifier for an article in the online version of Encyclopedia of China (Third Edition)\nID: P8189, label: National Library of Israel J9U ID, description: identifier used by the National Library of Israel\nID: P4073, label: Fandom wiki ID, description: identifier of a topic's wiki, in Fandom.com\nID: P2924, label: Great Russian Encyclopedia Online ID (old version), description: identifier for an entry on old.bigenc.ru, the official site of the Great Russian Encyclopedia Online 2014–2017 (current version of bigenc.ru is P11514)\nID: P8309, label: Yle topic ID, description: identifier for topics in Finland's national broadcaster Yle's web services\nID: P4622, label: trophy awarded, description: trophy awarded at the end of a selection process or of a competition, usually to winners or finishers under the form of a cup, a medal, a diploma\nID: P3479, label: Omni topic ID, description: identifier for a topic, used by Omni and Aftonbladet\nID: P9545, label: Encyclopedia of China (Second Edition) ID, description: identifier for an article in the online version of Encyclopedia of China (Second Edition)\nID: P5337, label: Google News topics ID, description: identifier for a subject in the news on Google News\nID: P9084, label: ABC News topic ID, description: identifier of a topic of content on the Australian Broadcasting Corporation website\nID: P7982, label: Hrvatska enciklopedija ID, description: identifier for an article in the Croatian Encyclopedia (Hrvatska enciklopedija)\nID: P10045, label: Vokrug.tv show ID, description: identify for a creative work in Vokrug.tv\nID: P12385, label: Gran Enciclopèdia Catalana ID, description: identifier for an item in the Gran Enciclopèdia Catalana\nID: P5905, label: Comic Vine ID, description: identifier at the Comic Vine database of comic books, fictional characters, people, films and television series/episodes\nID: P8295, label: AustLit ID, description: identifier at AustLit\nID: P8313, label: Den Store Danske ID, description: identifier of an article in the online encyclopedia denstoredanske.lex.dk\nID: P8349, label: Proleksis enciklopedija ID, description: identifier for a topic in Proleksis enciklopedija\nID: P12596, label: museum-digital tag ID, description: numeric identifier for keywords used in the description of cultural heritage objects in Museum-Digital\nID: P10170, label: Channel One Russia show ID, description: identifier of TV program for Channel One Russia\nID: P9318, label: Ávvir topic ID, description: identifier of a topic in the Northern Sámi publication Ávvir\nID: P2581, label: BabelNet ID, description: ID in BabelNet encyclopedic dictionary\nID: P7305, label: Online PWN Encyclopedia ID, description: identifier for an entry in the online release of the Online PWN Encyclopedia\nID: P6219, label: TASS reference, description: background information on historical and current events, locations, biographies of famous people\nID: P8814, label: WordNet 3.1 Synset ID, description: Synset identifier in Princeton’s WordNet Version 3.1\nID: P3569, label: Cultureel Woordenboek ID, description: identifier for a concept in the Dutch Cultureel Woordenboek ('Cultural Dictionary')\nID: P6467, label: Hulu series ID, description: TV series identifier in Hulu\nID: P4515, label: Prisma ID, description: identifier for a film (movie) or person, in prisma.de\nID: P6200, label: BBC News topic ID, description: identifier for a topic on the BBC News website\nID: P7775, label: RationalWiki ID, description: identifier for an item at RationalWiki\nID: P3221, label: New York Times topic ID, description: identifier for a topic, at the New York Times' website\nID: P3417, label: Quora topic ID, description: identifier for a topic on Quora (English language version)\nID: P3509, label: Dagens Nyheter topic ID, description: identifier for a topic, used by the Swedish daily newspaper Dagens Nyheter\nID: P2888, label: exact match, description: URL used to link two items or properties, indicating a high degree of confidence that the concepts can be used interchangeably\nID: P5008, label: on focus list of Wikimedia project, description: property to indicate that an item is of particular interest for a Wikimedia project. This property does not add notability. Items should not be created with this property if they are not notable for Wikidata. See also P6104, P972, P2354.\nID: P5019, label: Brockhaus Enzyklopädie online ID, description: identifier for an article in the online version of Brockhaus Enzyklopädie\nID: P8408, label: KBpedia ID, description: identifier for the KBpedia knowledge graph, which provides consistent mappings across seven large-scale public knowledge bases including Wikidata, and is used to promote data interoperability and extraction of training sets for machine learning\nID: P11137, label: Reddit topic ID, description: identifier of a topic on Reddit\nID: P3222, label: NE.se ID, description: ID of article on the Swedish Nationalencyklopedin (NE.se) site\nID: P11408, label: Pixiv Encyclopedia ID, description: identifier for an article on Pixiv Encyclopedia\nID: P10916, label: Süddeutsche Zeitung topic ID, description: identifier for a topic at the Süddeutsche Zeitung newspaper website\nID: P5829, label: Television Academy Foundation show ID, description: identifier for a television show discussed on the Television Academy Foundation's The Interviews website\nID: P11196, label: Baidu Tieba name, description: name of a specific topic driven forum in Baidu Tieba\nID: P8687, label: social media followers, description: number of subscribers on a particular social media website (use as main statement only; see P3744 instead for qualifier). Qualify with \"point in time\" and property for account. For Twitter, use numeric id.\nID: P3553, label: Zhihu topic ID, description: numeric id of topics (tags) of questions on Zhihu, a Chinese question-and-answer website\nID: P3847, label: Open Library subject ID, description: identifier for a topic in the Open Library database\nID: P7502, label: Golden ID, description: ID page in Golden knowledge base\nID: P6081, label: RIA Novosti reference, description: background information on historical and current events, biographies of famous people", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "ENTITY SEARCH: director" }, { + "chatId": 0, + "name": "system", "content": "ID: Q2526255, label: film director, description: person who directs a film\nID: Q3455803, label: director, description: director of a creative work\nID: Q3387717, label: theatrical director, description: person overseeing the mounting of a theatre production\nID: Q1162163, label: director, description: person who leads a particular area of a company or organization\nID: Q2824523, label: board member, description: position in an organization", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "STOP" }, { + "chatId": 0, + "name": "system", "content": "You are an expert at generating SPARQL queries for the Wikidata Knowledge Graph from natural language. \nEntity IDs are prepended with 'wd' and property IDs are prepended with 'wdt'. \nYour task is to convert the natural language instruction into a SPARQL query.\nThe following are four examples in which I am showcasing a natural language instruction (NLI) and the converted SPARQL Query. \n NLI: Who are creators of Apple and what are their birthdates?\n SPARQL Query:\n SELECT ?founder ?founderLabel ?birthdate\n WHERE {\n wd:Q312 wdt:P112 ?founder. # Q312 represents Apple and P112 represents founder\n ?founder wdt:P569 ?birthdate. # P569 represents date of birth\n \n SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". }\n }\n NLI: Who are the current heads of state for all countries in the world? \n SPARQL Query: \n SELECT ?country ?countryLabel ?headOfState ?headOfStateLabel \n WHERE { \n ?country wdt:P31 wd:Q6256; # Instance of: country \n p:P35 ?statement. # has head of government statement \n ?statement ps:P35 ?headOfState; # head of government property \n pq:P580 ?startDate. # start date of the term \n FILTER NOT EXISTS { ?statement pq:P582 ?endDate } # Ensure current head of state \n SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". } \n } \n ORDER BY ?countryLabel \n NLI: What are the top five tallest mountains in the world and their respective heights? \n SPARQL Query: \n SELECT ?mountain ?mountainLabel ?height \n WHERE { \n ?mountain wdt:P31 wd:Q8502; # Instance of: mountain \n wdt:P2044 ?height. # Height property \n FILTER (?height >= 8000) # Minimum height of 8000 meters \n SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". } \n } \n ORDER BY DESC(?height) \n LIMIT 5 \n NLI: Which symphonies were composed by Ludwig van Beethoven? \n SPARQL Query: \n SELECT ?composition (SAMPLE(?compositionLabel) as ?compositionLabel) \n WHERE { \n ?composition wdt:P31 wd:Q105543609; # Instance of: Beethoven's symphonies \n wdt:P86 wd:Q255; # Composer: Ludwig van Beethoven \n rdfs:label ?compositionLabel. \n FILTER(CONTAINS(LCASE(?compositionLabel), \"symphony\")) \n SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". } \n } \n GROUP BY ?composition \n Start the SPARQL query with ```sparql and end the query with ```. After you generate a SPARQL query, you briefly explain, as concisely as possible, to the user why the query addresses their original question. Keep your explanation as short as possible and only further explain when asked. Now construct a query that answers the user's question: Between 2022 and 2024, which movies won the Academy Award for Best Picture? Also tell me who was the movie director, and when it won the award.", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "```sparql\nSELECT ?movie ?movieLabel ?director ?directorLabel ?awardDate\nWHERE {\n ?movie p:P166 ?statement. # P166 is the property for 'award received'\n ?statement ps:P166 wd:Q102427; # Q102427 represents 'Academy Award for Best Picture'\n pq:P585 ?awardDate. # P585 is the property for 'point in time'\n ?movie wdt:P57 ?director. # P57 is the property for 'director'\n \n FILTER(YEAR(?awardDate) >= 2022 && YEAR(?awardDate) <= 2024)\n \n SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". }\n}\nORDER BY ?awardDate\n```\nThis query fetches movies that won the Academy Award for Best Picture between 2022 and 2024, including each movie's director and the date when the award was won. It filters the awards by the given years and orders the results by the date when the award was received." }, { + "chatId": 0, + "name": "system", "content": "Respond with a brief name for this query. If you generated this query, it can just be the question that the user asked.\n SELECT ?movie ?movieLabel ?director ?directorLabel ?awardDate\nWHERE {\n ?movie p:P166 ?statement. # P166 is the property for 'award received'\n ?statement ps:P166 wd:Q102427; # Q102427 represents 'Academy Award for Best Picture'\n pq:P585 ?awardDate. # P585 is the property for 'point in time'\n ?movie wdt:P57 ?director. # P57 is the property for 'director'\n \n FILTER(YEAR(?awardDate) >= 2022 && YEAR(?awardDate) <= 2024)\n \n SERVICE wikibase:label { bd:serviceParam wikibase:language \"[AUTO_LANGUAGE],en\". }\n}\nORDER BY ?awardDate", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "Academy Award for Best Picture winners (2022-2024) with directors and award dates" }, { + "chatId": 0, + "name": "system", "content": "These are the JSON results from the last query. Respond with a brief summary of the results.\n {\n \"head\": {\n \"vars\": [\n \"movie\",\n \"movieLabel\",\n \"director\",\n \"directorLabel\",\n \"awardDate\"\n ]\n },\n \"results\": {\n \"bindings\": [\n {\n \"movie\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q104686893\"\n },\n \"director\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q7506788\"\n },\n \"movieLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"CODA\"\n },\n \"directorLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"Siân Héder\"\n },\n \"awardDate\": {\n \"datatype\": \"http://www.w3.org/2001/XMLSchema#dateTime\",\n \"type\": \"literal\",\n \"value\": \"2022-03-27T00:00:00Z\"\n }\n },\n {\n \"movie\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q83808444\"\n },\n \"director\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q28746830\"\n },\n \"movieLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"Everything Everywhere All at Once\"\n },\n \"directorLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"Dan Kwan\"\n },\n \"awardDate\": {\n \"datatype\": \"http://www.w3.org/2001/XMLSchema#dateTime\",\n \"type\": \"literal\",\n \"value\": \"2023-01-01T00:00:00Z\"\n }\n },\n {\n \"movie\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q83808444\"\n },\n \"director\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q28746848\"\n },\n \"movieLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"Everything Everywhere All at Once\"\n },\n \"directorLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"Daniel Scheinert\"\n },\n \"awardDate\": {\n \"datatype\": \"http://www.w3.org/2001/XMLSchema#dateTime\",\n \"type\": \"literal\",\n \"value\": \"2023-01-01T00:00:00Z\"\n }\n },\n {\n \"movie\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q108839994\"\n },\n \"director\": {\n \"type\": \"uri\",\n \"value\": \"http://www.wikidata.org/entity/Q25191\"\n },\n \"movieLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"Oppenheimer\"\n },\n \"directorLabel\": {\n \"xml:lang\": \"en\",\n \"type\": \"literal\",\n \"value\": \"Christopher Nolan\"\n },\n \"awardDate\": {\n \"datatype\": \"http://www.w3.org/2001/XMLSchema#dateTime\",\n \"type\": \"literal\",\n \"value\": \"2024-03-10T00:00:00Z\"\n }\n }\n ]\n }\n}", "role": "system" }, { + "chatId": 0, + "name": "gpt-4-turbo-preview", "role": "assistant", "content": "The Academy Award for Best Picture between 2022 and 2024 was won by:\n\n1. \"CODA\" directed by Siân Héder, which won the award on March 27, 2022.\n2. \"Everything Everywhere All at Once\" with directors Dan Kwan and Daniel Scheinert, both awarded on January 1, 2023. It's listed twice because there are two directors.\n3. \"Oppenheimer\" directed by Christopher Nolan, which won the award on March 10, 2024." } diff --git a/src/utils/graphin.ts b/src/utils/graphin.ts index 39032df..add518b 100644 --- a/src/utils/graphin.ts +++ b/src/utils/graphin.ts @@ -1,7 +1,9 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import {IUserEdge, IUserNode} from "@antv/graphin"; -import {SemanticTriple} from "../types/semanticTypes.ts"; + +import {SemanticTriple} from "types/semanticTypes.ts"; + import {SPARQLItemType} from "./transformTripleDataToGraphin.ts"; const getColor = (itemType: SPARQLItemType) => { diff --git a/src/utils/knowledgeBase/formatURI.ts b/src/utils/knowledgeBase/formatURI.ts new file mode 100644 index 0000000..59e11ea --- /dev/null +++ b/src/utils/knowledgeBase/formatURI.ts @@ -0,0 +1,20 @@ +// Copyright (c) 2024 Massachusetts Institute of Technology +// SPDX-License-Identifier: MIT + +/** + * This function is used to format a URI for rendering in the results table + * @param uri the URI from query results + * @returns what we want to render as the content of an anchor tag + */ +export function formatURI(uri:string) { + return uri.replace("http://www.wikidata.org/","") +} + +/** + * This function is used to get the href to redirect to from the URI + * @param uri the URI from query results + * @returns what we want to set as the href of an anchor tag + */ +export function getHrefFromURI(uri:string) { + return uri +} \ No newline at end of file diff --git a/src/utils/knowledgeBase/fuzzySearch.ts b/src/utils/knowledgeBase/fuzzySearch.ts index f7adb90..9d416df 100644 --- a/src/utils/knowledgeBase/fuzzySearch.ts +++ b/src/utils/knowledgeBase/fuzzySearch.ts @@ -1,9 +1,11 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import { SearchResponse } from "wikibase-sdk" -import { handleFetchJsonResponse } from "../handleFetchJsonResponse" import { wbk } from "./wbk" +import { handleFetchJsonResponse } from "utils/handleFetchJsonResponse" + + /** * This function fuzzy searches Wikidata for entities by label name. * This fuzzy search feature is implemented by Wikidata, not us diff --git a/src/utils/knowledgeBase/getEntityData.ts b/src/utils/knowledgeBase/getEntityData.ts index c58b1d4..5f67d64 100644 --- a/src/utils/knowledgeBase/getEntityData.ts +++ b/src/utils/knowledgeBase/getEntityData.ts @@ -1,10 +1,12 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT import { EntityId, Item } from "wikibase-sdk"; -import { handleFetchJsonResponse } from "../handleFetchJsonResponse.ts"; import { wbk } from "./wbk.ts"; import {useQuery, UseQueryResult} from "@tanstack/react-query"; -import { IDTableEntitiesType } from "../../types/idTable.ts"; + +import { handleFetchJsonResponse } from "utils/handleFetchJsonResponse.ts"; + +import { IDTableEntitiesType } from "types/idTable.ts"; interface EntityDictionary { diff --git a/src/utils/knowledgeBase/runQuery.ts b/src/utils/knowledgeBase/runQuery.ts index 94588b1..4e71e67 100644 --- a/src/utils/knowledgeBase/runQuery.ts +++ b/src/utils/knowledgeBase/runQuery.ts @@ -1,7 +1,8 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { SparqlResultsJsonType } from "../../types/sparql"; -import { handleFetchJsonResponse } from "../handleFetchJsonResponse"; +import { handleFetchJsonResponse } from "utils/handleFetchJsonResponse"; + +import { SparqlResultsJsonType } from "types/sparql"; /** * This function runs a SPARQL query on Wikidata diff --git a/src/utils/parseSparqlQuery.ts b/src/utils/parseSparqlQuery.ts index 607a404..d2b4ba1 100644 --- a/src/utils/parseSparqlQuery.ts +++ b/src/utils/parseSparqlQuery.ts @@ -2,7 +2,8 @@ // SPDX-License-Identifier: MIT import SparqlJs, { BgpPattern, SelectQuery } from "sparqljs"; -import {SemanticTriple} from "../types/semanticTypes.ts"; + +import {SemanticTriple} from "types/semanticTypes.ts"; const PREFIXES = `PREFIX bd: PREFIX cc: diff --git a/src/utils/summarizeQueryResults.ts b/src/utils/summarizeQueryResults.ts index 3cbf0ac..c61362e 100644 --- a/src/utils/summarizeQueryResults.ts +++ b/src/utils/summarizeQueryResults.ts @@ -1,6 +1,7 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import { SparqlResultsJsonType } from "../types/sparql"; +import { SparqlResultsJsonType } from "types/sparql"; + import { ChatGPTAPI } from "./ChatGPTAPI"; import { getEntityDataFromQuery } from "./knowledgeBase/getEntityData"; diff --git a/src/utils/transformTripleDataToGraphin.ts b/src/utils/transformTripleDataToGraphin.ts index 40fad47..168b1b9 100644 --- a/src/utils/transformTripleDataToGraphin.ts +++ b/src/utils/transformTripleDataToGraphin.ts @@ -1,10 +1,11 @@ // Copyright (c) 2024 Massachusetts Institute of Technology // SPDX-License-Identifier: MIT -import {SemanticTriple} from "../types/semanticTypes.ts"; import {GraphinData, Utils} from "@antv/graphin"; import {createEdge, createNode, parseNameFromWikidataUrl} from "./graphin.ts"; -import { IDTableEntitiesType } from "../types/idTable.ts"; + +import { IDTableEntitiesType } from "types/idTable.ts"; +import {SemanticTriple} from "types/semanticTypes.ts"; export enum SPARQLItemType { Term = "Term", diff --git a/tsconfig.json b/tsconfig.json index 2284c94..be31090 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,7 +21,9 @@ "noFallthroughCasesInSwitch": true, "typeRoots": [ "./node_modules/sparqljs-legacy-type/" - ] + ], + + "baseUrl": "src/" }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }] diff --git a/vite.config.ts b/vite.config.ts index 420e64e..3139630 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -3,13 +3,14 @@ import { defineConfig } from 'vite' import react from '@vitejs/plugin-react-swc' import commonjs from 'vite-plugin-commonjs' +import tsconfigPaths from 'vite-tsconfig-paths' // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react(), commonjs()], + plugins: [react(), commonjs(), tsconfigPaths()], base: process.env.GITHUB_PAGES==="true" ? "/linkq" : "", build: { commonjsOptions: { transformMixedEsModules: true }, outDir: "./build", - } + }, })