From 4cf735b8945b1093108696784104e72cbc2380cb Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 14:59:39 +0200 Subject: [PATCH 1/8] add nl --- ai/scraper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai/scraper.py b/ai/scraper.py index 8861d39bf..403c40643 100755 --- a/ai/scraper.py +++ b/ai/scraper.py @@ -117,4 +117,4 @@ def scrape_discord(): index = VectorStoreIndex.from_documents(list(chain)) index.storage_context.persist() -print("persisted new vector index") \ No newline at end of file +print("persisted new vector index") From ef645ff3ca23e69198c9df9f2ab16830e1c5779f Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 14:59:57 +0200 Subject: [PATCH 2/8] version py --- ai/.python-version | 1 + 1 file changed, 1 insertion(+) create mode 100644 ai/.python-version diff --git a/ai/.python-version b/ai/.python-version new file mode 100644 index 000000000..b326afbc9 --- /dev/null +++ b/ai/.python-version @@ -0,0 +1 @@ +3.9.15 From d60938caef1db50fc2bdb1aa7c7cc62bfbc4afbd Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 15:00:15 +0200 Subject: [PATCH 3/8] get storage context from s3 --- ai/README.md | 12 ++++++++++++ ai/main.py | 7 ++++++- ai/requirements.txt | 3 ++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ai/README.md b/ai/README.md index ea44a7326..2960e3898 100644 --- a/ai/README.md +++ b/ai/README.md @@ -13,6 +13,18 @@ The server is built with FastAPI. To start the server by running `uvicorn main:a Swaggger Documentation: /docs Chat endpoint: /chat +The storage context is pulled from s3 so the `main.py` script needs to know where to find it and how to authenticate. + +- Auth: + IRSA should work, otherwise you'll need to set the standard AWS env vars: + - `AWS_ACCESS_KEY_ID` + - `AWS_SECRET_ACCESS_KEY` +- Path: + The script expects the AWS path in `PLURAL_AI_INDEX_S3_PATH` in the format `/`. + Defaults to `plural-assets/dagster/plural-ai/vector_store_index` + +To be safe `AWS_DEFAULT_REGION` should be set to the region of the bucket. + ## Running scraper.py The scraper currently incorporates three datasources: diff --git a/ai/main.py b/ai/main.py index 05043562e..3adee1205 100644 --- a/ai/main.py +++ b/ai/main.py @@ -4,6 +4,7 @@ from llama_index import StorageContext, load_index_from_storage, ServiceContext, set_global_service_context from llama_index.indices.postprocessor import SentenceEmbeddingOptimizer from llama_index.embeddings import OpenAIEmbedding +from s3fs import S3FileSystem from pydantic import BaseModel @@ -22,7 +23,11 @@ class QueryResponse(BaseModel): service_context = ServiceContext.from_defaults(embed_model=embed_model) set_global_service_context(service_context) -storage_context = StorageContext.from_defaults(persist_dir="./storage") +storage_context = StorageContext.from_defaults( + # persist_dir format: "/" + persist_dir=os.getenv("PLURAL_AI_INDEX_S3_PATH", "plural-assets/dagster/plural-ai/vector_store_index"), + fs=S3FileSystem() +) index = load_index_from_storage(storage_context) query_engine = index.as_query_engine( node_postprocessors=[SentenceEmbeddingOptimizer(percentile_cutoff=0.5)], diff --git a/ai/requirements.txt b/ai/requirements.txt index e8ce47a2b..7d810c54d 100644 --- a/ai/requirements.txt +++ b/ai/requirements.txt @@ -56,4 +56,5 @@ yarl==1.9.2 python-graphql-client nltk config -html2text \ No newline at end of file +html2text +s3fs \ No newline at end of file From 667972f7395cbbe3121d8555636ea3363d47c1f0 Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 16:51:57 +0200 Subject: [PATCH 4/8] this should do it, daily reloads --- ai/main.py | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/ai/main.py b/ai/main.py index 3adee1205..1521f76f5 100644 --- a/ai/main.py +++ b/ai/main.py @@ -1,16 +1,34 @@ import os import openai +import asyncio from fastapi import FastAPI, HTTPException from llama_index import StorageContext, load_index_from_storage, ServiceContext, set_global_service_context from llama_index.indices.postprocessor import SentenceEmbeddingOptimizer from llama_index.embeddings import OpenAIEmbedding from s3fs import S3FileSystem - from pydantic import BaseModel +def load_query_engine(vector_store_index_path: str): + storage_context = StorageContext.from_defaults( + # persist_dir format: "/" + persist_dir=vector_store_index_path, + fs=S3FileSystem() + ) + index = load_index_from_storage(storage_context) + return index.as_query_engine( + node_postprocessors=[SentenceEmbeddingOptimizer(percentile_cutoff=0.5)], + response_mode="compact", + similarity_cutoff=0.7 + ) + openai.api_key = os.environ["OPENAI_API_KEY"] +vector_store_index_path = os.getenv("PLURAL_AI_INDEX_S3_PATH", "plural-assets/dagster/plural-ai/vector_store_index") app = FastAPI() +embed_model = OpenAIEmbedding(embed_batch_size=10) +service_context = ServiceContext.from_defaults(embed_model=embed_model) +set_global_service_context(service_context) +query_engine = load_query_engine(vector_store_index_path) class QueryRequest(BaseModel): question: str @@ -18,26 +36,19 @@ class QueryRequest(BaseModel): class QueryResponse(BaseModel): answer: str +async def reload_query_engine(): + while True: + await asyncio.sleep(86400) # daily + query_engine = load_query_engine(vector_store_index_path) -embed_model = OpenAIEmbedding(embed_batch_size=10) -service_context = ServiceContext.from_defaults(embed_model=embed_model) -set_global_service_context(service_context) - -storage_context = StorageContext.from_defaults( - # persist_dir format: "/" - persist_dir=os.getenv("PLURAL_AI_INDEX_S3_PATH", "plural-assets/dagster/plural-ai/vector_store_index"), - fs=S3FileSystem() -) -index = load_index_from_storage(storage_context) -query_engine = index.as_query_engine( - node_postprocessors=[SentenceEmbeddingOptimizer(percentile_cutoff=0.5)], - response_mode="compact", - similarity_cutoff=0.7 -) +@app.on_event("startup") +async def schedule_periodic(): + loop = asyncio.get_event_loop() + loop.create_task(reload_query_engine()) @app.get("/") def read_root(): - return {"Hello": "World"} + return {"Plural": "AI"} @app.post("/chat") def query_data(request: QueryRequest): From d79cac0557fddc2883de3cb1d31c8e797feede15 Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 16:52:51 +0200 Subject: [PATCH 5/8] missed global --- ai/main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ai/main.py b/ai/main.py index 1521f76f5..225a6ade8 100644 --- a/ai/main.py +++ b/ai/main.py @@ -37,6 +37,7 @@ class QueryResponse(BaseModel): answer: str async def reload_query_engine(): + global query_engine while True: await asyncio.sleep(86400) # daily query_engine = load_query_engine(vector_store_index_path) From 16b50af247c899e81cb14c027064e79304500964 Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 16:58:13 +0200 Subject: [PATCH 6/8] expalin --- ai/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai/main.py b/ai/main.py index 225a6ade8..445451b60 100644 --- a/ai/main.py +++ b/ai/main.py @@ -39,7 +39,7 @@ class QueryResponse(BaseModel): async def reload_query_engine(): global query_engine while True: - await asyncio.sleep(86400) # daily + await asyncio.sleep(86400) # 86400 seconds in a day query_engine = load_query_engine(vector_store_index_path) @app.on_event("startup") From a8bf1d4289411b3527f68a609853179f8b44e5d7 Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 17:03:44 +0200 Subject: [PATCH 7/8] better var naming --- ai/main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ai/main.py b/ai/main.py index 445451b60..1e3edf1dd 100644 --- a/ai/main.py +++ b/ai/main.py @@ -8,10 +8,10 @@ from s3fs import S3FileSystem from pydantic import BaseModel -def load_query_engine(vector_store_index_path: str): +def load_query_engine(s3_path: str): storage_context = StorageContext.from_defaults( # persist_dir format: "/" - persist_dir=vector_store_index_path, + persist_dir=s3_path, fs=S3FileSystem() ) index = load_index_from_storage(storage_context) @@ -22,13 +22,13 @@ def load_query_engine(vector_store_index_path: str): ) openai.api_key = os.environ["OPENAI_API_KEY"] -vector_store_index_path = os.getenv("PLURAL_AI_INDEX_S3_PATH", "plural-assets/dagster/plural-ai/vector_store_index") +PLURAL_AI_INDEX_S3_PATH = os.getenv("PLURAL_AI_INDEX_S3_PATH", "plural-assets/dagster/plural-ai/vector_store_index") app = FastAPI() embed_model = OpenAIEmbedding(embed_batch_size=10) service_context = ServiceContext.from_defaults(embed_model=embed_model) set_global_service_context(service_context) -query_engine = load_query_engine(vector_store_index_path) +query_engine = load_query_engine(PLURAL_AI_INDEX_S3_PATH) class QueryRequest(BaseModel): question: str @@ -40,7 +40,7 @@ async def reload_query_engine(): global query_engine while True: await asyncio.sleep(86400) # 86400 seconds in a day - query_engine = load_query_engine(vector_store_index_path) + query_engine = load_query_engine(PLURAL_AI_INDEX_S3_PATH) @app.on_event("startup") async def schedule_periodic(): From e7bd4f24e7568840931b3524da84a1d4dd1c3840 Mon Sep 17 00:00:00 2001 From: Hans Rauer Date: Fri, 25 Aug 2023 17:04:39 +0200 Subject: [PATCH 8/8] rename --- ai/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ai/main.py b/ai/main.py index 1e3edf1dd..2183d15e8 100644 --- a/ai/main.py +++ b/ai/main.py @@ -43,7 +43,7 @@ async def reload_query_engine(): query_engine = load_query_engine(PLURAL_AI_INDEX_S3_PATH) @app.on_event("startup") -async def schedule_periodic(): +async def schedule_reload_query_engine(): loop = asyncio.get_event_loop() loop.create_task(reload_query_engine())