Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ wget -O data/neurips-2025-orals-posters.json https://neurips.cc/static/virtual/d
#### Build the knowledge graph
You can build the knowledge graph per your needs by running the following script:
```commandline
uv run llm_agents/tools/knowledge_graph/graph_generator.py \
uv run agentic_nav/tools/knowledge_graph/graph_generator.py \
--input-json-file data/neurips-2025-orals-posters.json \
--embedding-model $EMBEDDING_MODEL_NAME \
--ollama-server-url $EMBEDDING_MODEL_API_BASE \
Expand All @@ -144,14 +144,14 @@ knowledge graphs here (the "thresh" in the file name indicates the `similarity-t
#### Importing the knowledge graph to a neo4j database
We provide an importer to move the knowledge graph into a graph database that supports vector-based similarity search.
```commandline
uv run llm_agents/tools/knowledge_graph/neo4j_db_importer.py \
uv run agentic_nav/tools/knowledge_graph/neo4j_db_importer.py \
--graph-path graphs/knowledge_graph.pkl \
--neo4j-uri $NEO4J_DB_URI \
--batch-size 100 \
--embedding-dimension 768 # This must match the vector dims generated by the embedding model.
```
**Note:** Depending on what your graph looks like this can also take a while (> 20min for 6K papers). Also, beware that
running this script will first clear any existing entries before the new graph is written to the database.
**Note:** Depending on what your graph looks like this can also take a while (>15min for 6K papers). Also, beware that
running this script will first clear any existing database entries before the new graph is written to the database.


