diff --git a/README.md b/README.md index 0f7ae26..6d4672b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,47 @@ > - **Supported Backend:** TigerGraph is the only Vector and Graph DB supported in this project. Hybrid Search is the officially retriever method supported at backend. > - **Limitations:** No official support is provided unless delivered through a Statement of Work (SOW) with the Solutions team. Customizations are customer-owned self-service to handle custom LLM service, prompt logic, UI integration, and pipeline orchestration. This project is provided "as is" without any warranties or guarantees. +## Table of Contents + +- [Releases](#releases) +- [Overview](#overview) + - [Nature Language Query](#nature-language-query) + - [Knowledge Graph Query](#knowledge-graph-query) +- [Getting Started](#getting-started) + - [Prerequisites](#prerequisites) + - [Quick Start](#quick-start) + - [Use TigerGraph Docker-Based Instance](#use-tigergraph-docker-based-instance) + - [Use Pre-Installed TigerGraph Instance](#use-pre-installed-tigergraph-instance) + - [Deploy GraphRAG Manually](#deploy-graphrag-manually) + - [Manual Deploy of GraphRAG with Docker Compose](#manual-deploy-of-graphrag-with-docker-compose) + - [Use Standalone TigerGraph instance (If preferred)](#use-standalone-tigergraph-instance-if-preferred) + - [Manual Deploy of GraphRAG with Kubernetes](#manual-deploy-of-graphrag-with-kubernetes) +- [Use TigerGraph GraphRAG](#use-tigergraph-graphrag) + - [Run Demo with Preloaded GraphRAG](#run-demo-with-preloaded-graphrag) + - [Manually Build GraphRAG From Scratch](#manually-build-graphrag-from-scratch) +- [Detailed Data Ingestion Methods](#detailed-data-ingestion-methods) +- [More Detailed Configurations](#more-detailed-configurations) + - [DB configuration](#db-configuration) + - [GraphRAG configuration](#graphrag-configuration) + - [Chat configuration](#chat-configuration) + - [LLM provider configuration](#llm-provider-configuration) + - [OpenAI](#openai) + - [Google GenAI](#google-genai) + - [GCP VertexAI](#gcp-vertexai) + - [Azure](#azure) + - [AWS Bedrock](#aws-bedrock) + - [Ollama](#ollama) + - [Hugging Face](#hugging-face) + - [Groq](#groq) +- [Customization and Extensibility](#customization-and-extensibility) + - [Test Your Code Changes](#test-your-code-changes) + - [Testing with Pytest](#testing-with-pytest) + - [Test Code Change in Docker Container](#test-code-change-in-docker-container) + - [Test Script Options](#test-script-options) + - [Configure LLM Service](#configure-llm-service) + - [Configure Testing Graphs](#configure-testing-graphs) + - [Configure Weights and Biases](#configure-weights-and-biases) + ## Releases * **9/22/2025: GraphRAG is available now officially v1.1 (v1.1.0). AWS Bedrock support is completed with BDA integration for multimodal document ingestion. * **6/18/2025: GraphRAG is available now officially v1.0 (v1.0.0). TigerGraph database is the only graph and vector storagge supported. @@ -11,74 +52,84 @@ Please see [Release Notes](https://docs.tigergraph.com/tg-graphrag/current/relea ## Overview -![./docs/img/TG-GraphRAG-Architecture.png](./docs/img/TG-GraphRAG-Architecture.png) +![GraphRAG Overview](./docs/img/TG-GraphRAG-Overview.png) -TigerGraph GraphRAG is an AI assistant that is meticulously designed to combine the powers of vector store, graph databases and generative AI to draw the most value from data and to enhance productivity across various business functions, including analytics, development, and administration tasks. It is one AI assistant with three core component services: -* InquiryAI as a natural language assistant for graph-powered solutions -* SupportAI as a knowledge Q&A assistant for documents and graphs +TigerGraph GraphRAG is an AI assistant that is meticulously designed to combine the powers of vector store, graph databases and generative AI to draw the most value from data and to enhance productivity across various business functions, including analytics, development, and administration tasks. It is one AI assistant with two core component services: +* A natural language assistant for graph-powered solutions +* A knowledge Q&A assistant for documents and graphs You can interact with GraphRAG through the built-in chat interface and APIs. For now, your own LLM services (from OpenAI, Azure, GCP, AWS Bedrock, Ollama, Hugging Face and Groq.) are required to use GraphRAG, but in future releases you can use TigerGraph’s LLMs. -### InquiryAI -![./docs/img/InquiryAI-Architecture.png](./docs/img/InquiryAI-Architecture.png) +### Nature Language Query +![Nature Language Query](./docs/img/NatureLanguageQuery-Architecture.png) -When a question is posed in natural language, GraphRAG (InquiryAI) employs a novel three-phase interaction with both the TigerGraph database and a LLM of the user's choice, to obtain accurate and relevant responses. +When a question is posed in natural language, GraphRAG employs a novel three-phase interaction with both the TigerGraph database and a LLM of the user's choice, to obtain accurate and relevant responses. The first phase aligns the question with the particular data available in the database. GraphRAG uses the LLM to compare the question with the graph’s schema and replace entities in the question by graph elements. For example, if there is a vertex type of `BareMetalNode` and the user asks `How many servers are there?`, the question will be translated to `How many BareMetalNode vertices are there?`. In the second phase, GraphRAG uses the LLM to compare the transformed question with a set of curated database queries and functions in order to select the best match. In the third phase, GraphRAG executes the identified query and returns the result in natural language along with the reasoning behind the actions. Using pre-approved queries provides multiple benefits. First and foremost, it reduces the likelihood of hallucinations, because the meaning and behavior of each query has been validated. Second, the system has the potential of predicting the execution resources needed to answer the question. -### SupportAI -![./docs/img/InquiryAI-Architecture.png](./docs/img/SupportAI-Architecture.png) +### Knowledge Graph Query +![Knowledge Graph Query](./docs/img/GraphRAG-Architecture.png) -With SupportAI, GraphRAG creates chatbots with graph-augmented AI on a user's own documents or text data. It builds a knowledge graph from source material and applies its unique variant of knowledge graph-based RAG (Retrieval Augmented Generation) to improve the contextual relevance and accuracy of answers to natural-language questions. +For inquiries cannot be answered with structured graph data, GraphRAG employs an AI chatbots with graph-augmented Knowledge Graph based on a user's own documents or text data. It builds a knowledge graph from source material and applies its unique variant of knowledge graph-based RAG (Retrieval Augmented Generation) to improve the contextual relevance and accuracy of answers to natural-language questions. GraphRAG will also identify concepts and build an ontology, to add semantics and reasoning to the knowledge graph, or users can provide their own concept ontology. Then, with this comprehensive knowledge graph, GraphRAG performs hybrid retrievals, combining traditional vector search and graph traversals, to collect more relevant information and richer context to answer users’ knowledge questions. Organizing the data as a knowledge graph allows a chatbot to access accurate, fact-based information quickly and efficiently, thereby reducing the reliance on generating responses from patterns learned during training, which can sometimes be incorrect or out of date. +[Go back to top](#top) -## Getting Started -### Self-Managed -The quickest way to access TigerGraph GraphRAG is to deploy its docker image with the docker compose file in the repo. In order to take this route, you will need the following prerequisites. +## Getting Started -#### Prerequisites -* Docker +### Prerequisites +* Docker + Docker Compose Plugin, or Kubernetes * TigerGraph DB 4.2+. * API key of your LLM provider. (An LLM provider refers to a company or organization that offers Large Language Models (LLMs) as a service. The API key verifies the identity of the requester, ensuring that the request is coming from a registered and authorized user or application.) Currently, GraphRAG supports the following LLM providers: OpenAI, Azure OpenAI, GCP, AWS Bedrock. -#### Deploy with Kubernetes -* Step 1: Get kubernetes deployment file - - Download the [graphrag-k8s.yml](https://raw.githubusercontent.com/tigergraph/ecosys/refs/heads/master/tutorials/graphrag/graphrag-k8s.yml) file directly -* Step 2: Set up configurations - Next, in the same directory as the Kubernetes deployment file is in, create a `configs` directory and download the following configuration files: - * [configs/server_config.json](https://raw.githubusercontent.com/tigergraph/ecosys/refs/heads/master/tutorials/graphrag/configs/server_config.json) +### Quick Start - Update the TigerGraph database information, LLM API keys and other configs accordingly. +#### Use TigerGraph Docker-Based Instance +Using the following command for a one-step quick deployment with TigerGraph Community Edition and default configurations: +``` +curl -k https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/setup_graphrag.sh | sh +``` -* Step 3: Start all services - Replace `/path/to/graphrag/configs` with the absolute path of the `configs` folder inside `graphrag-k8s.yml`, and update the TigerGraph database information and other configs accordingly. +The GraphRAG instances will be deployed at `./graphrag` folder and TigerGraph instance will be available at `http://localhost:14240`. +To change installation folder, use `sh -s -- ` instead of `sh` at the end of the above command. - Now, simply run `kubectl apply -f graphrag-k8s.yml` and wait for all the services to start. +#### Use Pre-Installed TigerGraph Instance + +Using the following command for a one-step quick deployment with TigerGraph Community Edition and default configurations: +``` +curl -k https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/setup_graphrag_tg.sh | sh +``` + +The GraphRAG instances will be deployed at `./graphrag` folder and connect to TigerGraph instance at `http://localhost:14240` by default. +To change installation folder, TigerGraph instance location or username/password, use `sh -s -- ` instead of `sh` at the end of the above command. -> Note: Nginx Ingress should be installed using `kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/cloud/deploy.yaml` +[Go back to top](#top) -#### Deploy with Docker Compose -* Step 1: Get docker-compose file - - Download the [docker-compose.yml](https://raw.githubusercontent.com/tigergraph/ecosys/refs/heads/master/tutorials/graphrag/docker-compose.yml) file directly +### Deploy GraphRAG Manually +The GraphRAG services can be deployed manually using Docker Compose or Kubernetes with updated configurations for different use cases. - The Docker Compose file contains all dependencies for GraphRAG. Moreover, GraphRAG comes with a Swagger API documentation page when it is deployed. If you wish to disable it, you can set the `PRODUCTION` environment variable to true for the GraphRAG service in the Compose file. +#### Manual Deploy of GraphRAG with Docker Compose -* Step 2: Set up configurations +##### Step 1: Get docker-compose file +Download the [docker-compose.yml](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/docker-compose.yml) file directly - Next, in the same directory as the Docker Compose file is in, create and fill in the following configuration files: - * [configs/server_config.json](https://raw.githubusercontent.com/tigergraph/ecosys/refs/heads/master/tutorials/graphrag/configs/server_config.json) - * [configs/nginx.conf](https://raw.githubusercontent.com/tigergraph/ecosys/refs/heads/master/tutorials/graphrag/configs/nginx.conf) +The Docker Compose file contains all dependencies for GraphRAG including a TigerGraph database. If you want to use a separate TigerGraph instance, you can comment out the `tigergraph` section from the docker compose file and restart all services. However, please follow the instructions below to make sure your standalone TigerGraph server is accessible from other GraphRAG containers. - Here’s what the folder structure looks like: +##### Step 2: Set up configurations + +Next, download the following configuration files and put them in a `configs` subdirectory of the directory contains the Docker Compose file: +* [configs/server_config.json](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/configs/server_config.json) +* [configs/nginx.conf](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/configs/nginx.conf) + +Here’s what the folder structure looks like: ``` graphrag ├── configs @@ -87,7 +138,13 @@ The quickest way to access TigerGraph GraphRAG is to deploy its docker image wit └── docker-compose.yml ``` -* Step 3 (Optional): Configure Logging Level in Dockerfile +##### Step 3: Adjust configurations + +Edit `llm_config` section of `configs/server_config.json` and replace `` to your own OPENAI_API_KEY. + +> If desired, you can also change the model to be used for the embedding service and completion service to your preferred models to adjust the output from the LLM service. + +##### Step 4: Configure Logging Level in Dockerfile (Optional) To configure the logging level of the service, edit the Docker Compose file. @@ -111,24 +168,234 @@ This line can be changed to support different logging levels. | `DEBUG_PII` | Finer-grained information that could potentially include `PII`, such as a user’s question, the complete function call (with parameters), and the LLM’s natural language response. | | NOTSET | All messages are processed. | +##### Step 5: Start all services -* Step 4: Start all services +Now, simply run `docker compose up -d` and wait for all the services to start. - Uncomment `tigergraph` section from `docker-compose.yml` if it's commented out. Please follow the [instructions](https://github.com/tigergraph/ecosys/blob/master/tutorials/GSQL.md#set-up-environment) to download TigerGraph docker image. +> Note: `graphrag` container will be down if TigerGraph service is not ready. Log into the `tigergraph` container, bring up tigergraph services and rerun `docker compose up -d` should resolve the issue. - Now, simply run `docker compose up -d` and wait for all the services to start. +##### Step 6: Stop all services (when needed) -> Note: `graphrag` container will be down if TigerGraph service is not ready. Log into the `tigergraph` container, bring up tigergraph services and rerun `docker compose up -d` should resolve the issue. +Run command `docker compose down` and wait for all the service containers to stopped and removed. + +[Go back to top](#top) + +#### Use Standalone TigerGraph instance (If preferred) + +> **_Note:_** Vector feature is available in both TigerGraph Community Edition 4.2.0+ and Enterprise Edition 4.2.0+. + +If you prefer to start a TigerGraph Community Edition instance without a license key, please make sure the container can be accessed from the GraphRAG containers by add `--network graphrag_default`: +``` +docker run -d -p 14240:14240 --name tigergraph --ulimit nofile=1000000:1000000 --init --network graphrag_default -t tigergraph/community:4.2.1 +``` + +> Use **tigergraph/tigergraph:4.2.1** if Enterprise Edition is preferred. +> Setting up **DNS** or `/etc/hosts` properly is an alternative solution to ensure contains can connect to each other. +> Or modify`hostname` in `db_config` section of `configs/server_config.json` and replace `http://tigergraph` to your tigergraph container IP address, e.g., `http://172.19.0.2`. + +Check the service status with the following commands: +``` +docker exec -it tigergraph /bin/bash +gadmin status +gadmin start all +``` + +After using the database, and you want to shutdown it, use the following shell commmand +``` +gadmin stop all +``` + +[Go back to top](#top) + + +#### Manual Deploy of GraphRAG with Kubernetes + +##### Step 1: Get kubernetes deployment file + Download the [graphrag-k8s.yml](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/graphrag-k8s.yml) file directly + +##### Step 2: Modify `graphrag-k8s.yml` (Optional) + Remove the sections for tigergraph instance if you're using a standalone TigerGraph instance instead + +##### Step 3: Set up server configurations + Next, in the same directory as the Kubernetes deployment file is in, create a `configs` directory and download the following configuration files: + * [configs/server_config.json](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/configs/server_config.json) + + Update the TigerGraph database information, LLM API keys and other configs accordingly. + +##### Step 4: Install Nginx Ingress (Optional) + If Nginx Ingress is not installed yet, it can be installed using `kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/cloud/deploy.yaml` + +##### Step 5: Start all services + Replace `/path/to/graphrag/configs` with the absolute path of the `configs` folder inside `graphrag-k8s.yml`, and update the TigerGraph database information and other configs accordingly. + + Now, simply run `kubectl apply -f graphrag-k8s.yml` and wait for all the services to start. + +##### Step 6: Stop all services (Optional) + Run kubectl delete -f graphrag-k8s.yml and wait for all the services in the deployment to be deleted. + +> Note: Nginx Ingress should be deleted using kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.1/deploy/static/provider/cloud/deploy.yaml if port 80 needs to be released + +[Go back to top](#top) -## Data Ingestion -For data ingestion, please follow the [GraphRAG Demo Notebook](./docs/notebooks/GraphRAGDemo.ipynb) -## Detailed Configurations +## Use TigerGraph GraphRAG + +GraphRAG is friendly to both technical and non-technical users. There is a graphical chat interface as well as API access to GraphRAG. Function-wise, GraphRAG can answer your questions by calling existing queries in the database, build a knowledge graph from your documents, and answer knowledge questions based on your documents. + +### Run Demo with Preloaded GraphRAG + +The pre-loaded knowledge graph `TigerGraphRAG` is provided for an express access to the GraphRAG features. + +#### Step 1: Get data package + +Download the following data file and put it under `/home/tigergraph/graphrag/` inside your TigerGraph container: +* [ExportedGraph.zip](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/data/ExportedGraph.zip) + +Use the following commands if the file cannot be downloaded inside the TigerGraph container directly: +``` +docker exec -it tigergraph mkdir -p /home/tigergraph/graphrag +docker exec -it tigergraph curl -kL https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/data/ExportedGraph.zip -o /home/tigergraph/graphrag/ExportedGraph.zip +``` + +> Note: command should be changed to equivalent formats if standalone TigerGraph instance is used + +#### Step 2: Import data package +Next, log onto the TigerGraph instance and make use of the Database Import feature to recreate the GraphRAG: +``` +docker exec -it tigergraph /bin/bash +gsql "import graph all from \"/home/tigergraph/graphrag\"" +gsql "install query all" +``` + +Wait until the following output is given: +``` +[======================================================================================================] 100% (26/26) +Query installation finished. +``` + +#### Step 3: Access Chatbot UI +Open your browser to access `http://localhost:` to access GraphRAG Chat. For example: http://localhost:80 + +Enter the username and password of the TigerGraph database to login. + +![Chat Login](./docs/img/ChatLogin.jpg) + +On the top of the page, select `Community Search` as RAG pattern and `TigerGraphRAG` as Graph. +![RAG Config](./docs/img/RAGConfig.jpg) + +In the chat box, input the question `how to load data to tigergraph vector store, give an example in Python` and click the `send` button. +![Demo Question](./docs/img/DemoQuestion.jpg) + +You can also ask other questions on statistics and data inside the TigerGraph database. +![Data ](./docs/img/Inquiry.jpg) + +[Go back to top](#top) + + +### Manually Build GraphRAG From Scratch + +If you want to experience the whole process of GraphRAG, you can build the GraphRAG from scratch. However, please review the LLM model and service setting carefully because it will cost some money to re-generate embedding and data structure for the raw data. + +#### Step 1: Get demo script + +The following scripts are needed to run the demo. Please download and put them in the same directory `./graphrag` as the Docker Compose file: +* Demo driver: [graphrag_demo.sh](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/graphrag_demo.sh) +* GraphRAG initializer: [init_graphrag.py](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/init_graphrag.py) +* Example: [answer_question.py](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/tutorials/answer_question.py) + +#### Step 2: Download the demo data + +Next, download the following data file and put it in a `data` subdirectory of the directory contains the Docker Compose file: +* [data/tg_tutorials.jsonl](https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/master/docs/data/tg_tutorials.jsonl) + +#### Step 3: Run the demo driver script + +> Note: Python 3.11+ is needed to run the demo + +It is recommended to use a virtual env to isolate the runtime environment for the demo +``` +python3.11 -m venv demo +source demo/bin/activate +``` + +Now, simply run the demo script to try GraphRAG. +``` + ./graphrag_demo.sh +``` + +The script will: +1. Check the environment +1. Init TigerGraph schema and related queries needed +1. Load the sample data +1. Init the GraphRAG based on the graph and install required queries +1. Ask a question via Python to get answer from GraphRAG + +[Go back to top](#top) + + +## Detailed Data Ingestion Methods +For more examples of data ingestion, please follow the [GraphRAG Demo Notebook](./docs/notebooks/GraphRAGDemo.ipynb) + +[Go back to top](#top) + + +## More Detailed Configurations + +### DB configuration +Copy the below into `configs/server_config.json` and edit the `hostname` and `getToken` fields to match your database's configuration. If token authentication is enabled in TigerGraph, set `getToken` to `true`. Set the timeout, memory threshold, and thread limit parameters as desired to control how much of the database's resources are consumed when answering a question. + +```json +{ + "db_config": { + "hostname": "http://tigergraph", + "restppPort": "9000", + "gsPort": "14240", + "getToken": false, + "default_timeout": 300, + "default_mem_threshold": 5000, + "default_thread_limit": 8 + } +} +``` + +### GraphRAG configuration +Copy the below code into `configs/server_config.json`. You shouldn’t need to change anything unless you change the port of the chat history service in the Docker Compose file. + +`reuse_embedding` to `true` will skip re-generating the embedding if it already exists. +`ecc` and `chat_history_api` are the addresses of internal components of GraphRAG.If you use the Docker Compose file as is, you don’t need to change them. + +```json +{ + "graphrag_config": { + "reuse_embedding": false, + "ecc": "http://eventual-consistency-service:8001", + "chat_history_api": "http://chat-history:8002" + } +} +``` + +### Chat configuration +Copy the below code into `configs/server_config.json`. You shouldn’t need to change anything unless you change the port of the chat history service in the Docker Compose file. + +```json +{ + "chat-history": { + "apiPort":"8002", + "dbPath": "chats.db", + "dbLogPath": "db.log", + "logPath": "requestLogs.jsonl", + "conversationAccessRoles": ["superuser", "globaldesigner"] + } +} +``` + +[Go back to top](#top) + ### LLM provider configuration In the `llm_config` section of `configs/server_config.json` file, copy JSON config template from below for your LLM provider, and fill out the appropriate fields. Only one provider is needed. -* OpenAI +#### OpenAI In addition to the `OPENAI_API_KEY`, `llm_model` and `model_name` can be edited to match your specific configuration details. ```json @@ -156,7 +423,7 @@ In addition to the `OPENAI_API_KEY`, `llm_model` and `model_name` can be edited } ``` -* Google GenAI +#### Google GenAI Get your Gemini API key via https://aistudio.google.com/app/apikey. @@ -186,7 +453,7 @@ Get your Gemini API key via https://aistudio.google.com/app/apikey. } ``` -* GCP VertexAI +#### GCP VertexAI Follow the GCP authentication information found here: https://cloud.google.com/docs/authentication/application-default-credentials#GAC and create a Service Account with VertexAI credentials. Then add the following to the docker run command: @@ -216,7 +483,7 @@ And your JSON config should follow as: } ``` -* Azure +#### Azure In addition to the `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_API_KEY`, and `azure_deployment`, `llm_model` and `model_name` can be edited to match your specific configuration details. @@ -253,7 +520,7 @@ In addition to the `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_API_KEY`, and `azure_d } ``` -* AWS Bedrock +#### AWS Bedrock ```json { @@ -269,7 +536,7 @@ In addition to the `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_API_KEY`, and `azure_d }, "completion_service": { "llm_service": "bedrock", - "llm_model": "anthropic.claude-3-5-haiku-20241022-v1:0", + "llm_model": "us.anthropic.claude-3-7-sonnet-20250219-v1:0", "region_name":"us-west-2", "authentication_configuration": { "AWS_ACCESS_KEY_ID": "ACCESS_KEY", @@ -284,7 +551,7 @@ In addition to the `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_API_KEY`, and `azure_d } ``` -* Ollama +#### Ollama ```json { @@ -310,7 +577,7 @@ In addition to the `AZURE_OPENAI_ENDPOINT`, `AZURE_OPENAI_API_KEY`, and `azure_d } ``` -* Hugging Face +#### Hugging Face Example configuration for a model on Hugging Face with a dedicated endpoint is shown below. Please specify your configuration details: @@ -367,7 +634,7 @@ Example configuration for a model on Hugging Face with a serverless endpoint is } ``` -* Groq +#### Groq ```json { @@ -394,67 +661,13 @@ Example configuration for a model on Hugging Face with a serverless endpoint is } ``` -### DB configuration -Copy the below into `configs/server_config.json` and edit the `hostname` and `getToken` fields to match your database's configuration. If token authentication is enabled in TigerGraph, set `getToken` to `true`. Set the timeout, memory threshold, and thread limit parameters as desired to control how much of the database's resources are consumed when answering a question. - -```json -{ - "db_config": { - "hostname": "http://tigergraph", - "restppPort": "9000", - "gsPort": "14240", - "getToken": false, - "default_timeout": 300, - "default_mem_threshold": 5000, - "default_thread_limit": 8 - } -} -``` - -### GraphRAG configuration -Copy the below code into `configs/server_config.json`. You shouldn’t need to change anything unless you change the port of the chat history service in the Docker Compose file. - -`reuse_embedding` to `true` will skip re-generating the embedding if it already exists. -`ecc` and `chat_history_api` are the addresses of internal components of GraphRAG.If you use the Docker Compose file as is, you don’t need to change them. - -```json -{ - "graphrag_config": { - "reuse_embedding": false, - "ecc": "http://eventual-consistency-service:8001", - "chat_history_api": "http://chat-history:8002" - } -} -``` - -### Chat configuration -Copy the below code into `configs/server_config.json`. You shouldn’t need to change anything unless you change the port of the chat history service in the Docker Compose file. - -```json -{ - "chat-history": { - "apiPort":"8002", - "dbPath": "chats.db", - "dbLogPath": "db.log", - "logPath": "requestLogs.jsonl", - "conversationAccessRoles": ["superuser", "globaldesigner"] - } -} -``` - -### Enable openCypher Query Generation in InquiryAI -If you would like to enable openCypher query generation in InquiryAI, you can set the `USE_CYPHER` environment variable to `"true"` in the GraphRAG service in the docker compose file. By default, this is set to `"false"`. **Note**: openCypher query generation is still in beta and may not work as expected, as well as increases the potential of hallucinated answers due to bad code generation. Use with caution, and only in non-production environments. - -## Using TigerGraph GraphRAG - -GraphRAG is friendly to both technical and non-technical users. There is a graphical chat interface as well as API access to GraphRAG. Function-wise, GraphRAG can answer your questions by calling existing queries in the database (InquiryAI), build a knowledge graph from your documents (SupportAI), and answer knowledge questions based on your documents (SupportAI). +[Go back to top](#top) -Please visit [GraphRAG Tutorial](https://github.com/tigergraph/ecosys/blob/master/tutorials/GraphRAG.md) for a detailed demo. ## Customization and Extensibility TigerGraph GraphRAG is designed to be easily extensible. The service can be configured to use different LLM providers, different graph schemas, and different LangChain tools. The service can also be extended to use different embedding services, different LLM generation services, and different LangChain tools. For more information on how to extend the service, see the [Developer Guide](./docs/DeveloperGuide.md). -### Test Code Changes +### Test Your Code Changes A family of tests are included under the `tests` directory. If you would like to add more tests please refer to the [guide here](./docs/DeveloperGuide.md#adding-a-new-test-suite). A shell script `run_tests.sh` is also included in the folder which is the driver for running the tests. The easiest way to use this script is to execute it in the Docker Container for testing. #### Testing with Pytest @@ -467,7 +680,7 @@ python -m pytest cd .. ``` -#### Test in Docker Container +#### Test Code Change in Docker Container First, make sure that all your LLM service provider configuration files are working properly. The configs will be mounted for the container to access. Also make sure that all the dependencies such as database are ready. If not, you can run the included docker compose file to create those services. ```sh diff --git a/docs/data/ExportedGraph.zip b/docs/data/ExportedGraph.zip new file mode 100644 index 0000000..b9e69c9 Binary files /dev/null and b/docs/data/ExportedGraph.zip differ diff --git a/docs/notebooks/data/tg_tutorials.jsonl b/docs/data/tg_tutorials.jsonl similarity index 100% rename from docs/notebooks/data/tg_tutorials.jsonl rename to docs/data/tg_tutorials.jsonl diff --git a/docs/img/ChatLogin.jpg b/docs/img/ChatLogin.jpg new file mode 100644 index 0000000..9fbca46 Binary files /dev/null and b/docs/img/ChatLogin.jpg differ diff --git a/docs/img/DemoQuestion.jpg b/docs/img/DemoQuestion.jpg new file mode 100644 index 0000000..d02d4d9 Binary files /dev/null and b/docs/img/DemoQuestion.jpg differ diff --git a/docs/img/SupportAI-Architecture.png b/docs/img/GraphRAG-Architecture.png similarity index 100% rename from docs/img/SupportAI-Architecture.png rename to docs/img/GraphRAG-Architecture.png diff --git a/docs/img/Inquiry.jpg b/docs/img/Inquiry.jpg new file mode 100644 index 0000000..4427ed5 Binary files /dev/null and b/docs/img/Inquiry.jpg differ diff --git a/docs/img/InquiryAI-Architecture.png b/docs/img/InquiryAI-Architecture.png deleted file mode 100644 index 20012d5..0000000 Binary files a/docs/img/InquiryAI-Architecture.png and /dev/null differ diff --git a/docs/img/NatureLanguageQuery-Architecture.png b/docs/img/NatureLanguageQuery-Architecture.png new file mode 100644 index 0000000..b8b6207 Binary files /dev/null and b/docs/img/NatureLanguageQuery-Architecture.png differ diff --git a/docs/img/RAGConfig.jpg b/docs/img/RAGConfig.jpg new file mode 100644 index 0000000..dd93402 Binary files /dev/null and b/docs/img/RAGConfig.jpg differ diff --git a/docs/img/TG-GraphRAG-Architecture.png b/docs/img/TG-GraphRAG-Architecture.png deleted file mode 100644 index 7bfc3b1..0000000 Binary files a/docs/img/TG-GraphRAG-Architecture.png and /dev/null differ diff --git a/docs/img/TG-GraphRAG-Overview.png b/docs/img/TG-GraphRAG-Overview.png new file mode 100644 index 0000000..732765c Binary files /dev/null and b/docs/img/TG-GraphRAG-Overview.png differ diff --git a/docs/notebooks/GraphRAGDemo.ipynb b/docs/notebooks/GraphRAGDemo.ipynb index 96e444c..dcae4a6 100644 --- a/docs/notebooks/GraphRAGDemo.ipynb +++ b/docs/notebooks/GraphRAGDemo.ipynb @@ -119,7 +119,7 @@ "source": [ "res = conn.ai.createDocumentIngest(\n", " data_source=\"local\",\n", - " data_source_config={\"data_path\": \"./data/tg_tutorials.jsonl\"},\n", + " data_source_config={\"data_path\": \"../data/tg_tutorials.jsonl\"},\n", " loader_config={\"doc_id_field\": \"doc_id\", \"content_field\": \"content\", \"doc_type\": \"markdown\"},\n", " file_format=\"json\",\n", ")\n", diff --git a/docs/tutorials/GraphRAGDemo.ipynb b/docs/tutorials/GraphRAGDemo.ipynb new file mode 100644 index 0000000..d05aaee --- /dev/null +++ b/docs/tutorials/GraphRAGDemo.ipynb @@ -0,0 +1,471 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Using TigerGraph GraphRAG for Document Question Answering\n", + "\n", + "This notebook demostrates how to use TigerGraph GraphRAG, an AI assistant for your TigerGraph databases. TigerGraph GraphRAG enables you to ask questions in natural language about your document data stored in TigerGraph and get answers in a human-readable format. GraphRAG is a graph-based retrieval-augmented generation approach that is used to answer questions about the document data stored in TigerGraph. TigerGraph GraphRAG is built to help users get started with GraphRAG and to provide a seamless experience for users to interact with their document data within TigerGraph." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%pip install pyTigerGraph, dotenv\n", + "\n", + "import os\n", + "from pyTigerGraph import TigerGraphConnection\n", + "from dotenv import load_dotenv\n", + "\n", + "load_dotenv()\n", + "# We first create a connection to the TigerGraph database\n", + "tg_host = \"http://localhost\" \n", + "username = os.getenv(\"USERNAME\", \"tigergraph\")\n", + "password = os.getenv(\"PASS\", \"tigergraph\")\n", + "conn = TigerGraphConnection(\n", + " host=tg_host,\n", + " username=username,\n", + " password=password,\n", + " gsPort=\"14240\",\n", + " restppPort=\"14240\",\n", + " graphname = \"TigerGraphRAG\"\n", + ")\n", + "\n", + "# And then add GraphRAG's address to the connection. This address\n", + "# is the host's address where the GraphRAG container is running.\n", + "graphrag_host = \"http://localhost\"\n", + "conn.ai.configureGraphRAGHost(f\"{graphrag_host}:8000\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a Graph and Ingest Data\n", + "\n", + "We provide utilities to setup your TigerGraph database with a schema and load your desired documents. In this example, we are utilizing the TigerGraph documentation as our dataset. The documents are processed into a JSONL file of the following format:\n", + "\n", + "```json\n", + "{\"doc_id\": \"id_for_document_here\", \"content\": \"Text content of the document\"}\n", + "```\n", + "\n", + "The following code block will create a graph called `TigerGraphRAG` and load the documents into the graph. The schema that is created looks like this:\n", + "\n", + "![graphrag_schema](./pictures/GraphRAGSchema.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create Graph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.gsql(f\"\"\"CREATE GRAPH {conn.graphname}()\"\"\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Get connection token if authentication is enabled" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# We need to authenticate the connection if restpp authentication is enabled\n", + "conn.getToken()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create SuportAI schema and install related queries" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.initializeSupportAI()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create DocumentIngest for local file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "res = conn.ai.createDocumentIngest(\n", + " data_source=\"local\",\n", + " data_source_config={\"data_path\": \"./data/tg_tutorials.jsonl\"},\n", + " loader_config={\"doc_id_field\": \"doc_id\", \"content_field\": \"content\", \"doc_type\": \"markdown\"},\n", + " file_format=\"json\",\n", + ")\n", + "print(res)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run DocumentIngest to load documents to graph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.runDocumentIngest(res[\"load_job_id\"], res[\"data_source_id\"], res[\"data_path\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, create and run DocumentIngest for data files on Cloud storage" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "access = \"\"\n", + "sec = \"\"\n", + "res = conn.ai.createDocumentIngest(\n", + " data_source=\"s3\",\n", + " data_source_config={\"aws_access_key\": access, \"aws_secret_key\": sec},\n", + " loader_config={\"doc_id_field\": \"url\", \"content_field\": \"content\", \"doc_type\": \"\"},\n", + " file_format=\"json\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.runDocumentIngest(res[\"load_job_id\"], res[\"data_source_id\"], \"s3://tg-documentation/pytg_current/pytg_current.jsonl\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build Knowledge Graph from the documents loaded" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.forceConsistencyUpdate(\"graphrag\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comparing Document Search Methods\n", + "\n", + "TigerGraph GraphRAG provides multiple methods to search documents in the graph. The methods are:\n", + "- **Hybrid Search**: This method uses a combination of vector search and graph traversal to find the most relevant information to the query. It uses the selected algorithm to search the embeddings of documents, document chunks, entities, and relationships. These results serve as the starting point for the graph traversal. The graph traversal is used to find the most relevant information to the query.\n", + "\n", + "- **Similarity Search**: This method uses the selected algorithm to search the embeddings of one of the document, document chunk, entity, or relationship vector indices. It returns the most relevant information to the query based on the embeddings. This method is what you would expect from a traditional vector RAG solution.\n", + "\n", + "- **Sibling Search**: This method is very similar to the Vector Search method, but it uses the sibling (IS_AFTER) relationships between document chunks to expand the context around the document chunk that is most relevant to the query. This method is useful when you want to get more context around the most relevant document chunk." + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "metadata": {}, + "outputs": [], + "source": [ + "query = \"How do I get the vertex count from TigerGrpah using Python?\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Hybrid Search in TigerGraph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.searchDocuments(query,\n", + " method=\"hybrid\",\n", + " method_parameters = {\"indices\": [\"DocumentChunk\", \"Entity\"],\n", + " \"top_k\": 5,\n", + " \"num_hops\": 2,\n", + " \"num_seen_min\": 3,\n", + " \"verbose\": False})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Document Chunk Similarity Search" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.searchDocuments(query,\n", + " method=\"similarity\",\n", + " method_parameters={\"index\": \"DocumentChunk\",\n", + " \"top_k\": 5,\n", + " \"withHyDE\": False,\n", + " \"verbose\": False})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sibling Document Chunk Similarity Search" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.searchDocuments(query,\n", + " method=\"sibling\",\n", + " method_parameters={\"index\": \"DocumentChunk\",\n", + " \"top_k\": 5,\n", + " \"lookahead\": 3,\n", + " \"lookback\": 3,\n", + " \"withHyDE\": False,\n", + " \"verbose\": False})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### GraphRAG Document Chunk Community Search" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "conn.ai.searchDocuments(query,\n", + " method=\"graphrag\",\n", + " method_parameters={\"community_level\": 2, \"top_k\": 3, \"verbose\": True})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comparing LLM Generated Responses\n", + "\n", + "TigerGraph GraphRAG provides a way to generate the response to the user's query using a LLM, based on the search results from the methods above. You can compare the responses generated by the LLM for each of the search methods to see which one is the most relevant to the user's query. In this example, we can see that the Hybrid Search method generates the most relevant response to the user's query. While none of the responses were wrong, the Hybrid Search method generated the most relevant response to the user's query, by suggesting to use the `getVertexCount()` function to get the number of vertices in the graph." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "resp = conn.ai.answerQuestion(query,\n", + " method=\"graphrag\",\n", + " method_parameters={\"community_level\": 2, \"top_k\": 3, \"verbose\": True})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(resp[\"response\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check verbose info for more details if needed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "print(json.dumps(resp[\"verbose\"], indent=4))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Answer question using Hybrid Search" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "resp = conn.ai.answerQuestion(query,\n", + " method=\"hybrid\",\n", + " method_parameters = {\"indices\": [\"DocumentChunk\", \"Entity\"],\n", + " \"top_k\": 5,\n", + " \"num_hops\": 2,\n", + " \"num_seen_min\": 3,\n", + " \"verbose\": True})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(resp[\"response\"])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(resp[\"retrieved\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Answer question using Similarity Search" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "resp = conn.ai.answerQuestion(query,\n", + " method=\"similarity\",\n", + " method_parameters={\"index\": \"DocumentChunk\",\n", + " \"top_k\": 5,\n", + " \"withHyDE\": False})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(resp[\"response\"])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Answer question using Sibling Search" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "resp = conn.ai.answerQuestion(query,\n", + " method=\"sibling\",\n", + " method_parameters={\"index\": \"DocumentChunk\",\n", + " \"top_k\": 5,\n", + " \"lookahead\": 3,\n", + " \"lookback\": 3,\n", + " \"withHyDE\": False})" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(resp[\"response\"])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "copi", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/docs/tutorials/answer_question.py b/docs/tutorials/answer_question.py new file mode 100644 index 0000000..5f494c2 --- /dev/null +++ b/docs/tutorials/answer_question.py @@ -0,0 +1,49 @@ +import os +from pyTigerGraph import TigerGraphConnection + +host = "http://localhost" + +username = "tigergraph" +password = "tigergraph" + +# We first create a connection to the database +conn = TigerGraphConnection( + host=host, + username=username, + password=password, + restppPort=14240 + ) + +conn.graphname = "TigerGraphRAG" + +# And then add GraphRAG's address to the connection. This address +# is the host's address where the GraphRAG container is running. +conn.ai.configureGraphRAGHost(f"{host}:8000") + +query = "how to load data to tigergraph vector store, give an example in Python" +print(f"""Fetching answer for question: {query}""") + +resp = conn.ai.answerQuestion( + query, + method="hybrid", + method_parameters = { + "indices": ["Document", "DocumentChunk", "Entity", "Relationship"], + "top_k": 2, + "num_hops": 2, + "num_seen_min": 2, + "verbose": True + }) + +print(f"""\nAnswer using Hybrid Search:\n{resp["response"]}""") + +resp = conn.ai.answerQuestion( + query, + method="community", + method_parameters={ + "community_level": 2, + "combine": False, + "top_k": 5, + "verbose": True + }) + +print(f"""\nAnswer using Community Search:\n{resp["response"]}""") diff --git a/docs/tutorials/configs/nginx.conf b/docs/tutorials/configs/nginx.conf new file mode 100644 index 0000000..9a0fe5f --- /dev/null +++ b/docs/tutorials/configs/nginx.conf @@ -0,0 +1,32 @@ +server { + listen 80; + + location / { + proxy_pass http://graphrag-ui:3000; + } + + location /chat- { + proxy_pass http://graphrag-ui:3000; + } + + location /chat { + proxy_pass http://graphrag-ui:3000/; + } + + + location /chat-dialog { + proxy_pass http://graphrag-ui:3000/; + } + + location ~^/ui/.*/chat$ { + proxy_pass http://graphrag:8000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_read_timeout 86400; + } + + location /ui/ { + proxy_pass http://graphrag:8000; + } +} diff --git a/docs/tutorials/configs/server_config.json b/docs/tutorials/configs/server_config.json new file mode 100644 index 0000000..f1c8907 --- /dev/null +++ b/docs/tutorials/configs/server_config.json @@ -0,0 +1,47 @@ +{ + "db_config": { + "hostname": "http://tigergraph", + "restppPort": "14240", + "gsPort": "14240", + "getToken": false, + "default_timeout": 300, + "default_mem_threshold": 5000, + "default_thread_limit": 8 + }, + "graphrag_config": { + "reuse_embedding": false, + "ecc": "http://graphrag-ecc:8001", + "chat_history_api": "http://chat-history:8002", + "chunker_config": {} + }, + "llm_config": { + "embedding_service": { + "model_name": "text-embedding-3-small", + "embedding_model_service": "openai", + "authentication_configuration": { + "OPENAI_API_KEY": "YOUR_OPENAI_API_KEY_HERE" + } + }, + "completion_service": { + "llm_service": "openai", + "llm_model": "gpt-4.1-mini", + "authentication_configuration": { + "OPENAI_API_KEY": "YOUR_OPENAI_API_KEY_HERE" + }, + "model_kwargs": { + "temperature": 0 + }, + "prompt_path": "./common/prompts/openai_gpt4/" + } + }, + "chat_config": { + "apiPort": "8002", + "dbPath": "chats.db", + "dbLogPath": "db.log", + "logPath": "requestLogs.jsonl", + "conversationAccessRoles": [ + "superuser", + "globaldesigner" + ] + } +} diff --git a/docs/tutorials/data b/docs/tutorials/data new file mode 120000 index 0000000..4909e06 --- /dev/null +++ b/docs/tutorials/data @@ -0,0 +1 @@ +../data \ No newline at end of file diff --git a/docs/tutorials/docker-compose-tg.yml b/docs/tutorials/docker-compose-tg.yml new file mode 100644 index 0000000..19d6588 --- /dev/null +++ b/docs/tutorials/docker-compose-tg.yml @@ -0,0 +1,74 @@ +services: + graphrag: + image: tigergraph/graphrag:latest + platform: linux/amd64 + container_name: graphrag + build: + context: . + dockerfile: graphrag/Dockerfile + ports: + - 8000:8000 + depends_on: + - graphrag-ecc + - chat-history + environment: + SERVER_CONFIG: "/code/configs/server_config.json" + LOGLEVEL: "INFO" + USE_CYPHER: "true" + volumes: + - ./configs/:/code/configs + + graphrag-ecc: + image: tigergraph/graphrag-ecc:latest + platform: linux/amd64 + container_name: graphrag-ecc + build: + context: . + dockerfile: ecc/Dockerfile + ports: + - 8001:8001 + environment: + SERVER_CONFIG: "/code/configs/server_config.json" + LOGLEVEL: "INFO" + INIT_EMBED_STORE: "false" + volumes: + - ./configs/:/code/configs + + chat-history: + image: tigergraph/chat-history:latest + platform: linux/amd64 + container_name: chat-history + build: + context: chat-history/ + dockerfile: Dockerfile + ports: + - 8002:8002 + environment: + CONFIG_FILES: "/configs/server_config.json" + LOGLEVEL: "INFO" + volumes: + - ./configs/:/configs + + graphrag-ui: + image: tigergraph/graphrag-ui:latest + platform: linux/amd64 + container_name: graphrag-ui + build: + context: graphrag-ui + dockerfile: Dockerfile + ports: + - 3000:3000 + depends_on: + - graphrag + + nginx: + container_name: nginx + image: nginx + volumes: + - ./configs/nginx.conf:/etc/nginx/conf.d/default.conf + ports: + - "80:80" + depends_on: + - graphrag-ui + - graphrag + diff --git a/docs/tutorials/docker-compose.yml b/docs/tutorials/docker-compose.yml new file mode 100644 index 0000000..8be754b --- /dev/null +++ b/docs/tutorials/docker-compose.yml @@ -0,0 +1,86 @@ +services: + graphrag: + image: tigergraph/graphrag:latest + platform: linux/amd64 + container_name: graphrag + build: + context: . + dockerfile: graphrag/Dockerfile + ports: + - 8000:8000 + depends_on: + - graphrag-ecc + - chat-history + - tigergraph + environment: + SERVER_CONFIG: "/code/configs/server_config.json" + LOGLEVEL: "INFO" + USE_CYPHER: "true" + volumes: + - ./configs/:/code/configs + + graphrag-ecc: + image: tigergraph/graphrag-ecc:latest + platform: linux/amd64 + container_name: graphrag-ecc + build: + context: . + dockerfile: ecc/Dockerfile + ports: + - 8001:8001 + environment: + SERVER_CONFIG: "/code/configs/server_config.json" + LOGLEVEL: "INFO" + INIT_EMBED_STORE: "false" + volumes: + - ./configs/:/code/configs + + chat-history: + image: tigergraph/chat-history:latest + platform: linux/amd64 + container_name: chat-history + build: + context: chat-history/ + dockerfile: Dockerfile + ports: + - 8002:8002 + environment: + CONFIG_FILES: "/configs/server_config.json" + LOGLEVEL: "INFO" + volumes: + - ./configs/:/configs + + graphrag-ui: + image: tigergraph/graphrag-ui:latest + platform: linux/amd64 + container_name: graphrag-ui + build: + context: graphrag-ui + dockerfile: Dockerfile + ports: + - 3000:3000 + depends_on: + - graphrag + + nginx: + container_name: nginx + image: nginx + volumes: + - ./configs/nginx.conf:/etc/nginx/conf.d/default.conf + ports: + - "80:80" + depends_on: + - graphrag-ui + - graphrag + + tigergraph: + image: tigergraph/community:4.2.1 + container_name: tigergraph + platform: linux/amd64 + ports: + - "14240:14240" + volumes: + - tigergraph_data:/home/tigergraph/tigergraph/data + +volumes: + tigergraph_data: diff --git a/docs/tutorials/graphrag-k8s.yml b/docs/tutorials/graphrag-k8s.yml new file mode 100644 index 0000000..f1e3233 --- /dev/null +++ b/docs/tutorials/graphrag-k8s.yml @@ -0,0 +1,322 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: graphrag + +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: tigergraph-data +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tigergraph +spec: + replicas: 1 + selector: + matchLabels: + app: tigergraph + template: + metadata: + labels: + app: tigergraph + spec: + containers: + - name: tigergraph + image: tigergraph/community:4.2.2 + imagePullPolicy: IfNotPresent + ports: + - containerPort: 14240 + volumeMounts: + - mountPath: /home/tigergraph/tigergraph/data + name: tigergraph-storage + volumes: + - name: tigergraph-storage + persistentVolumeClaim: + claimName: tigergraph-data +--- +apiVersion: v1 +kind: Service +metadata: + name: tigergraph +spec: + selector: + app: tigergraph + ports: + - protocol: TCP + port: 14240 + targetPort: 14240 + type: ClusterIP + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: graphrag + namespace: graphrag +spec: + replicas: 1 + selector: + matchLabels: + app: graphrag + template: + metadata: + labels: + app: graphrag + spec: + containers: + - name: graphrag + image: tigergraph/graphrag:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8000 + env: + - name: SERVER_CONFIG + value: "/code/configs/server_config.json" + - name: LOGLEVEL + value: "INFO" + - name: USE_CYPHER + value: "true" + volumeMounts: + - name: configs + mountPath: /code/configs + volumes: + - name: configs + hostPath: + path: /path/to/graphrag/configs # <-- path on the node + type: DirectoryOrCreate + +--- +apiVersion: v1 +kind: Service +metadata: + name: graphrag + namespace: graphrag +spec: + selector: + app: graphrag + ports: + - port: 8000 + targetPort: 8000 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: graphrag-ecc + namespace: graphrag +spec: + replicas: 1 + selector: + matchLabels: + app: graphrag-ecc + template: + metadata: + labels: + app: graphrag-ecc + spec: + containers: + - name: graphrag-ecc + image: tigergraph/graphrag-ecc:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8001 + env: + - name: SERVER_CONFIG + value: "/code/configs/server_config.json" + - name: LOGLEVEL + value: "INFO" + - name: INIT_EMBED_STORE + value: "false" + volumeMounts: + - name: configs + mountPath: /code/configs + volumes: + - name: configs + hostPath: + path: /path/to/graphrag/configs + type: DirectoryOrCreate + +--- +apiVersion: v1 +kind: Service +metadata: + name: graphrag-ecc + namespace: graphrag +spec: + selector: + app: graphrag-ecc + ports: + - port: 8001 + targetPort: 8001 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: chat-history + namespace: graphrag +spec: + replicas: 1 + selector: + matchLabels: + app: chat-history + template: + metadata: + labels: + app: chat-history + spec: + containers: + - name: chat-history + image: tigergraph/chat-history:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 8002 + env: + - name: CONFIG_FILES + value: "/configs/server_config.json" + - name: LOGLEVEL + value: "INFO" + volumeMounts: + - name: configs + mountPath: /configs + volumes: + - name: configs + hostPath: + path: /path/to/graphrag/configs + type: DirectoryOrCreate + +--- +apiVersion: v1 +kind: Service +metadata: + name: chat-history + namespace: graphrag +spec: + selector: + app: chat-history + ports: + - port: 8002 + targetPort: 8002 + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: graphrag-ui + namespace: graphrag +spec: + replicas: 1 + selector: + matchLabels: + app: graphrag-ui + template: + metadata: + labels: + app: graphrag-ui + spec: + containers: + - name: graphrag-ui + image: tigergraph/graphrag-ui:latest + imagePullPolicy: IfNotPresent + ports: + - containerPort: 3000 + +--- +apiVersion: v1 +kind: Service +metadata: + name: graphrag-ui + namespace: graphrag +spec: + selector: + app: graphrag-ui + ports: + - port: 3000 + targetPort: 3000 + +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: graphrag-ingress + namespace: graphrag + annotations: + nginx.ingress.kubernetes.io/use-regex: "true" + nginx.ingress.kubernetes.io/proxy-read-timeout: "86400" + nginx.ingress.kubernetes.io/proxy-http-version: "1.1" + nginx.ingress.kubernetes.io/proxy-set-headers: "Upgrade=$http_upgrade,Connection=Upgrade" +spec: + ingressClassName: nginx + rules: + - http: + paths: + # /chat-, /chat, /chat-dialog + - path: /chat- + pathType: Prefix + backend: + service: + name: graphrag-ui + port: + number: 3000 + + - path: /chat + pathType: Prefix + backend: + service: + name: graphrag-ui + port: + number: 3000 + + # Regex path: /.+/graphrag/.+ + - path: /.+/graphrag/.+ + pathType: ImplementationSpecific + backend: + service: + name: graphrag + port: + number: 8000 + + # Regex path: /.+/supportai/.+ + - path: /.+/supportai/.+ + pathType: ImplementationSpecific + backend: + service: + name: graphrag + port: + number: 8000 + + # Regex path: /ui/.*/chat + - path: /ui/.*/chat + pathType: ImplementationSpecific + backend: + service: + name: graphrag + port: + number: 8000 + + # /ui/ fallback + - path: /ui/ + pathType: Prefix + backend: + service: + name: graphrag + port: + number: 8000 + + # Root path + - path: / + pathType: Prefix + backend: + service: + name: graphrag-ui + port: + number: 3000 diff --git a/docs/tutorials/graphrag_demo.sh b/docs/tutorials/graphrag_demo.sh new file mode 100755 index 0000000..266f733 --- /dev/null +++ b/docs/tutorials/graphrag_demo.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +if ! python --version 2>&1 | grep "Python 3\.1.\." >/dev/null; then + echo "Python 3.11+ is needed, please check Python version or use virutal environment" + exit 1 +fi + +if ! pip freeze 2>&1 | grep pyTigerGraph >/dev/null; then + echo "pyTigerGraph is needed, please install it by running: pip install pyTigerGraph" + exit 2 +fi + +echo "Initializing GraphRAG. It may take 5 to 10 minutes." +python ./init_graphrag.py + +current_stage= +while :; do + stage=$(docker logs graphrag-ecc 2>&1 | grep "Processing Start\|DONE. graphrag.run" | tail -1) + if [[ -n "$stage" && ! "$stage" == "$current_stage" ]]; then + if [[ "$stage" =~ Processing ]]; then + echo $stage | cut -d ' ' -f5-7 + elif [[ "$stage" =~ Done ]]; then + echo "GraphRAG initialization is done." + break + fi + fi + current_stage=$stage + sleep 5 +done + +python ./answer_question.py diff --git a/docs/tutorials/init_graphrag.py b/docs/tutorials/init_graphrag.py new file mode 100644 index 0000000..76f36a9 --- /dev/null +++ b/docs/tutorials/init_graphrag.py @@ -0,0 +1,38 @@ +import os +import json +from pyTigerGraph import TigerGraphConnection + +def create_graph(conn: TigerGraphConnection): + conn.gsql(f"""CREATE GRAPH {conn.graphname}()""") + conn.ai.initializeGraphRAG() + +def load_data(conn: TigerGraphConnection): + res = conn.ai.createDocumentIngest( + data_source="local", + data_source_config={"data_path": "./data/tg_tutorials.jsonl"}, + loader_config={"doc_id_field": "doc_id", "content_field": "content", "doc_type": "markdown"}, + file_format="json", + ) + conn.ai.runDocumentIngest(res["load_job_id"], res["data_source_id"], res["data_path"]) + +def update_graphrag(conn: TigerGraphConnection): + conn.ai.forceConsistencyUpdate("graphrag") + +if __name__ == "__main__": + + # We first create a connection to the database + conn = TigerGraphConnection( + host="http://localhost", + username="tigergraph", + password="tigergraph", + restppPort="14240", + ) + conn.graphname = "TigerGraphRAG" + + # And then add GraphRAG's address to the connection. This address + # is the host's address where the GraphRAG container is running. + conn.ai.configureGraphRAGHost("http://localhost:8000") + + create_graph(conn) + load_data(conn) + update_graphrag(conn) diff --git a/docs/tutorials/setup_graphrag.sh b/docs/tutorials/setup_graphrag.sh new file mode 100755 index 0000000..1bebb09 --- /dev/null +++ b/docs/tutorials/setup_graphrag.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +if ! which curl >/dev/null; then + echo "cURL is not found, please install it and retry." + exit 1 +fi + +if ! docker compose >/dev/null; then + echo "Docker Compose plugin is not working properly, please resolve it and retry." + echo "Refer to https://docs.docker.com/compose/install/linux/ for more installation instructions." + exit 2 +fi + +if ! docker images | grep tigergraph/community >/dev/null; then + echo "TigerGraph Community version docker image is not found, please download from https://dl.tigergraph.com/ and load it." + exit 3 +fi + +tg_version=$(docker images | grep tigergraph/community | awk '{print $2}' | sort -Vr | head -1) +if [[ -z "$tg_version" || ! "$tg_version" =~ ^4\.[23]\. ]]; then + echo "TigerGraph version is not compatible, please use 4.2.0+" + exit 4 +fi + +root_dir=${1:-./graphrag} +tg_username=$(echo ${2:-tigergraph} | sed 's/[][\/.^$*+?|(){}]/\\&/g') +tg_password=$(echo ${3:-tigergraph} | sed 's/[][\/.^$*+?|(){}]/\\&/g') + +mkdir -p $root_dir || true +[[ -d $root_dir ]] || (echo "Target dir $root_dir is not found!" && exit 5) + +echo "Entering GraphRAG root dir: $root_dir" +cd $root_dir || (echo "Cannot switch to $root_dir!" && exit 6) + +echo "Downloading GraphRAG sevice config..." +mkdir -p configs || true +curl -s https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/main/docs/tutorials/docker-compose.yml | sed "s/community:4.2.1/community:${tg_version}/g" > docker-compose.yml +curl -s https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/main/docs/tutorials/nginx.conf -o configs/nginx.conf +curl -s https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/main/docs/tutorials/server_config.json | sed '/"gsPort": "14240"/a\ + "username": "'${tg_username}'",\ + "password": "'${tg_password}'", +' > configs/server_config.json + +echo "Starting GraphRAG sevices.." +docker compose up -d +sleep 5 + +echo "Checking service status..." +if ! curl -s http://localhost:14240/restpp/version >/dev/null; then + docker exec -it tigergraph /home/tigergraph/tigergraph/app/cmd/gadmin start all >/dev/null + docker compose up -d >/dev/null + sleep 5 +fi + +if ! docker ps | grep "tigergraph/graphrag:latest" >/dev/null; then + echo "Failed to start GraphRAG service." + echo 'Please double check tigergraph username and password in configs/server_config.json, and re-run `docker compose up -d`' + echo 'Or check log via `docker logs graphrag` for detailed failure.' +else + echo "GraphRAG service started successfully." + echo "Visit http://localhost to access the chatbot." +fi +cd - >/dev/null + diff --git a/docs/tutorials/setup_graphrag_tg.sh b/docs/tutorials/setup_graphrag_tg.sh new file mode 100755 index 0000000..294332f --- /dev/null +++ b/docs/tutorials/setup_graphrag_tg.sh @@ -0,0 +1,73 @@ +#!/bin/bash + +if ! which curl >/dev/null; then + echo "cURL is not found, please install it and retry." + exit 1 +fi + +if ! docker compose >/dev/null; then + echo "Docker Compose plugin is not working properly, please resolve it and retry." + echo "Refer to https://docs.docker.com/compose/install/linux/ for more installation instructions." + exit 2 +fi + +root_dir=${1:-./graphrag} +tg_host=${2:-http://tigergraph} +tg_port=${3:-14240} +tg_username=$(echo ${4:-tigergraph} | sed 's/[][\/.^$*+?|(){}]/\\&/g') +tg_password=$(echo ${5:-tigergraph} | sed 's/[][\/.^$*+?|(){}]/\\&/g') + +if ! [[ "$tg_host" =~ ^http[s]?:// ]]; then + if [[ "$tg_port" == "443" ]]; then + tg_host="https://${tg_host}" + else + tg_host="http://${tg_host}" + fi + echo "Rewriting tg_host to ${tg_host} based on tg_port: ${tg_port}" +fi + +if ! [[ "$tg_host" =~ ^http[s]?://tigergraph ]]; then + pong=$(curl -s ${tg_host}:${tg_port}/api/ping) + if ! echo $pong | grep "pong" >/dev/null; then + echo "Cannot connect to TigerGraph instance at ${tg_host}:${tg_port}" + exit 3 + fi +fi + +mkdir -p $root_dir || true +[[ -d $root_dir ]] || (echo "Target dir $root_dir is not found!" && exit 5) + +echo "Entering GraphRAG root dir: $root_dir" +cd $root_dir || (echo "Cannot switch to $root_dir!" && exit 6) + +echo "Downloading GraphRAG sevice config..." +mkdir -p configs || true +curl -s https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/main/docs/tutorials/docker-compose-tg.yml | sed "s/community:4.2.1/community:${tg_version}/g" > docker-compose.yml +curl -s https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/main/docs/tutorials/nginx.conf -o configs/nginx.conf +curl -s https://raw.githubusercontent.com/tigergraph/graphrag/refs/heads/main/docs/tutorials/server_config.json | sed '/"gsPort": "14240"/a\ + "username": "'${tg_username}'",\ + "password": "'${tg_password}'", +' | sed "s#http://tigergraph#${tg_host}#g; s/14240/${tg_port}/g"> configs/server_config.json + +exit +echo "Starting GraphRAG sevices.." +docker compose up -d +sleep 5 + +echo "Checking service status..." +if ! curl -s http://localhost:14240/restpp/version >/dev/null; then + docker exec -it tigergraph /home/tigergraph/tigergraph/app/cmd/gadmin start all >/dev/null + docker compose up -d >/dev/null + sleep 5 +fi + +if ! docker ps | grep "tigergraph/graphrag:latest" >/dev/null; then + echo "Failed to start GraphRAG service." + echo 'Please double check tigergraph username and password in configs/server_config.json, and re-run `docker compose up -d`' + echo 'Or check log via `docker logs graphrag` for detailed failure.' +else + echo "GraphRAG service started successfully." + echo "Visit http://localhost to access the chatbot." +fi +cd - >/dev/null +