
    +#hE                         d dl Z d dlmZmZmZmZ d dlZd dlmZm	Z	m
Z
mZmZ d dlZd dlmZ 	 d dlmZ d dlmZmZ  G d d	      Zd
Z G d dej0                        Zy# e$ r	  ed      w xY w)    N)AnyListOptionalUnion)APITimeoutErrorInternalServerErrorOpenAIRateLimitErrorUnprocessableEntityError)dotdict)GraphDatabase)	AuthErrorServiceUnavailablezHPlease install the neo4j package by running `pip install dspy-ai[neo4j]`c                   t    e Zd ZdedefdZ ej                  ej                  ee	e
efd      defd       Zy)	Embedderprovidermodelc                     |dk(  r9t        j                  d      }|st        d      t               | _        || _        y y )NopenaiOPENAI_API_KEYz/Environment variable OPENAI_API_KEY must be set)osgetenv
ValueErrorr	   clientr   )selfr   r   api_keys       S/var/www/html/sandstorm/venv/lib/python3.12/site-packages/dspy/retrieve/neo4j_rm.py__init__zEmbedder.__init__   s=    xii 01G !RSS (DKDJ         )max_timereturnc                     | j                   j                  j                  || j                        }|j                  D cg c]  }|j
                   c}S c c}w )N)inputr   )r   
embeddingscreater   data	embedding)r   queriesr(   results       r   __call__zEmbedder.__call__%   sE     KK**11tzz1R	/8~~>V  >>>s    AN)__name__
__module____qualname__strr   backoffon_exceptionexpor   r   r
   r   r   r+    r   r   r   r      sZ     S  W$		
 	?3 ?	?r   r   zJCALL db.index.vector.queryNodes($index, $k, $embedding) YIELD node, score c                        e Zd ZdZ	 	 	 	 	 ddedededededef fdZd	eeee   f   de	e   d
e
j                  fdZ xZS )Neo4jRMa  
    Implements a retriever that utilizes Neo4j for retrieving passages.
    This class manages a connection to a Neo4j database using official Neo4j Python drivers and requires
    the database credentials (username, password, URI, and optionally the database name) to be set as environment variables.
    Additionally, it utilizes an embedding provider (defaulting to OpenAI's services) to compute query embeddings,
    which are then used to find the most relevant nodes in the Neo4j graph based on the specified node property or custom retrieval query.

    Returns a list of passages in the form of `dspy.Prediction` objects.

    Args:
        index_name (str): The name of the vector index in the Neo4j database to query against.
        text_node_property (Optional[str]): The property of the node containing the text. Required if `retrieval_query` is not set.
        k (Optional[int]): The default number of top passages to retrieve. Defaults to 5.
        retrieval_query (Optional[str]): Custom Cypher query for retrieving passages. Required if `text_node_property` is not set.
        embedding_provider (str): The provider of the embedding service. Defaults to "openai".
        embedding_model (str): The model identifier for generating embeddings. Defaults to "text-embedding-ada-002".

    Examples:
        Below is a code snippet showcasing how to initialize Neo4jRM with environment variables for the database connection and OpenAI as the embedding provider:

        ```python
        import os

        import dspy
        import openai

        os.environ["NEO4J_URI"] = "bolt://localhost:7687"
        os.environ["NEO4J_USERNAME"] = "neo4j"
        os.environ["NEO4J_PASSWORD"] = "password"
        os.environ["OPENAI_API_KEY"] = "sk-"

        neo4j_retriever = Neo4jRM(
            index_name="myIndex",
            text_node_property="text",
            k=10,
            embedding_provider="openai",
            embedding_model="text-embedding-ada-002",
        )

        dspy.settings.configure(rm=neo4j_retriever)
        ```

        In this example, `Neo4jRM` is configured to retrieve nodes based on the "text" property from an index named "myIndex",
        using embeddings computed by OpenAI's "text-embedding-ada-002" model.
    
index_nametext_node_propertykretrieval_queryembedding_providerembedding_modelc                    t         |   |       || _        t        j                  d      | _        t        j                  d      | _        t        j                  d      | _        t        j                  dd      | _        || _	        || _
        || _        | j
                  st        d      | j                  st        d      | j                  st        d	      | j                  s| j                  st        d
      	 t        j                  | j                  | j
                  | j                  f      | _        | j                  j                          t'        ||      | _        y # t         t"        f$ r}t%        d      |d }~ww xY w)N)r8   NEO4J_USERNAMENEO4J_PASSWORD	NEO4J_URINEO4J_DATABASEneo4jz/Environment variable NEO4J_USERNAME must be setz/Environment variable NEO4J_PASSWORD must be setz*Environment variable NEO4J_URI must be setzKEither `text_node_property` or `retrieval_query` parameters must be defined)authz#Failed to connect to Neo4j database)r   r   )superr   r6   r   r   usernamepassworduridatabaser8   r9   r7   r   r   driververify_connectivityr   r   ConnectionErrorr   embedder)	r   r6   r7   r8   r9   r:   r;   e	__class__s	           r   r   zNeo4jRM.__init__f   sF    	1$		"23		"2399[)		"2G<."4}}NOO}}NOOxxIJJ&&t/C/Cjkk	P'..txxt}}dmm>\]DKKK++- !*<OT 
 	P ""GHaO		Ps    AE) )F	8FF	query_or_queriesr"   c                    t        |t              s|g}| j                  |      }g }| j                  xs d| j                   d}|D ]  }| j
                  j                  t        |z   || j                  |xs | j                  d| j                        \  }}}|j                  |D 	cg c]  }	t        d|	d   i      |	d   d c}	        t        |d	 d
      d |xs | j                   }
|
D cg c]  }|d   	 c}S c c}	w c c}w )NzRETURN node.z AS text, score)r(   indexr8   )	database_	long_texttextscore)passagerT   c                     | d   S )NrT   r3   )xs    r   <lambda>z!Neo4jRM.forward.<locals>.<lambda>   s
    !G* r   T)keyreverserU   )
isinstancelistrK   r9   r7   rH   execute_queryDEFAULT_INDEX_QUERYr6   r8   rG   extendr   sorted)r   rN   r8   query_vectorscontentsr9   vectorrecords_rsorted_passagesels               r   forwardzNeo4jRM.forward   s    *D1 01&67..iLAXAX@YYh2i# 	tF KK55#o5$tQ[$&&Q-- 6 MGQ
 OOjqref+qy1I)JUVW^U_`rs	t !$
 AK	
 )88"988 s 9s   (D
2D)N   Nr   ztext-embedding-ada-002)r,   r-   r.   __doc__r/   intr   r   r   r   dspy
Predictionri   __classcell__)rM   s   @r   r5   r5   7   s    ,b #'#"*7$U$U  $U 	$U
 $U  $U $UL9c49n(= 9(3- 9TXTcTc 9r   r5   )r   typingr   r   r   r   r0   r   r   r   r	   r
   r   rm   	dsp.utilsr   rA   r   neo4j.exceptionsr   r   ImportErrorr   r^   Retriever5   r3   r   r   <module>ru      sw    	 - -    	#? ?0 c g9dmm g9C  
R s   A A,