Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

88 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gsoc

D4CG

Contributor: Regina Huang

Email: huang.rong@northeastern.edu

Github profile: https://github.com/RongHuang14

LinkedIn: https://www.linkedin.com/in/ronghuang14/

Mentor: Jooho Lee

About

GraphQL Convertor is a GraphQL generation agent application built with Chainlit and FastAPI that converts natural language queries into GraphQL queries.

Overview: This project is a GraphQL generation agent that converts human language queries into GraphQL queries using AI. Below is the project workflow and code structure:

Workflow

├── README.md  
├── frontend_requirements.txt                  
├── backend_requirements.txt
├── .env                        # OpenAI key & postgresql url
│
├── src/    
│   ├── frontend/                
│   │   ├── chainlit_app.py     # Main Chainlit application
│   │   ├── chainlit.md         # Welcome page
│   │   └── run.sh              # Frontend startup script
│   │
│   ├── backend/                 
│   │   ├── app.py              # Main FastAPI application
│   │   ├── start.sh            # Backend startup script
│   │   ├── interactive_demo.sh 
│   │   └── utils/
│   │       ├── nested_graphql_helper.py  # utils for generating nested graphql
│   │       ├── prompt_builder.py    
│   │       ├── filter_utils.py      
│   │       ├── credential_helper.py  # Generate token for guppy/graphql API
│   │       ├── schema_parser.py    
│   │       ├── query_builder.py     
│   │       └── context_manager.py       
│   │
│   └── tests/                   
│       ├── test_db.py          
│       ├── test_queries.py     
│       ├── test_filter_utils.py 
│       ├── validate_graphql_generation.py
│       └── test_setup.py       
│
├── schema/                      
│   ├── gitops.json             # GraphQL schema content
│   ├── pcdc-schema-prod-*.json 
│   └── subject.json            
│
├── assets/                     

Getting Started

1. Installation

  1. After cloning the project, install dependencies:
    You need to build frontend env and backend env seperately, because gen3 and chainlit have version conflict on aiofiles.

Build frontend venv

python3 -m venv frontend_env
source frontend_env/bin/activate
pip install --upgrade pip
pip install -r frontend_requirements.txt

Build backend venv

python3 -m venv backend_env
source backend_env/bin/activate
pip install --upgrade pip
pip install -r backend_requirements.txt
  1. Set up your OpenAI API key in the .env file:
OPENAI_API_KEY=your_api_key_here
DATABASE_URL=postgresql://postgres:your_postgresql_address

2. Run the Application Backend

First, make sure you start the backend server in backend_env:

source backend_env/bin/activate
cd src/backend/
python -m uvicorn app:app --reload

The backend API will run at http://localhost:8000

Backend API Usage

cd src/backend/
1. Convert user input to flat GraphQL:
curl -X POST "http://localhost:8000/flat_graphql" \
     -H "Content-Type: application/json" \
     -d '{"text": "I want to query all male patients"}'
Example Response
{
    "query": "query ($filter: JSON) { _aggregation { subject(accessibility: all, filter: $filter) { consortium { histogram { key count } } race { histogram { key count } } _totalCount } } }",
    "variables": "{'AND': [{'IN': {'race': ['Asian']}}]}"
}
2. Convert user input to nested GraphQL:
curl -X POST "http://localhost:8000/nested_graphql" \
     -H "Content-Type: application/json" \
     -d '{"text": "The cohort consists of participants from the INRG consortium who have metastatic tumors. Specifically, these tumors are classified as absent and are located on the skin."}'
