MCPcopy Create free account
hub / github.com/CodeGraphContext/CodeGraphContext / ai_query

Function ai_query

src/codegraphcontext/viz/server.py:495–621  ·  view source on GitHub ↗
(request: AIQueryRequest)

Source from the content-addressed store, hash-verified

493
494@app.post("/api/ai_query")
495async def ai_query(request: AIQueryRequest):
496 if not db_manager:
497 raise HTTPException(status_code=500, detail="Database not initialized")
498
499 gemini_key = os.getenv("GEMINI_API_KEY")
500 openai_key = os.getenv("OPENAI_API_KEY")
501
502 if not gemini_key and not openai_key:
503 raise HTTPException(
504 status_code=400,
505 detail="AI querying requires GEMINI_API_KEY or OPENAI_API_KEY environment variable. Please set it in your configuration or .env."
506 )
507
508 query = request.query
509 repo_path = request.repo_path
510
511 translation_prompt = """You are an expert graph database administrator. Translate the user's natural language question about a codebase into a valid read-only Cypher query.
512
513The graph database represents the codebase structure with the following schema:
514### Nodes & Properties:
515* **`Repository`**: `name` (string), `path` (string, absolute path), `is_dependency` (boolean)
516* **`File`**: `name` (string), `path` (string, absolute path), `relative_path` (string), `is_dependency` (boolean)
517* **`Function`**: `name` (string), `path` (string, absolute path), `line_number` (int), `end_line` (int), `args` (list of strings), `cyclomatic_complexity` (int), `decorators` (list of strings), `lang` (string), `source` (string), `is_dependency` (boolean)
518* **`Class`**: `name` (string), `path` (string, absolute path), `line_number` (int), `end_line` (int), `bases` (list of strings), `decorators` (list of strings), `lang` (string), `source` (string), `is_dependency` (boolean)
519* **`Interface`**, **`Struct`**, **`Enum`**, **`Trait`**: similar properties to Class/Function
520* **`Module`**: `name` (string)
521
522### Relationships:
523* **`CONTAINS`**: (Repository)-[:CONTAINS]->(File), (File)-[:CONTAINS]->(Function), (File)-[:CONTAINS]->(Class)
524* **`CALLS`**: (Function)-[:CALLS]->(Function)
525* **`IMPORTS`**: (File)-[:IMPORTS]->(Module)
526* **`INHERITS`**: (Class)-[:INHERITS]->(Class)
527* **`IMPLEMENTS`**: (Class)-[:IMPLEMENTS]->(Interface)
528
529### Query Writing Rules:
5301. Only write SELECT/MATCH read-only queries. Do NOT use CREATE, MERGE, DELETE, SET, REMOVE, or other modifying keywords.
5312. Return nodes using the variable names `n` and `m`, and relationships using `rel` where possible. This is critical for the visualizer.
532 Example: MATCH (n:Class)-[rel:INHERITS]->(m:Class) RETURN n, rel, m
5333. Keep the query simple and efficient. Limit results using `LIMIT 150` unless more are needed.
5344. If the user asks about dependencies or paths, try to return paths using variables, and return nodes/relationships.
5355. Make property matches case-insensitive or fuzzy if appropriate (e.g. using `toLower(n.name) CONTAINS 'auth'` or `n.name =~ '(?i).*auth.*'`).
5366. If the user is querying a specific repository, you can filter by `Repository.path` or `Repository.name` if path is supplied.
537
538Respond ONLY with a JSON object in this format:
539{
540 "cypher_query": "MATCH ... RETURN n, rel, m LIMIT 100",
541 "explanation": "Brief description of what this Cypher query does"
542}
543"""
544
545 try:
546 # Call LLM to get Cypher
547 llm_response = call_llm(translation_prompt, query)
548 parsed_response = parse_json_from_llm(llm_response)
549 cypher_query = parsed_response.get("cypher_query", "")
550 translation_explanation = parsed_response.get("explanation", "")
551
552 if not cypher_query:

Callers

nothing calls this directly

Calls 11

call_llmFunction · 0.85
parse_json_from_llmFunction · 0.85
parse_elementFunction · 0.85
itemsMethod · 0.80
valuesMethod · 0.80
getMethod · 0.65
appendMethod · 0.65
sessionMethod · 0.45
get_driverMethod · 0.45
runMethod · 0.45

Tested by

no test coverage detected