### Agent interactions
Expand Down
97 changes: 67 additions & 30 deletions agentic_nav/agents/neurips2025_conference.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,41 +24,78 @@
system = {
"role": "system",
"content": f"""
You are AgenticNAV, an assistant to navigate accepted papers at the NeurIPS 2025 conference.
You can assist users in finding papers based on their research interests, preferred dates, and time slots.
You can also build schedules for them to visit posters that they are interested in.

**Here are some guidelines**:
- When searching for similar papers, the search tool only takes paper titles and abstracts as input keywords; it cannot take anything else as the input keywords.
- When a user asks you to find papers or build a schedule for multiple topics or keywords, you can make multiple tool calls to the same tool for each topic/keyword.
- When you respond with a paper, include: Poster position (#), Paper title, Authors, Session time, OpenReview URL (if possible), and Virtual Site URL (if possible).
- It is ok to present only parts of the information in the previous bullet point, if some of the data is not available.
- When you include the session time, specify at which location the paper will be presented.
- Always separate papers by day, session, and location to make it easy for the user to read.
- When listing papers, make sure to order them by session details (i.e., date, time, location). Keep San Diego and Mexico City separate.
- The OpenReview (named "OpenReview" with URL reference) and Virtual Site (named "Conference Page" with URL reference) URLs should be in one table cell. The column name should be "Links".
- The paper title, author names, session, and time should be in one table cell. If possible, make the author names smaller.
- If there is a Virtual Site available, you need to prepend https://neurips.cc for the link to be usable (never mention this to the user).
- Make sure to present papers in a Markdown table. Do not wrap it inside html code.
- When building a schedule, do not specify the name of the day.
- The attribute `poster_position` (starting with #) is the physical location of a poster in the conference venue at a given session. It is unique per session but may appear multiple times across sessions.
- If you find the same paper title multiple times, remove the duplicate titles and do not mention it in your response.
- When a user asks for a conference map, respond with the link: https://media.neurips.cc/Conferences/NeurIPS2025/sdconvctr-ground-level.svg. You don't know any specifics about the venue.

**Important rule**: If you are unsure or cannot find the information requested by the user, say you don't know and cannot help, unfortunately.
You are AgenticNAV, an assistant to navigate accepted papers at the NeurIPS 2025 conference.
You can assist users in finding papers based on their research interests, preferred dates, and time slots.
You can also build schedules for them to visit presentations (both posters and oral sessions) that they are interested in.

**Search Guidelines**:
- The search tool only accepts paper titles and abstracts as input keywords
- For queries with multiple topics/keywords, make separate tool calls for each topic
- Always search for BOTH posters AND orals unless the user explicitly requests only one type

**Presentation Format Requirements**:

When presenting papers to users, you MUST include BOTH poster presentations AND oral presentations in separate sections:

1. **Structure**:
- Create separate sections for "Poster Presentations" and "Oral Presentations"
- Within each section, organize by conference day (one table per day)
- Keep San Diego and Mexico City locations separate
- Do not specify day names when building schedules

2. **Poster Table Format** (2 columns only):
- Column 1: Paper Details
- Paper title (bold)
- Authors (small letters)
- Session and poster position (e.g., "Session 3, Poster #142")
- Column 2: Links
- OpenReview URL
- Virtual Site URL (prepend https://neurips.cc)

3. **Oral Table Format** (2 columns only):
- Column 1: Paper Details
- Paper title (bold)
- Authors (small letters)
- Session and time slot
- Column 2: Links
- OpenReview URL
- Virtual Site URL (prepend https://neurips.cc)

4. **Technical Requirements**:
- Use Markdown tables only (no HTML)
- `poster_position` attribute (starting with #) indicates physical location, unique per session
- Include all available metadata for each paper

**Response Structure Template**:
Poster Presentations
[Day Name, Date]
[Markdown table with posters]
[Next Day Name, Date]
[Markdown table with posters]

**Timeline:**
- Tuesday, December 02, 2025: Panels and Tutorials only, no paper and poster presentations
- Wednesday, December 03, 2025: Poster Sessions in the Morning and Afternoon
- Thursday, December 04, 2025: Poster Sessions in the Morning and Afternoon
- Friday, December 05, 2025: Poster Sessions in the Morning and Afternoon
- Those are the only days with poster and oral sessions.

**Here is the current timestamp**: {datetime.now(ZoneInfo('America/Los_Angeles'))}. The conference is happening in San Diego, California.
Oral Presentations
[Day Name, Date]
[Markdown table with orals]
[Next Day Name, Date]
[Markdown table with orals]

**Conference Information**:
- Venue map: https://media.neurips.cc/Conferences/NeurIPS2025/sdconvctr-ground-level.svg
- Location: San Diego, California and Mexico City, Mexico
- Timeline:
- Tuesday, Dec 02, 2025: Panels and Tutorials only (no papers/posters)
- Wednesday, Dec 03, 2025: Poster and Oral Sessions (Morning & Afternoon)
- Thursday, Dec 04, 2025: Poster and Oral Sessions (Morning & Afternoon)
- Friday, Dec 05, 2025: Poster and Oral Sessions (Morning & Afternoon)

**Current timestamp**: {datetime.now(ZoneInfo('America/Los_Angeles'))}

**Important**: If you cannot find the requested information, clearly state that you don't know and cannot help with that specific request. Always proactively search for and present BOTH poster and oral presentations unless explicitly told otherwise.
"""
}



AGENT_INTRODUCTION_PROMPT = {
"role": "assistant",
"content": f"""
Expand Down
3 changes: 3 additions & 0 deletions agentic_nav/frontend/browser_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,9 @@ def main():
# 🤖 AgenticNAV - Planning your NeurIPS 2025 visit made effortless
This agent can help you explore the more than 5000 papers at this year's NeurIPS conference.
You can start chatting right away but we also offer options for customization (see tab "Guide & Settings").

**Note on Usability:** HuggingFace ZeroGPU quotas for users that are not logged in are very restrictive.
This is out of our control and may limit the utility of AgenticNAV.
""")

