latest
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from weakref import ref
|
||||
from dotenv import load_dotenv, find_dotenv
|
||||
load_dotenv(find_dotenv())
|
||||
import os
|
||||
@@ -18,36 +19,21 @@ from langchain_community.graphs import Neo4jGraph
|
||||
from langchain_community.chat_models import ChatOpenAI
|
||||
from langchain.prompts.prompt import PromptTemplate
|
||||
from routers.llm.private.ollama.ollama_wrapper import OllamaWrapper
|
||||
from modules.database.tools.neontology.utils import get_node_types, get_rels_by_type
|
||||
from modules.database.tools.neontology.basenode import BaseNode
|
||||
from modules.database.tools.neontology.baserelationship import BaseRelationship
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
# Define the schema for nodes and relationships
|
||||
node_types = {
|
||||
"KeyStage": ["merged", "key_stage_name", "unique_id", "created"],
|
||||
"KeyStageSyllabus": ["ks_syllabus_name", "unique_id", "created", "merged", "ks_syllabus_key_stage", "ks_syllabus_subject"],
|
||||
"YearGroup": ["created", "merged", "unique_id", "year_group_name"],
|
||||
"YearGroupSyllabus": ["created", "merged", "yr_syllabus_name", "yr_syllabus_year_group", "yr_syllabus_id", "yr_syllabus_subject"],
|
||||
"Topic": ["topic_type", "topic_assessment_type", "created", "merged", "unique_id", "topic_id", "total_number_of_lessons_for_topic", "topic_title"],
|
||||
"Lesson": ["topic_lesson_id", "topic_lesson_type", "created", "merged", "topic_lesson_title", "topic_lesson_length", "topic_lesson_suggested_activities", "topic_lesson_weblinks", "topic_lesson_skills_learned"],
|
||||
"LearningStatement": ["created", "merged", "lesson_learning_statement", "lesson_learning_statement_id", "lesson_learning_statement_type"]
|
||||
}
|
||||
|
||||
relationship_types = {
|
||||
"KEY_STAGE_INCLUDES_KEY_STAGE_SYLLABUS": ["created", "merged"],
|
||||
"KEY_STAGE_SYLLABUS_INCLUDES_YEAR_GROUP_SYLLABUS": ["created", "merged"],
|
||||
"YEAR_GROUP_FOLLOWS_YEAR_GROUP": ["created", "merged"],
|
||||
"KEY_STAGE_FOLLOWS_KEY_STAGE": ["created", "merged"],
|
||||
"YEAR_SYLLABUS_INCLUDES_TOPIC": ["created", "merged"],
|
||||
"TOPIC_INCLUDES_LESSON": ["created", "merged"],
|
||||
"LESSON_INCLUDES_LEARNING_STATEMENT": ["created", "merged"],
|
||||
"LESSON_FOLLOWS_LESSON": ["created", "merged"]
|
||||
}
|
||||
node_types = get_node_types(BaseNode)
|
||||
relationship_types = get_rels_by_type(BaseRelationship)
|
||||
|
||||
@router.get("/prompt")
|
||||
async def query_graph(
|
||||
database: str, prompt: str, top_k: int = 30, model: str = "gpt-4o", temperature: float = 0,
|
||||
database: str, prompt: str, top_k: int = 30, model: str = "qwen2.5-coder:3b", temperature: float = 0,
|
||||
verbose: bool = False, return_intermediate_steps: bool = False, exclude_types: list = None, include_types: list = None,
|
||||
return_direct: bool = False, validate_cypher: bool = False, model_type: str = "openai"
|
||||
return_direct: bool = False, validate_cypher: bool = False, model_type: str = "ollama"
|
||||
):
|
||||
logging.info(f"Received request with prompt: {prompt}")
|
||||
if exclude_types is None:
|
||||
@@ -70,7 +56,9 @@ async def query_graph(
|
||||
url=os.environ['APP_BOLT_URL'],
|
||||
username=os.environ['USER_NEO4J'],
|
||||
password=os.environ['PASSWORD_NEO4J'],
|
||||
database=database
|
||||
database=database,
|
||||
enhanced_schema=True,
|
||||
sanitize=True,
|
||||
)
|
||||
|
||||
logging.info("Refreshing schema...")
|
||||
@@ -79,14 +67,18 @@ async def query_graph(
|
||||
schema = graph.schema
|
||||
logging.info(f"Schema: {schema}")
|
||||
|
||||
CYPHER_GENERATION_TEMPLATE = """Task: Generate a Cypher statement to query a graph database for timetable information.
|
||||
CYPHER_GENERATION_TEMPLATE = """Task: Generate a Cypher statement to query a graph database.
|
||||
Role:
|
||||
You are an assistant in a school for teachers, specializing in querying graph databases to find answers to questions.
|
||||
The teacher will ask you questions about their timetable.
|
||||
You are an assistant specializing in querying graph databases to find answers to questions about establishments, schools, and related data.
|
||||
The user will ask you questions about the graph database
|
||||
|
||||
Instructions:
|
||||
1. Use only the provided relationship types and properties in the schema.
|
||||
2. Do not use any other relationship types or properties that are not provided.
|
||||
3. When querying for geographic entities like counties, towns, or countries, use the 'name' property, not 'code'.
|
||||
4. To find relationship types, use: MATCH (n:NodeType)-[r]->(m) RETURN DISTINCT type(r)
|
||||
5. Relationship labels are in uppercase, e.g. LOCATED_IN_COUNTRY
|
||||
6. For broad queries use OPTIONAL MATCH to allow for null results, e.g. OPTIONAL MATCH (n:NodeType) RETURN n.name
|
||||
|
||||
Schema:
|
||||
{schema}
|
||||
@@ -95,6 +87,7 @@ async def query_graph(
|
||||
1. Do not include any explanations or apologies in your responses.
|
||||
2. Do not respond to any questions that might ask anything else than for you to construct a Cypher statement.
|
||||
3. Do not include any text except the generated Cypher statement.
|
||||
4. Do not include line break characters n other formatting keys.
|
||||
|
||||
The question is:
|
||||
{question}"""
|
||||
@@ -105,11 +98,11 @@ async def query_graph(
|
||||
)
|
||||
|
||||
if model_type == "ollama":
|
||||
ollama_host = os.getenv("OLLAMA_URL")
|
||||
ollama_port = os.getenv("OLLAMA_PORT")
|
||||
ollama_host = os.getenv("HOST_OLLAMA")
|
||||
ollama_port = os.getenv("PORT_OLLAMA")
|
||||
if not ollama_host or not ollama_port:
|
||||
raise HTTPException(status_code=500, detail="Ollama host or port not set")
|
||||
client = OllamaWrapper(host=f'http://{ollama_host}:{ollama_port}')
|
||||
client = OllamaWrapper(host=f'{ollama_host}:{ollama_port}', model=model)
|
||||
cypher_llm = client
|
||||
qa_llm = client
|
||||
else:
|
||||
@@ -127,7 +120,8 @@ async def query_graph(
|
||||
exclude_types=exclude_types,
|
||||
include_types=include_types,
|
||||
return_direct=return_direct,
|
||||
validate_cypher=validate_cypher
|
||||
validate_cypher=validate_cypher,
|
||||
allow_dangerous_requests=True
|
||||
)
|
||||
|
||||
formatted_prompt = CYPHER_GENERATION_PROMPT.format(schema=schema, question=prompt)
|
||||
@@ -150,4 +144,6 @@ async def query_graph(
|
||||
logging.info(f"Cypher chain: \n{chain}\n")
|
||||
logging.info("==================================================")
|
||||
|
||||
return chain(prompt)
|
||||
return chain(prompt)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user