Visit the Website: https://ginkgo-p.onrender.com/
In order to visualize a graph generated by your algorithms on your own environment, simply copy paste valid JSON to Ginkgo-P through the Quick Start option. It must follow this example in order to be visualized:
{
"highlighted_path": [ //this represents a list of links to be highlighted (could be empty too)
{
"source": "1",
"type": "isLocatedIn",
"target": "2"
},
{
"source": "1",
"type": "happenedIn",
"target": "3"
}
],
"highlighted_nodes": [
{
"id": "1",
"name": "Hawaii"
}
],
"graph": {
"nodes": [
{
"id": "1",
"name": "Hawaii"
},
{
"id": "2",
"name": "Hawaii_State_Capitol"
},
{
"id": "3",
"name": "Black_Week_(Hawaii)"
},
{
"id": "4",
"name": "Aloha_Stadium"
}
],
"links": [
{
"source": "1",
"type": "isLocatedIn",
"target": "2"
},
{
"source": "1",
"type": "happenedIn",
"target": "3"
},
{
"source": "1",
"type": "isLocatedIn",
"target": "4"
},
{
"source": "4",
"type": "contains",
"target": "3"
}
]
}
}
See here for an example of how this JSON can be filled out.
To launch locally, first download NodeJS from here. Ensure you have the latest version of NodeJS that this project supports. At the time of writing, it is 8.19.2. Test that NodeJS is installed correctly with npm --v
to check the version.
Then, run npm ci
in the root project folder to install all necessary node packages (npm clean install). cd
into ginkgo_backend
and ginkgo_frontend
and do the run npm ci
again in each directory.
We need to now create a MongoDB account to cache queries and their results in a database. Reference this resource to get a MongoDB Connection String in URI Format. Once you have this string, create a .env
file in /ginkgo_backend
and enter MONGODB_URI=<your MongoDB URI string here>
to set that environment variable. Ensure that the IP Addresses that are using/deploying your app are denoted inside your database's Network Access settings. If you wish to allow any IP address to connect to your MongoDB database, set this to be 0.0.0.0/0.0.0
. See this resource for more information.
Additionally, you will need to set your default target for your frontend to send API requests to. If you wish to set it to be localhost and at port 8080, create a .env
file in /ginkgo_frontend
and enter REACT_APP_DEFAULT_BACKEND=http://localhost:8080
.
To run on your local machine, enter 'npm run dev' from the root directory. This will run both the frontend and backend on their development scripts as defined in their respective package.json.
You will need to set environment variables to run this platform. See getting_started_with_ginkgo-p/README.md
for more details and some example inputs.
To deploy, we recommend an infrastructure as a service (IaaS) service such as Render. Follow a tutorial such as this to familiarize yourself with how to deploy a MERN stack app to Render.
First, write and test an algorithm and add it to /ginkgo_backend/algorithm_scripts/ (you can access data and add new data to the /ginkgo_backend/datasets folder). Then, add the title of the script and its language initializer to /ginkgo_backend/algorithm_scripts. (E.g. test_script.py
and python
since I would run python test_script.py
in my terminal.)
The frontend must specific two things in the body of its API request to the backend:
- "language": a string specifying which language the script is written in (written down as the string that is a part of the call)
- "script": a string that is the file name of the script in
/ginkgo_backend/algorithm_scripts
to run
However, the frontend can add more objects to the API call to be used in running the script. In fact, this is encouraged.
Test your new algorithm using a resource such as Postman sending data to the API in the form of a body like so:
{
"language": "python3",
"script": "test_script.py",
"arg1": "My test query to see",
"arg2": "if my test script is running properly!"
}
By sending a POST request with this body, the backend will run python test_script.py
with parameters "My test query to see"
and "if my test script is running properly!"
. If you make the above request, you should expect back the following json:
{
"message": "some helpful logging",
"algocall_result": {
"script": "test_script.py",
"language": "python3",
"result": "My test query to see\nif my test script is running properly!\n",
"_id": "a randomly generated id to be used as a unique identifier in MongoDB"
}
}
If you get back a response as expected, then your algorithm is implemented properly. Check out NodeJS documentation for more resources on how to interact with a NodeJS child process. Two noteworthy hints are that data can be passed to a script via sys argvs
in Python and to receive data from the script, simply print
it in Python. Check out /ginkgo_backend/algorithm_scripts/test_script.py
to see what we mean.
Go to /ginkgo_frontend/src/components/App/App.js
and uncomment line {/* <Route path="Example" element={<ExampleCategory />} /> */}
. Then navigate to insert_website_url/Example
to display the component.
Check out /ginkgo_frontend/src/components/ExampleCategory
folder to see how to create a category (for a task such as question answering) of algorithms. Specifically, check out ExampleTab1
in the folder for an example of how to create a form component. Check out ExampleTab2
in the folder for an example of how a hardcoded result would be displayed using d3.
If you wish to add a new algorithm that returns an interactive d3 graph as shown in ExampleTab2
, make sure your component makes a request to the API which must return a JSON object in this form:
{
"message": "...some logging message",
"algocall_result": {
"script": "...name of your script",
"language": "...language of your script",
"result": "VERY IMPORTANT GRAPH REPRESENTATION"
}
}
where VERY IMPORTANT GRAPH REPRESENTATION
is a collection of <head, relation, tail>
relationships which define a graph. See below for an example of how the representation must be returned from your script:
{
"status": "..return some status here (we use `Good` or `Bad` depending on your custom algorithm and error handling)",
"highlighted_path": [ //this represents a list of links to be highlighted if you wish to
{
"source": "1",
"type": "isLocatedIn",
"target": "2"
},
{
"source": "1",
"type": "happenedIn",
"target": "3"
}
],
"graph": {
"nodes": [
{
"id": "1",
"name": "Hawaii"
},
{
"id": "2",
"name": "Hawaii_State_Capitol"
},
{
"id": "3",
"name": "Black_Week_(Hawaii)"
},
{
"id": "4",
"name": "Aloha_Stadium"
}
],
"links": [
{
"source": "1",
"type": "isLocatedIn",
"target": "2"
},
{
"source": "1",
"type": "happenedIn",
"target": "3"
},
{
"source": "1",
"type": "isLocatedIn",
"target": "4"
},
{
"source": "4",
"type": "contains",
"target": "3"
},
]
}
}
If your script returns this type of JSON object, you are almost done!
First make a copy of /ginkgo_frontend/src/components/ExampleCategory
and place it in /ginkgo_frontend/src/components
. To add it to the frontend, we must add it to our main App.js.
Navigate to /ginkgo_frontend/src/components/App/App.js
and edit the return function to be like this:
return (
<>
<div className="App">
<div>
<NavBar />
<Routes>
<Route path="/" element={<HomePage />} />
{/* <Route path="Example" element={<ExampleCategory />} /> */}
<Route path="...insert your path" element={<YourExampleCategoryCopy />}/>
<Route path="multihopreasoning" />
<Route path="pointwisereasoning" />
<Route path="kgcompletion" element={<KGCompletionCategory />} />
<Route path="kgquestionanswering" />
</Routes>
</div>
<Particles id="tsparticles" />
</div>
</>
);
Now we add it to our NavBar (/ginkgo_frontend/src/components/NavBar/NavBar.js
) and add a new <li>
element like so:
<li>
<Link to="kgquestionanswering" className="text-purple-500">
KG Question Answering
</Link>
</li>
<li>
<Link to="multihopreasoning" className="text-purple-500">
Multi-Hop Reasoning
</Link>
</li>
<li>
<Link to="pointwisereasoning" className="text-purple-500">
Node Recommendation
</Link>
</li>
<li>
<Link to="...insert your path from App.js" className="text-purple-500">
Your Example Category Copy
</Link>
</li>
Finally, we are ready to customize our ExampleTab2Copy
file. In your new copy, we must edit the POST request to our backend. Replace the following:
const params = {
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": JSON.stringify({
"language": "python3",
"script": "script1.py",
...data_sent
})
};
with
const params = {
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
"body": JSON.stringify({
"language": "...language of your script",
"script": "...name of your script",
...data_sent
})
};
and we're done! As long as your script does not require any parameters, you should see your interactive d3 graph as soon as you submit any string in the "Query" field!
If your script does require parameters (most do), you must either specify it hardcoded in the POST request body via params
above or you must edit the rest of ExampleTab2Copy
like so for an example parameter:
For Form Validation:
//check out yup form validation here: https://www.sanity.io/guides/form-validation-with-npm-yup
const schema = yup.object().shape({
// language: yup.string().required(),
// script: yup.string().required(),
query: yup.string().required()
yourParamter: yup.insertYourDataType().required() // if your parameter isn't required but is optional, remove the last ".required()"
});
To add to your form:
// <p className="text-red-500 text-sm mt-2">
// A valid query is required.
// </p>
// )}
// </div>
<div className="mb-8">
<label
htmlFor="yourParameter"
className={`block font-bold text-sm mb-2 ${
errors.yourParameter ? "text-red-400" : "text-purple-500"
}`}
>
Your Parameter Label
</label>
<input
{...register("yourParameter")} //creates a register to label your user's input
type="text"
id="yourParameter"
placeholder="enter anything - this is to demo the example result"
autoComplete="off"
className={`block w-full bg-transparent outline-none border-b-2 py-2 px-4 placeholder-purple-300 focus:bg-purple-100 ${
errors.yourParameter
? "text-red-300 border-red-400"
: "text-purple-500 border-purple-400"
}`}
/>
{errors.yourParameter && (
<p className="text-red-500 text-sm mt-2">
Say something if your user doesn't input your Parameter correctly!
</p>
)}
</div>
Finally, test your new component by entering some test data and looking at your new beautiful interactive d3 graph!
- Material Tailwind
- DaisyUI
- Tailwind CSS
- Particles JS
- Postman
- React Query
- Example of Amazing React + Express project
- Examples of Routes and Controllers
- MongoDB REST Tutorial
- Managing NodeJS Child Processes
- MongoDB Cheatsheet
- Mongoose Tutorial
- Calling Python Script with NodeJS Express Server
- How to Access Return Value of a Promise
- How to Use Redis With Express and MongoDB/Mongoose