# Session state for agent instance, config, and messages
Expand Down
67 changes: 5 additions & 62 deletions agentic_nav/tools/knowledge_graph/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,64 +143,7 @@ def find_neighboring_papers(
min_similarity: float = 0.75
) -> str:
"""
Retrieve immediate neighboring entities of a specific paper from the Neo4j knowledge graph.

This function performs a one-hop neighborhood search to find entities directly connected to
a target paper. It is designed to be used after an initial similarity search when users want
to explore specific relationships (similar papers, authors, or topics) for a paper of interest.

Args:
paper_id (str): The unique identifier of the target paper node in the graph. neo4j UUID.
relationship_types (List[str], str): Types of relationships to query.
Defaults to ["SIMILAR_TO"].
Valid options: ["SIMILAR_TO", "IS_AUTHOR_OF", "BELONGS_TO_TOPIC"]
neighbor_entity (str, optional): The type of neighboring entity to return.
Defaults to "similar_papers".
Valid options: ["similar_papers", "authors", "topics", "raw_results"]
num_neighbors_to_return (int, optional): Maximum number of neighbors to return.
Defaults to 10. Results are randomly shuffled before truncation to provide diversity.
min_similarity (float, optional): Minimum similarity threshold for returned neighbors.

Returns:
str: A token-efficient formatted string representation of neighboring entities,
encoded using the toon_encode function.

Restrictions:
- Requires a running Neo4j database instance at bolt://localhost:7687 with credentials
(username: "neo4j", password: "llm_agents")
- Should be used after an initial similarity search as part of a focused exploration workflow
- The paper_id must exist in the Neo4j graph database
- Only performs one-hop searches (direct neighbors only)
- Only the three specified relationship types are supported
- Only the four specified neighbor entity types are supported
- The neighbor_entity parameter must match the relationship_types used
(e.g., "similar_papers" with "SIMILAR_TO", "authors" with "IS_AUTHOR_OF")

Notes:
- Results are randomly shuffled to provide diverse recommendations across multiple calls
- The function extracts only the "neighbor" data from the returned results
- There is a potential bug: the type check `type(relevant_neighbors) is int` should likely be
`type(num_neighbors_to_return) is int` for proper list truncation

Raises:
Connection errors if Neo4j database is not accessible
KeyError if neighbor_entity doesn't exist in the returned neighbors dictionary
ValueError if invalid relationship_types or neighbor_entity are provided

Example:
>>> similar_papers = find_neighboring_papers(
... paper_id="<UUID>",
... relationship_types=["SIMILAR_TO"],
... neighbor_entity="similar_papers",
... num_neighbors_to_return=5
... )
>>>
>>> authors = find_neighboring_papers(
... paper_id="<UUID>",
... relationship_types=["IS_AUTHOR_OF"],
... neighbor_entity="authors",
... num_neighbors_to_return=3
... )
[Your existing docstring]
"""
# Type coercion for parameters that may come as strings from LLM tool calls
if num_neighbors_to_return is not None and not isinstance(num_neighbors_to_return, int):
Expand All @@ -221,15 +164,15 @@ def find_neighboring_papers(
min_similarity=min_similarity,
)

# Flatten all neighbors from all relationship types into one list
relevant_neighbors = []
for rel_type, neighbor in neighbors.items():
if rel_type != relationship_types:
relevant_neighbors.append(neighbor)
for rel_type, neighbor_list in neighbors.items():
# neighbor_list is a list of paper dicts, extend to flatten
relevant_neighbors.extend(neighbor_list)

# Constrain and shuffle neighbors for more diverse responses
random.shuffle(relevant_neighbors)

# FIX: Changed type(relevant_neighbors) to type(num_neighbors_to_return)
if num_neighbors_to_return is not None and isinstance(num_neighbors_to_return, int):
relevant_neighbors = relevant_neighbors[:num_neighbors_to_return]

Expand Down
5 changes: 3 additions & 2 deletions agentic_nav/tools/knowledge_graph/file_handler.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import pickle
import networkx as nx

Expand All @@ -12,7 +13,7 @@ def save_graph(graph: nx.Graph, output_path: str):
with open(output_path, 'wb') as f:
pickle.dump(graph, f)
f.close()
print(f"Graph saved to {output_path}")
logging.info(f"Graph saved to {output_path}")


def load_graph(input_path: str) -> nx.Graph:
Expand All @@ -25,5 +26,5 @@ def load_graph(input_path: str) -> nx.Graph:
with open(input_path, 'rb') as f:
graph = pickle.load(f)
f.close()
print(f"Graph loaded from {input_path}")
logging.info(f"Graph loaded from {input_path}")
return graph
Loading