Una implementación GraphRAG simple y fácil de piratear
? GraphRAG es bueno y potente, pero la implementación oficial es difícil/dolorosa de leer o piratear .
? Este proyecto proporciona un GraphRAG más pequeño, más rápido y más limpio , sin dejar de ser la funcionalidad principal (ver puntos de referencia y problemas).
? Excluyendo tests
e indicaciones, nano-graphrag
tiene aproximadamente 1100 líneas de código .
? Pequeño pero portátil (faiss, neo4j, ollama...), asíncrono y completamente tipificado.
Instalar desde la fuente (recomendado)
# clone this repo first
cd nano-graphrag
pip install -e .
Instalar desde PyPi
pip install nano-graphrag
Consejo
Configure la clave API de OpenAI en el entorno: export OPENAI_API_KEY="sk-..."
.
Consejo
Si está utilizando la API de Azure OpenAI, consulte .env.example para configurar su openai de Azure. Luego pase GraphRAG(...,using_azure_openai=True,...)
para habilitarlo.
Consejo
Si utiliza la API de Amazon Bedrock, asegúrese de que sus credenciales estén configuradas correctamente mediante comandos como aws configure
. Luego habilítelo configurando así: GraphRAG(...,using_amazon_bedrock=True, best_model_id="us.anthropic.claude-3-sonnet-20240229-v1:0", cheap_model_id="us.anthropic.claude-3-haiku-20240307-v1:0",...)
. Consulte un script de ejemplo.
Consejo
Si no tiene ninguna clave, consulte este ejemplo que usa transformers
y ollama
. Si desea utilizar otro LLM o modelo de integración, consulte Avances.
descargue una copia de Un cuento de Navidad de Charles Dickens:
curl https://raw.githubusercontent.com/gusye1234/nano-graphrag/main/tests/mock_data.txt > ./book.txt
Utilice el siguiente fragmento de Python:
from nano_graphrag import GraphRAG , QueryParam
graph_func = GraphRAG ( working_dir = "./dickens" )
with open ( "./book.txt" ) as f :
graph_func . insert ( f . read ())
# Perform global graphrag search
print ( graph_func . query ( "What are the top themes in this story?" ))
# Perform local graphrag search (I think is better and more scalable one)
print ( graph_func . query ( "What are the top themes in this story?" , param = QueryParam ( mode = "local" )))
La próxima vez que inicialice un GraphRAG
desde el mismo working_dir
, recargará todos los contextos automáticamente.
graph_func . insert ([ "TEXT1" , "TEXT2" ,...])
nano-graphrag
admite la inserción incremental, no se agregarán cálculos ni datos duplicados:
with open ( "./book.txt" ) as f :
book = f . read ()
half_len = len ( book ) // 2
graph_func . insert ( book [: half_len ])
graph_func . insert ( book [ half_len :])
nano-graphrag
usa md5-hash del contenido como clave, por lo que no hay fragmentos duplicados.Sin embargo, cada vez que inserte, las comunidades del gráfico se volverán a calcular y se volverán a generar los informes de la comunidad.
nano-graphrag
también admite la inserción y consulta ingenua de RAG:
graph_func = GraphRAG ( working_dir = "./dickens" , enable_naive_rag = True )
...
# Query
print ( rag . query (
"What are the top themes in this story?" ,
param = QueryParam ( mode = "naive" )
)
Para cada método NAME(...)
, hay un método asíncrono correspondiente aNAME(...)
await graph_func . ainsert (...)
await graph_func . aquery (...)
...
GraphRAG
y QueryParam
son dataclass
en Python. Utilice help(GraphRAG)
y help(QueryParam)
para ver todos los parámetros disponibles. O consulte la sección Avances para ver algunas opciones.
A continuación se muestran los componentes que puede utilizar:
Tipo | Qué | Dónde |
---|---|---|
LLM | AbiertoAI | Incorporado |
Roca Amazónica | Incorporado | |
búsqueda profunda | ejemplos | |
ollama | ejemplos | |
Incrustar | AbiertoAI | Incorporado |
Roca Amazónica | Incorporado | |
Transformadores de oraciones | ejemplos | |
Base de datos vectorial | nano-vectordb | Incorporado |
hnswlib | Ejemplos integrados | |
milvus-lite | ejemplos | |
faiss | ejemplos | |
Almacenamiento de gráficos | networkx | Incorporado |
neo4j | Incorporado(doc) | |
Visualización | grafml | ejemplos |
fragmentación | por tamaño de token | Incorporado |
por divisor de texto | Incorporado |
Built-in
significa que tenemos esa implementación dentro de nano-graphrag
. examples
significa que tenemos esa implementación dentro de un tutorial en la carpeta de ejemplos.
Consulte ejemplos/puntos de referencia para ver algunas comparaciones entre componentes.
Siempre bienvenido a contribuir con más componentes.
GraphRAG(...,always_create_working_dir=False,...)
omitirá el paso de creación del directorio. Úselo si cambia todos sus componentes a almacenamientos que no sean archivos. graph_func.query
devuelve la respuesta final sin transmisión.
Si desea interactuar con nano-graphrag
en su proyecto, puede usar param=QueryParam(..., only_need_context=True,...)
, que solo devolverá el contexto recuperado del gráfico, algo como:
# Local mode
-----Reports-----
```csv
id, content
0, # FOX News and Key Figures in Media and Politics...
1, ...
```
...
# Global mode
----Analyst 3----
Importance Score: 100
Donald J. Trump: Frequently discussed in relation to his political activities...
...
Puede integrar ese contexto en su mensaje personalizado.
nano-graphrag
utiliza indicaciones del objeto dict nano_graphrag.prompt.PROMPTS
. Puedes jugar con él y reemplazar cualquier mensaje interno.
Algunas indicaciones importantes:
PROMPTS["entity_extraction"]
se utiliza para extraer las entidades y relaciones de un fragmento de texto.PROMPTS["community_report"]
se utiliza para organizar y resumir la descripción del grupo de gráficos.PROMPTS["local_rag_response"]
es la plantilla de aviso del sistema de la generación de búsqueda local.PROMPTS["global_reduce_rag_response"]
es la plantilla de aviso del sistema de la generación de búsqueda global.PROMPTS["fail_response"]
es la respuesta alternativa cuando no hay nada relacionado con la consulta del usuario. nano-graphrag
le permite personalizar su propio método de fragmentación, consulte el ejemplo.
Cambie al método de fragmentación del divisor de texto incorporado:
from nano_graphrag . _op import chunking_by_seperators
GraphRAG (..., chunk_func = chunking_by_seperators ,...)
En nano-graphrag
, necesitamos dos tipos de LLM, uno excelente y otro económico. El primero se utiliza para planificar y responder, el segundo se utiliza para resumir. Por defecto, el genial es gpt-4o
y el barato es gpt-4o-mini
Puede implementar su propia función LLM (consulte _llm.gpt_4o_complete
):
async def my_llm_complete (
prompt , system_prompt = None , history_messages = [], ** kwargs
) -> str :
# pop cache KV database if any
hashing_kv : BaseKVStorage = kwargs . pop ( "hashing_kv" , None )
# the rest kwargs are for calling LLM, for example, `max_tokens=xxx`
...
# YOUR LLM calling
response = await call_your_LLM ( messages , ** kwargs )
return response
Reemplace el predeterminado con:
# Adjust the max token size or the max async requests if needed
GraphRAG ( best_model_func = my_llm_complete , best_model_max_token_size = ..., best_model_max_async = ...)
GraphRAG ( cheap_model_func = my_llm_complete , cheap_model_max_token_size = ..., cheap_model_max_async = ...)
Puede consultar este ejemplo que utiliza deepseek-chat
como modelo LLM.
Puede consultar este ejemplo que usa ollama
como modelo LLM.
nano-graphrag
usará best_model_func
para generar JSON con parámetros "response_format": {"type": "json_object"}
. Sin embargo, hay algunos modelos de código abierto que pueden producir JSON inestable.
nano-graphrag
presenta una interfaz de posproceso para que pueda convertir la respuesta a JSON. La firma de esta función se encuentra a continuación:
def YOUR_STRING_TO_JSON_FUNC ( response : str ) -> dict :
"Convert the string response to JSON"
...
Y pase su propia función por GraphRAG(...convert_response_to_json_func=YOUR_STRING_TO_JSON_FUNC,...)
.
Por ejemplo, puede consultar json_repair para reparar la cadena JSON devuelta por LLM.
Puede reemplazar las funciones de incrustación predeterminadas con cualquier instancia de _utils.EmbedddingFunc
.
Por ejemplo, el predeterminado utiliza la API de incrustación de OpenAI:
@ wrap_embedding_func_with_attrs ( embedding_dim = 1536 , max_token_size = 8192 )
async def openai_embedding ( texts : list [ str ]) -> np . ndarray :
openai_async_client = AsyncOpenAI ()
response = await openai_async_client . embeddings . create (
model = "text-embedding-3-small" , input = texts , encoding_format = "float"
)
return np . array ([ dp . embedding for dp in response . data ])
Reemplace la función de incrustación predeterminada con:
GraphRAG ( embedding_func = your_embed_func , embedding_batch_num = ..., embedding_func_max_async = ...)
Puede consultar un ejemplo que utiliza sentence-transformer
para calcular incrustaciones localmente.
Puede reemplazar todos los componentes relacionados con el almacenamiento con su propia implementación; nano-graphrag
utiliza principalmente tres tipos de almacenamiento:
base.BaseKVStorage
para almacenar pares de datos clave-json
GraphRAG(.., key_string_value_json_storage_cls=YOURS,...)
base.BaseVectorStorage
para indexar incrustaciones
nano-vectordb
como backend.hnswlib
incorporado, consulte este ejemplo.milvus-lite
como backend (no disponible en Windows).GraphRAG(.., vector_db_storage_cls=YOURS,...)
base.BaseGraphStorage
para almacenar gráficos de conocimiento
networkx
como backend.Neo4jStorage
integrado para gráficos, consulte este tutorial.GraphRAG(.., graph_storage_cls=YOURS,...)
Puede consultar nano_graphrag.base
para ver interfaces detalladas para cada componente.
Consulte la FQA.
Ver ROADMAP.md
nano-graphrag
está abierto a cualquier tipo de contribución. Lea esto antes de contribuir.
nano-graphrag
Bienvenido a las solicitudes de extracción si su proyecto utiliza
nano-graphrag
, ayudará a otros a confiar en este repositorio❤️
nano-graphrag
no implementó la función covariates
de GraphRAG
nano-graphrag
implementa la búsqueda global diferente a la original. El original usa un estilo similar a un mapa reducido para poner todas las comunidades en contexto, mientras que nano-graphrag
solo usa las comunidades centrales y más importantes (use QueryParam.global_max_consider_community
para controlar, el valor predeterminado es 512 comunidades).