Research Assistant
Inspiration
The inspiration for this project came from the desire to streamline the research process by leveraging the power of modern AI and knowledge graph technologies. Researchers often spend countless hours searching for relevant information across various sources, struggling to connect the dots between disparate pieces of information, and manually organizing their findings. This project aims to alleviate these pain points by creating an intelligent research assistant that can automate information retrieval, perform semantic searches, and store knowledge in a structured way.
What it does
The Research Assistant is a powerful tool designed to help users find and organize information more efficiently. It combines the capabilities of a language model, web search engines, a specialized academic paper database (Arxiv), and a Neo4j graph database to provide a comprehensive research experience.
Key Features:
- Conversational Interface: Users can interact with the assistant using natural language, asking questions and giving instructions in a conversational manner.
- Multiple Search Tools: The assistant can utilize multiple search tools to find information:
- DuckDuckGo: Performs general web searches using the DuckDuckGo search engine.
- Arxiv: Searches the Arxiv database for academic papers based on keywords and categories.
- Neo4j Graph Database: Stores and retrieves information from a knowledge graph, enabling semantic searches and relationship-based queries.
- Agentic Behavior: The assistant intelligently decides which tool to use based on the user's query and the context of the conversation. It can also combine results from multiple tools to provide a more comprehensive answer.
- Automated Information Retrieval: The assistant automates the process of finding relevant information, saving users time and effort.
- Knowledge Graph Integration: The assistant can store information from research papers (including titles, authors, summaries, categories, and text chunks) in a Neo4j graph database, creating a structured knowledge base.
- Contextual Awareness: The assistant maintains a history of the conversation, allowing it to understand the context of the user's queries and provide more relevant responses.
- LLM Integration: The assistant can use an underlying Language Model (LLM) to generate more refined answers by combining and summarizing information from various sources.
How we built it
The Research Assistant project is built using a combination of technologies and programming languages:
1. Go Backend (Modus):
- Modus Framework: The core backend is built using the Modus framework, which provides a convenient way to create serverless applications in Go.
- Go Programming Language: The primary backend logic is implemented in Go, leveraging its performance and concurrency features.
- Modus SDK: The Go code interacts with the Modus runtime environment, models (LLMs and embedding models), and external services (Neo4j) through the Modus SDK.
- HTTP Requests: The Go code makes HTTP requests to the Python API to perform web searches and interact with the Arxiv database.
- Neo4j Integration: The Go code uses the
neo4jpackage from the Modus SDK to interact with the Neo4j graph database, creating indexes, storing data, and performing queries. - OpenAI/Gemini Models: The Go code utilizes the Modus SDK's model APIs to interact with OpenAI and Gemini models for embedding and chat completion tasks.
2. Python API (Flask):
- Flask Web Framework: A simple Python API is built using Flask to handle requests from the Go backend.
-
duckduckgo_searchLibrary: This library is used to perform web searches on DuckDuckGo. -
arxivLibrary: This library is used to search and retrieve data from the Arxiv.org API. -
llama_index: This library is used to extract text from pdf files, to get the text from the Arxiv papers. - HTTP Endpoints: The Python API exposes endpoints like
/fetch-duckduckgoand/fetch-arxivto handle search requests and/get-chunksto get text chunks from a paper, which are called by the Go backend.
3. Neo4j Graph Database:
- Data Storage: Neo4j is used to store information about research papers, categories, and authors in a graph structure.
- Full-Text Search (FTS) Indexes: FTS indexes are created on various properties (e.g.,
name,snippet,description,text) to enable efficient keyword-based searches. - Vector Indexes: Vector indexes are created using the
db.index.vector.queryNodesfunctionality to enable similarity searches based on embeddings. - Cypher Queries: The Go code uses Cypher queries to interact with Neo4j, including creating indexes, inserting data, and performing searches.
4. System Message:
- A detailed system message is defined to instruct the underlying LLM about its role as a research assistant, the tools it has available, and how to use them.
5. Agentic Behavior:
- The
querySystemfunction in the Go code implements the agentic logic, deciding which tool to use based on the user's query and the context of the conversation.
Workflow:
- The user interacts with the Modus application through the API explorer (GraphQL).
- The Go backend receives the user's query.
- The
querySystemfunction analyzes the query and decides which tool to use (DuckDuckGo, Arxiv, or Neo4j functions). - If necessary, the Go code makes HTTP requests to the Python API to perform searches or other operations.
- The Python API returns the results as JSON.
- The Go code processes the results, potentially combining information from multiple sources.
- The
querySystemfunction might then prompt an LLM to refine the answer further. - The final response is returned to the user through the API explorer.
Challenges we ran into
- Modus SDK Limitations: The Modus SDK had some limitations in terms of directly accessing environment variables and using certain Node.js libraries in AssemblyScript. We had to find workarounds, such as calling external APIs to handle tasks that couldn't be done directly in AssemblyScript.
- WASM Errors: We encountered "out of bounds memory access" errors in the WebAssembly runtime, which were challenging to debug. These were often related to how the Modus SDK handled JSON parsing and memory management.
-
JSON.stringifylimitations: TheJSON.stringifymethod did not work as intended in certain cases, and the request body did not get correctly serialized. - API Key Handling: Initially, we tried to pass API keys directly through environment variables, but that proved problematic. We had to switch to using Modus connections and secrets to manage API keys securely.
- Asynchronous Operations: Asynchronous operations and using
awaitin the AssemblyScript code required careful handling due to the limitations of the environment. - Porting Code: Porting code from AssemblyScript to Go, and then creating a hybrid Go-Python application, introduced complexities in terms of data structure compatibility and API design.
- Neo4j Index Creation: Dynamically creating Neo4j indexes with spaces in node names required escaping with backticks, which was not immediately obvious.
http.fetchbehavior: Thehttp.fetchmethod in the Modus SDK automatically serializes the response to JSON, which caused issues when the response was not a JSON object.- Error Handling: Implementing robust error handling across the Go and Python codebases and within the Modus runtime environment required careful consideration.
Accomplishments that we're proud of
- Successful Integration of Multiple Tools: We successfully integrated DuckDuckGo, Arxiv, and Neo4j into a single application, demonstrating the ability to combine different information sources.
- Agentic Behavior: We implemented a basic agentic system that can intelligently choose between different tools based on the user's query.
- Hybrid Go-Python Architecture: We created a working system that leverages both Go (for the Modus backend) and Python (for external API interactions and library usage), showcasing the flexibility of Modus.
- Dynamic Index Creation: We implemented dynamic creation of Neo4j indexes based on unique node names, demonstrating a good understanding of Neo4j's Cypher query language.
- Overcoming Modus SDK Limitations: We found workarounds for several limitations in the Modus SDK and AssemblyScript environment, demonstrating problem-solving skills and adaptability.
- End-to-End Functionality: We built a working prototype of a research assistant that can perform searches, retrieve information, and store data in a knowledge graph.
What we learned
- Modus SDK: We gained a deep understanding of the Modus SDK, its capabilities, and its limitations, particularly in the context of Go and WebAssembly.
- Go Programming: We honed our Go programming skills, including working with JSON, HTTP requests, concurrency, and error handling.
- Neo4j and Cypher: We learned how to use Neo4j, create indexes (both full-text and vector), and write Cypher queries to interact with the graph database.
- API Integration: We gained experience in integrating with external APIs (DuckDuckGo, Arxiv, and indirectly, Google Search via SerpApi) and handling their responses.
- Hybrid Architectures: We explored the challenges and benefits of building a hybrid application that combines different programming languages and technologies.
- Agentic Systems: We experimented with basic agentic design principles, implementing logic to choose the right tool for a given task.
- Error Handling in Complex Systems: We learned the importance of robust error handling when dealing with multiple interacting components and external services.
What's next for ResearchAssistant
Enhanced Agentic Capabilities:
- Improve the agent's decision-making logic using more sophisticated techniques (e.g., NLP, machine learning) to better understand user intent and choose the best tools.
- Implement a more robust system for evaluating and selecting the most relevant information from multiple sources.
- Allow the agent to learn from user feedback and improve its performance over time.
Improved LLM Integration:
- Integrate a Language Model (LLM) more deeply into the system to generate more refined and insightful answers, summaries, and reports.
- Use the LLM to generate more natural and human-like conversations.
Advanced Search and Filtering:
- Implement more advanced search and filtering options for Arxiv and Neo4j, allowing users to specify date ranges, authors, specific journals, and other criteria.
- Allow users to perform more complex graph queries on the Neo4j database.
User Interface:
- Develop a user-friendly interface (e.g., web, mobile) to make the research assistant more accessible and easier to use.
Scalability and Performance:
- Optimize the code for performance and scalability, especially for handling large datasets and complex queries.
- Explore ways to distribute the workload across multiple servers or instances.
Security:
- Implement more robust security measures, especially for handling API keys and user data.
- Consider using a more secure method for storing and accessing Neo4j credentials.
Knowledge Graph Expansion:
- Expand the knowledge graph to include other sources of information beyond Arxiv.
- Implement features to automatically extract and link entities, relationships, and concepts from new data sources.
Personalization:
- Allow users to create profiles and customize their research experience.
- Implement features to track user interests and preferences, and tailor search results accordingly.
Collaboration:
- Enable collaboration features, allowing multiple users to share information and work on research projects together.
By pursuing these next steps, the Research Assistant can evolve into a truly powerful and indispensable tool for researchers across various disciplines.

Log in or sign up for Devpost to join the conversation.