Example Response
{
  "AND": [
    {
      "IN": {
        "consortium": [
          "INRG"
        ]
      }
    },
    {
      "nested": {
        "AND": [
          {
            "IN": {
              "tumor_classification": [
                "Metastatic"
              ]
            }
          },
          {
            "IN": {
              "tumor_state": [
                "Absent"
              ]
            }
          },
          {
            "IN": {
              "tumor_site": [
                "Skin"
              ]
            }
          }
        ],
        "path": "tumor_assessments"
      }
    }
  ]
}
2. Get query GraphQL result:
Flat GraphQL Example
curl -X POST http://localhost:8000/query \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query ($filter: JSON) { _aggregation { subject(accessibility: all, filter: $filter) { consortium { histogram { key count } } sex { histogram { key count } } _totalCount } } }",
    "variables": {"filter": {"AND": [{"IN": {"sex": ["Male"]}}]}}
  }'
Example Response
{"data":{"_aggregation":{"subject":{"consortium":{"histogram":[{"key":"INSTRuCT","count":52},{"key":"NODAL","count":44},{"key":"INRG","count":42},{"key":"INTERACT","count":38},{"key":"HIBISCUS","count":37},{"key":"MaGIC","count":33},{"key":"ALL","count":32}]},"sex":{"histogram":[{"key":"Other","count":60},{"key":"Male","count":48},{"key":"Undifferentiated","count":45},{"key":"Female","count":43},{"key":"Unknown","count":35},{"key":"Not Reported","count":31},{"key":"no data","count":57}]},"_totalCount":319}}}}
Nested GraphQL Example (aggregation format)
curl -X POST http://localhost:8000/query \
  -H "Content-Type: application/json" \
  -d '{
  "query": "query GetAggregation($filter: JSON) { _aggregation { subject(accessibility: all, filter: $filter) { _totalCount } } }",
  "variables": {
    "filter": {
      "AND": [
        {
          "IN": {
            "consortium": [
              "INRG"
            ]
          }
        },
        {
          "nested": {
            "path": "tumor_assessments",
            "AND": [
              {
                "IN": {
                  "tumor_classification": [
                    "Metastatic"
                  ]
                }
              },
              {
                "IN": {
                  "tumor_state": [
                    "Absent"
                  ]
                }
              },
              {
                "IN": {
                  "tumor_site": [
                    "Skin"
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}'
{
  "data": {
    "_aggregation": {
      "subject": {
        "_totalCount": 8508
      }
    }
  }
}

3. Run the Application Frontend

First, make sure you start the frontend server in frontend_env:

source frontend_env/bin/activate
bash src/frontend/run.sh

It will run at http://localhost:8082

To login, you can use any of follwing accounts: username: test password: test username: admin password: admin username: user password: user123

4. Postgresql db schema

Database table schema

create table public."Element" (
  id uuid not null default extensions.uuid_generate_v4 (),
  "threadId" uuid null,
  type text null,
  url text null,
  "chainlitKey" text null,
  name text not null,
  display text null,
  "objectKey" text null,
  size text null,
  page integer null,
  "forIds" text[] null,
  mime text null,
  "updatedAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  "deletedAt" timestamp with time zone null,
  "createdAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  constraint Element_pkey primary key (id),
  constraint Element_threadId_fkey foreign KEY ("threadId") references "Thread" (id) on delete CASCADE
) TABLESPACE pg_default;

create index IF not exists idx_element_threadid on public."Element" using btree ("threadId") TABLESPACE pg_default;
create table public."Feedback" (
  id uuid not null default extensions.uuid_generate_v4 (),
  "forId" uuid not null,
  "threadId" uuid not null,
  value integer not null,
  comment text null,
  "createdAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  "updatedAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  "deletedAt" timestamp with time zone null,
  constraint Feedback_pkey primary key (id),
  constraint Feedback_threadId_fkey foreign KEY ("threadId") references "Thread" (id) on delete CASCADE
) TABLESPACE pg_default;

create index IF not exists idx_feedback_threadid on public."Feedback" using btree ("threadId") TABLESPACE pg_default;

create index IF not exists idx_feedback_forid on public."Feedback" using btree ("forId") TABLESPACE pg_default;
create table public."Step" (
  id uuid not null default extensions.uuid_generate_v4 (),
  name text null default 'step'::text,
  type text not null,
  "threadId" uuid null,
  "parentId" uuid null,
  streaming boolean null default false,
  "waitForAnswer" boolean null default false,
  "isError" boolean null default false,
  metadata jsonb null default '{}'::jsonb,
  tags text[] null,
  input text null,
  output text null,
  "createdAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  command text null,
  start timestamp with time zone null,
  "end" timestamp with time zone null,
  generation jsonb null,
  "showInput" text null,
  language text null,
  indent integer null default 0,
  "updatedAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  "deletedAt" timestamp with time zone null,
  "startTime" timestamp with time zone null,
  "endTime" timestamp with time zone null,
  "completionStartTime" timestamp with time zone null,
  "completionEndTime" timestamp with time zone null,
  "disableFeedback" boolean null default false,
  constraint Step_pkey primary key (id),
  constraint Step_parentId_fkey foreign KEY ("parentId") references "Step" (id) on delete CASCADE,
  constraint Step_threadId_fkey foreign KEY ("threadId") references "Thread" (id) on delete CASCADE
) TABLESPACE pg_default;

create index IF not exists idx_step_threadid on public."Step" using btree ("threadId") TABLESPACE pg_default;

create index IF not exists idx_step_parentid on public."Step" using btree ("parentId") TABLESPACE pg_default;

create index IF not exists idx_step_createdat on public."Step" using btree ("createdAt" desc) TABLESPACE pg_default;
create table public."User" (
  id uuid not null default extensions.uuid_generate_v4 (),
  identifier text not null,
  metadata jsonb null default '{}'::jsonb,
  "createdAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  "updatedAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  "deletedAt" timestamp with time zone null,
  constraint User_pkey primary key (id),
  constraint User_identifier_key unique (identifier)
) TABLESPACE pg_default;

create index IF not exists idx_user_identifier on public."User" using btree (identifier) TABLESPACE pg_default;
create table public."Thread" (
  id uuid not null default extensions.uuid_generate_v4 (),
  "createdAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  name text null,
  "userId" uuid null,
  "userIdentifier" text null,
  tags text[] null,
  metadata jsonb null default '{}'::jsonb,
  "updatedAt" timestamp with time zone null default CURRENT_TIMESTAMP,
  "deletedAt" timestamp with time zone null,
  participant jsonb null,
  constraint Thread_pkey primary key (id),
  constraint Thread_userId_fkey foreign KEY ("userId") references "User" (id) on delete CASCADE
) TABLESPACE pg_default;

create index IF not exists idx_thread_userid on public."Thread" using btree ("userId") TABLESPACE pg_default;

create index IF not exists idx_thread_useridentifier on public."Thread" using btree ("userIdentifier") TABLESPACE pg_default;

create index IF not exists idx_thread_createdat on public."Thread" using btree ("createdAt" desc) TABLESPACE pg_default;

5. Future work

5.1 Support disease_phase field in nested graphql (Todo)

{"query":"query ($filter: JSON) { _aggregation { subject (filter: $filter, accessibility: all) { sex { histogram { key count } } race { histogram { key count } } ethnicity { histogram { key count } } consortium { histogram { key count } } } } }","variables":{"filter":{"AND":[{"nested":{"path":"tumor_assessments","AND":[{"AND":[{"IN":{"disease_phase":["Initial Diagnosis"]}},{"AND":[{"IN":{"tumor_classification":["Metastatic"]}},{"IN":{"tumor_site":["Bone"]}}]}]}]}}]}}}

5.2 Support number field(GTE, LTE) in nested graphql (Todo)

{
  "filter_main": {
    "AND": [
      {
        "nested": {
          "path": "tumor_assessments",
          "AND": [
            {
              "AND": [
                {
                  "GTE": {
                    "age_at_tumor_assessment": 0
                  }
                },
                {
                  "LTE": {
                    "age_at_tumor_assessment": 100
                  }
                }
              ]
            }
          ]
        }
      }
    ]
  }
}

About

No description, website, or topics provided.

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages