From 54decee4abafc5cfef2fa6bf50ec858fd03492d7 Mon Sep 17 00:00:00 2001 From: "Michael B. Klein" Date: Tue, 17 Oct 2023 14:29:44 +0000 Subject: [PATCH] Remove non-streaming chat handler Move python dependencies to a layer --- .gitignore | 1 + .husky/pre-commit | 2 +- Makefile | 10 +- .../dependencies}/requirements.txt | 0 chat/src/handlers/chat.py | 2 +- chat/template.yaml | 18 ++- python/requirements.txt | 3 - python/src/__init__.py | 0 python/src/handlers/chat.py | 105 ------------ python/src/helpers/apitoken.py | 28 ---- python/src/helpers/event.py | 48 ------ python/src/helpers/prompts.py | 153 ------------------ python/src/setup.py | 34 ---- python/test/__init__.py | 0 python/test/fixtures/apitoken.py | 5 - python/test/fixtures/events.py | 56 ------- python/test/handlers/__init__.py | 0 python/test/helpers/__init__.py | 0 python/test/helpers/test_apitoken.py | 24 --- python/test/helpers/test_event.py | 63 -------- template.yaml | 29 ---- 21 files changed, 25 insertions(+), 556 deletions(-) rename {python/src => chat/dependencies}/requirements.txt (100%) delete mode 100644 python/requirements.txt delete mode 100644 python/src/__init__.py delete mode 100644 python/src/handlers/chat.py delete mode 100644 python/src/helpers/apitoken.py delete mode 100644 python/src/helpers/event.py delete mode 100644 python/src/helpers/prompts.py delete mode 100644 python/src/setup.py delete mode 100644 python/test/__init__.py delete mode 100644 python/test/fixtures/apitoken.py delete mode 100644 python/test/fixtures/events.py delete mode 100644 python/test/handlers/__init__.py delete mode 100644 python/test/helpers/__init__.py delete mode 100644 python/test/helpers/test_apitoken.py delete mode 100644 python/test/helpers/test_event.py diff --git a/.gitignore b/.gitignore index 6c650ad7..adf3345d 100644 --- a/.gitignore +++ b/.gitignore @@ -223,6 +223,7 @@ $RECYCLE.BIN/ .vscode /samconfig.toml /samconfig.yaml +/samconfig.*.yaml /env.json /env.*.json /*.parameters diff --git a/.husky/pre-commit b/.husky/pre-commit index 0fc6b0d5..01456dba 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,4 @@ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" cd node && npm run lint && npm run prettier && cd - -cd python && ruff check . && cd - +cd chat/src && ruff check . && cd - diff --git a/Makefile b/Makefile index 08a70c01..adf43162 100644 --- a/Makefile +++ b/Makefile @@ -33,16 +33,16 @@ style-node: test-node: cd node && npm run test deps-python: - cd python && pip install -r requirements.txt + cd chat/src && pip install -r requirements.txt cover-python: - cd python && coverage run --include='src/**/*' -m unittest -v && coverage report + cd chat/src && coverage run --include='src/**/*' -m unittest -v && coverage report style-python: - cd python && ruff check . + cd chat/src && ruff check . test-python: - cd python && python -m unittest -v + cd chat/src && python -m unittest -v build: .aws-sam/build.toml link: build - cd python/src && for src in *.py **/*.py; do for target in $$(find ../../.aws-sam/build -maxdepth 1 -type d); do if [[ -f $$target/$$src ]]; then ln -f $$src $$target/$$src; fi; done; done + cd chat/src && for src in *.py **/*.py; do for target in $$(find ../../.aws-sam/build -maxdepth 1 -type d); do if [[ -f $$target/$$src ]]; then ln -f $$src $$target/$$src; fi; done; done cd node/src && for src in *.js *.json **/*.js **/*.json; do for target in $$(find ../../.aws-sam/build -maxdepth 1 -type d); do if [[ -f $$target/$$src ]]; then ln -f $$src $$target/$$src; fi; done; done serve: link sam local start-api --host 0.0.0.0 --log-file dc-api.log diff --git a/python/src/requirements.txt b/chat/dependencies/requirements.txt similarity index 100% rename from python/src/requirements.txt rename to chat/dependencies/requirements.txt diff --git a/chat/src/handlers/chat.py b/chat/src/handlers/chat.py index ff916767..d38a4bf0 100644 --- a/chat/src/handlers/chat.py +++ b/chat/src/handlers/chat.py @@ -34,7 +34,7 @@ def __init__(self, socket: Websocket): self.socket = socket def on_llm_new_token(self, token: str, **kwargs): - self.socket.send({'token': token}); + self.socket.send({'token': token}) def handler(event, context): try: diff --git a/chat/template.yaml b/chat/template.yaml index f97e3e16..303ec226 100644 --- a/chat/template.yaml +++ b/chat/template.yaml @@ -171,13 +171,27 @@ Resources: Action: lambda:InvokeFunction FunctionName: !Ref ChatFunction Principal: apigateway.amazonaws.com + ChatDependencies: + Type: AWS::Serverless::LayerVersion + Properties: + LayerName: + Fn::Sub: "${AWS::StackName}-dependencies" + Description: Dependencies for streaming chat function + ContentUri: ./dependencies + CompatibleRuntimes: + - python3.10 + LicenseInfo: "Apache-2.0" + Metadata: + BuildMethod: python3.10 ChatFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./src - Runtime: python3.9 + Runtime: python3.10 Architectures: - x86_64 + Layers: + - !Ref ChatDependencies MemorySize: 128 Handler: handlers/chat.handler Timeout: 300 @@ -197,6 +211,8 @@ Resources: - 'execute-api:ManageConnections' Resource: - !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ChatWebSocket}/*' + Metadata: + BuildMethod: nodejs18.x Deployment: Type: AWS::ApiGatewayV2::Deployment DependsOn: diff --git a/python/requirements.txt b/python/requirements.txt deleted file mode 100644 index 074747e7..00000000 --- a/python/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ --r src/requirements.txt -coverage -ruff \ No newline at end of file diff --git a/python/src/__init__.py b/python/src/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python/src/handlers/chat.py b/python/src/handlers/chat.py deleted file mode 100644 index fd8703e4..00000000 --- a/python/src/handlers/chat.py +++ /dev/null @@ -1,105 +0,0 @@ -import json -import os -import setup -from helpers.event import Event -from helpers.prompts import document_template, prompt_template -from langchain.chains.qa_with_sources import load_qa_with_sources_chain -from langchain.prompts import PromptTemplate -from openai.error import InvalidRequestError - -ALLOW_HEADERS = ("Accept, Accept-Charset, Accept-Encoding, Accept-Language, " - "Accept-Datetime, Authorization, Cache-Control, Content-Length, " - "Content-Type, Cookie, Date, Expect, Host, If-Match, " - "If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, " - "Origin, Pragma, Range, Referer, User-Agent, X-CSRF-Token, " - "X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Port, " - "X-Requested-With") -DEFAULT_INDEX = "Work" -DEFAULT_KEY = "title" -DEFAULT_ATTRIBUTES = ("title,alternate_title,collection,contributor,creator," - "date_created,description,genre,language,library_unit," - "location,physical_description_material,physical_description_size," - "published,rights_statement,scope_and_contents,series,source," - "style_period,subject,table_of_contents,technique,visibility," - "work_type") - -def handler(event, context): - event = Event(event) - origin_header = event.header("Origin", os.getenv("PROTOTYPE_URL", "*")) - print(f"Origin header received: {origin_header}") - - if not event.api_token.is_logged_in(): - return { - "statusCode": 401, - "headers": { - "Content-Type": "text/plain" - }, - "body": "Unauthorized" - } - question = event.body() if event.is_post_request() else event.param("q", "") - index_name = event.param("index", DEFAULT_INDEX) - text_key = event.param("text_key", DEFAULT_KEY) - attributes = [ - item for item - in set(event.param("attributes", DEFAULT_ATTRIBUTES).split(",")) - if item not in [text_key, "source"] - ] - - weaviate = setup.weaviate_vector_store(index_name=index_name, - text_key=text_key, - attributes=attributes + ["source"]) - - client = setup.openai_chat_client() - - prompt = PromptTemplate( - template=prompt_template(), - input_variables=["question", "context"] - ) - - document_prompt = PromptTemplate( - template=document_template(attributes), - input_variables=["page_content", "source"] + attributes, - ) - - docs = weaviate.similarity_search(question, k=10, additional="certainty") - chain = load_qa_with_sources_chain( - client, - chain_type="stuff", - prompt=prompt, - document_prompt=document_prompt, - document_variable_name="context", - verbose=to_bool(os.getenv("VERBOSE")) - ) - - try: - response = chain({"question": question, "input_documents": docs}) - response = { - "question": response["question"], - "answer": response["output_text"], - "source_documents": [doc.__dict__ for doc in response['input_documents']] - } - except InvalidRequestError as err: - response = { - "question": question, - "answer": str(err), - "source_documents": [] - } - - return { - "statusCode": 200, - "headers": { - "Content-Type": "application/json", - "access-control-allow-methods": "POST, GET", - "access-control-allow-credentials": True, - "access-control-max-age": 600, - "access-control-allow-origin": event.header("Origin", - os.getenv("PROTOTYPE_URL", "*")), - "access-control-allow-headers": ALLOW_HEADERS - }, - "body": json.dumps(response) - } - -def to_bool(val): - if isinstance(val, str): - return val.lower() not in ["", "no", "false", "0"] - return bool(val) diff --git a/python/src/helpers/apitoken.py b/python/src/helpers/apitoken.py deleted file mode 100644 index 4c6ecbd4..00000000 --- a/python/src/helpers/apitoken.py +++ /dev/null @@ -1,28 +0,0 @@ -from datetime import datetime -import jwt -import os - -class ApiToken: - @classmethod - def empty_token(cls): - time = int(datetime.now().timestamp()) - return { - 'iss': os.getenv('DC_API_ENDPOINT'), - 'exp': datetime.fromtimestamp(time + 12 * 60 * 60).timestamp(), # 12 hours - 'iat': time, - 'entitlements': [], - 'isLoggedIn': False, - } - - def __init__(self, signed_token=None): - if signed_token is None: - self.token = ApiToken.empty_token() - else: - try: - secret = os.getenv("API_TOKEN_SECRET") - self.token = jwt.decode(signed_token, secret, algorithms=["HS256"]) - except Exception: - self.token = ApiToken.empty_token() - - def is_logged_in(self): - return self.token.get("isLoggedIn", False) diff --git a/python/src/helpers/event.py b/python/src/helpers/event.py deleted file mode 100644 index ed2e175f..00000000 --- a/python/src/helpers/event.py +++ /dev/null @@ -1,48 +0,0 @@ -from .apitoken import ApiToken -import base64 -import os - -class Event: - def __init__(self, event): - self.event = event - cookies_from_event = event.get("cookies", []) - cookie_list = [ - cookie.split("=", 1) if "=" in cookie else ("", cookie) - for cookie in cookies_from_event - ] - self.cookies = dict(cookie_list) - token = self.header("Authorization") or self.cookie(os.getenv("API_TOKEN_NAME")) - if isinstance(token, str): - token = token.replace("Bearer ", "") - self.api_token = ApiToken(token) - - def header(self, header, default=None): - headers = self.event.get("headers") - return headers.get(header, headers.get(header.lower(), default)) - - def param(self, parameter, default=None): - params = self.event.get("queryStringParameters", {}) - return params.get(parameter, default) - - def method(self): - return self.event["requestContext"]["http"]["method"] - - def is_get_request(self): - return self.method() == "GET" - def is_head_request(self): - return self.method() == "HEAD" - def is_options_request(self): - return self.method() == "OPTIONS" - def is_post_request(self): - return self.method() == "POST" - - def body(self): - result = self.event.get("body", None) - if result is None or result == "": - return None - if self.event.get("isBase64Encoded", False): - return base64.b64decode(result).decode("UTF-8") - return result - - def cookie(self, name, default=None): - return self.cookies.get(name, default) diff --git a/python/src/helpers/prompts.py b/python/src/helpers/prompts.py deleted file mode 100644 index b79510e8..00000000 --- a/python/src/helpers/prompts.py +++ /dev/null @@ -1,153 +0,0 @@ -# ruff: noqa: E501 -def prompt_template(): - return """Using all of the provided source documents, create a helpful and thorough answer to the supplied question. - If you don't know the answer, just say that you don't know. Don't try to make up an answer, but you should use the documents provided in order to ground your response. - It may be helpful to explain why a provided document does not pertain to the query as well. - Feel free to reference various aspects of the sources in your explanation, but please don't include the full sources in the answer. - The Content field represents the title of each document, and the Metadata fields are the attributes. The Source field is the unique identifier for each document. - 'certainty' is an opinionated measure of the distance between the query vector and the document embedding vector. Certainty always returns a number between 0 and 1, with 1 indicating identical vectors and 0 indicating opposing angles. - - Content: Purchase order and note - Metadata: - _additional: {{'certainty': 0.8744078576564789, 'id': '29389b8d-a85d-46d1-9a6d-a738c6f81c88'}} - alternate_title: None - collection: Berkeley Folk Music Festival - contributor: ['University of California, Berkeley. Associated Students', 'Berkeley Folk Music Festival'] - creator: None - date_created: ['October 7, 1970', '1970?'] - description: ['Purchase order for costs related to security for the 1970 Berkeley Folk Music Festival and a handwritten note containing calculations and the heading "Police"'] - genre: ['notes (documents)', 'purchase orders'] - language: ['English'] - library_unit: Charles Deering McCormick Library of Special Collections - location: None - physical_description_material: None - physical_description_size: ['5 inches (height) x 3 inches (width)', '7 inches (height) x 8.5 inches (width)'] - published: True - rights_statement: In Copyright - scope_and_contents: None - series: ['Berkeley Folk Music Festival Archive--3. Festivals: Records, Budgets, Publicity'] - source: 29389b8d-a85d-46d1-9a6d-a738c6f81c88 - style_period: None - subject: ['Berkeley Folk Music Festival (15th : 1970 : Berkeley, Calif.)'] - table_of_contents: None - technique: None - visibility: Public - work_type: Image - Source: 29389b8d-a85d-46d1-9a6d-a738c6f81c88 - - Content: Berkeley Folk Music Festival, 1966 June 26-30 - Metadata: - _additional: {{'certainty': 0.869585394859314, 'id': '477e3f63-fc06-4bfc-8734-0b6100c0d1c3'}} - alternate_title: None - collection: Berkeley Folk Music Festival - contributor: ['Olivier, Barry, 1935-', 'Hart, Kelly, 1943-', 'University of California, Berkeley. Associated Students'] - creator: None - date_created: ['1966'] - description: ['Poster for the Berkeley Folk Music Festival, held at the University of California, Berkeley from June 30 to July 4, 1966, presented by the Associated Students. White text on black background between black and white images of a man playing a fiddle and another man singing into a mic while holding a guitar. Guest list includes Pete Seeger, Jefferson Airplane, Sam Hinton, Greenbriar Boys, Shlomo Carlebach, John Fahey, Los Halcones de Salitrillos, Charley Marshall, Phil Ochs, Ralph J. Gleason, Malvina Reynolds, Robert Pete Williams, Alice Stuart Thomas, Bess Lomax Hawes, and Charles Seeger.'] - genre: ['posters'] - language: ['English'] - library_unit: Charles Deering McCormick Library of Special Collections - location: None - physical_description_material: None - physical_description_size: ['12.75 inches (height) x 12.75 inches (width)'] - published: True - rights_statement: In Copyright - scope_and_contents: None - series: ['Berkeley Folk Music Festival Archive--13. Miscellaneous Posters'] - source: 477e3f63-fc06-4bfc-8734-0b6100c0d1c3 - style_period: None - subject: ['Berkeley (Calif.)', 'University of California, Berkeley', 'Gleason, Ralph J.', 'Folk music', 'Jefferson Airplane (Musical group)', 'Seeger, Pete, 1919-2014', 'Fahey, John, 1939-2001', 'Williams, Robert Pete, 1914-1980', 'Folk music festivals', 'Hinton, Sam, 1917-2009', 'Reynolds, Malvina', 'Halcones de Salitrillo (Musical group)', 'Folk musicians', 'Concerts', 'Carlebach, Shlomo, 1925-1994', 'Marshall, Charley', 'Ochs, Phil', 'Seeger, Charles, 1886-1979', 'Berkeley Folk Music Festival', 'Greenbriar Boys', 'Stuart, Alice, 1942-', 'Hawes, Bess Lomax, 1921-2009'] - table_of_contents: None - technique: None - visibility: Public - work_type: Image - Source: 477e3f63-fc06-4bfc-8734-0b6100c0d1c3 - - Content: Berkeley Folk Music Festival, 1966 June 26-30 - Metadata: - _additional: {{'certainty': 0.8694239258766174, 'id': 'bddeb375-762b-45e3-9e4e-5a4084ac5955'}} - alternate_title: None - collection: Berkeley Folk Music Festival - contributor: ['Olivier, Barry, 1935-', 'Hart, Kelly, 1943-', 'University of California, Berkeley. Associated Students'] - creator: None - date_created: ['1966'] - description: ['Poster for the Berkeley Folk Music Festival, held at the University of California, Berkeley from June 30 to July 4, 1966, presented by the Associated Students. White text on black background between black and white images of a man playing a fiddle and another man singing into a mic while holding a guitar. Guest list includes Pete Seeger, Jefferson Airplane, Sam Hinton, Greenbriar Boys, Shlomo Carlebach, John Fahey, Los Halcones de Salitrillos, Charley Marshall, Phil Ochs, Ralph J. Gleason, Malvina Reynolds, Robert Pete Williams, Alice Stuart Thomas, Bess Lomax Hawes, and Charles Seeger.'] - genre: ['posters'] - language: ['English'] - library_unit: Charles Deering McCormick Library of Special Collections - location: None - physical_description_material: None - physical_description_size: ['13.75 inches (height) x 21.75 inches (width)'] - published: True - rights_statement: In Copyright - scope_and_contents: None - series: ['Berkeley Folk Music Festival Archive--9. Posters of Berkeley Folk Music Festivals'] - source: bddeb375-762b-45e3-9e4e-5a4084ac5955 - style_period: None - subject: ['Berkeley (Calif.)', 'University of California, Berkeley', 'Gleason, Ralph J.', 'Folk music', 'Jefferson Airplane (Musical group)', 'Seeger, Pete, 1919-2014', 'Fahey, John, 1939-2001', 'Williams, Robert Pete, 1914-1980', 'Folk music festivals', 'Hinton, Sam, 1917-2009', 'Reynolds, Malvina', 'Halcones de Salitrillo (Musical group)', 'Folk musicians', 'Concerts', 'Carlebach, Shlomo, 1925-1994', 'Marshall, Charley', 'Ochs, Phil', 'Berkeley Folk Music Festival (9th : 1966 : Berkeley, Calif.)', 'Hawes, Bess Lomax, 1921-2009', 'Greenbriar Boys', 'Stuart, Alice, 1942-', 'Seeger, Charles, 1886-1979', 'Berkeley Folk Music Festival'] - table_of_contents: None - technique: None - visibility: Public - work_type: Image - Source: bddeb375-762b-45e3-9e4e-5a4084ac5955 - - Content: Berkeley Folk Music Festival, 1966 June 30-July 4 - Metadata: - _additional: {{'certainty': 0.8693937957286835, 'id': 'aab0bb76-ab02-429a-843a-5be56e31ba67'}} - alternate_title: None - collection: Berkeley Folk Music Festival - contributor: ['Olivier, Barry, 1935-', 'Hart, Kelly, 1943-', 'University of California, Berkeley. Associated Students'] - creator: None - date_created: ['1966'] - description: ['Poster for the 9th Annual Berkeley Folk Music Festival, held at the University of California, Berkeley from June 30 to July 4, 1966, presented by the Associated Students. White text on black background between black and white images of a man playing a fiddle and another man singing into a mic while holding a guitar. Guest list includes Pete Seeger, Jefferson Airplane, Sam Hinton, Greenbriar Boys, Shlomo Carlebach, John Fahey, Los Halcones de Salitrillos, Charley Marshall, Phil Ochs, Ralph J. Gleason, Malvina Reynolds, Robert Pete Williams, Alice Stuart Thomas, Bess Lomax Hawes, and Charles Seeger. Originally found in box 28, folder 3.'] - genre: ['posters'] - language: ['English'] - library_unit: Charles Deering McCormick Library of Special Collections - location: None - physical_description_material: None - physical_description_size: ['24.25 inches (height) x 37.5 inches (width)'] - published: True - rights_statement: In Copyright - scope_and_contents: None - series: ['Berkeley Folk Music Festival Archive--13. Miscellaneous Posters'] - source: aab0bb76-ab02-429a-843a-5be56e31ba67 - style_period: None - subject: ['Berkeley (Calif.)', 'University of California, Berkeley', 'Gleason, Ralph J.', 'Folk music', 'Jefferson Airplane (Musical group)', 'Seeger, Pete, 1919-2014', 'Fahey, John, 1939-2001', 'Williams, Robert Pete, 1914-1980', 'Folk music festivals', 'Hinton, Sam, 1917-2009', 'Reynolds, Malvina', 'Halcones de Salitrillo (Musical group)', 'Folk musicians', 'Concerts', 'Carlebach, Shlomo, 1925-1994', 'Marshall, Charley', 'Ochs, Phil', 'Berkeley Folk Music Festival (9th : 1966 : Berkeley, Calif.)', 'Hawes, Bess Lomax, 1921-2009', 'Greenbriar Boys', 'Stuart, Alice, 1942-', 'Seeger, Charles, 1886-1979', 'Berkeley Folk Music Festival'] - table_of_contents: None - technique: None - visibility: Public - work_type: Image - Source: aab0bb76-ab02-429a-843a-5be56e31ba67 - - QUESTION: Which musicians played at the Berkeley Folk Music Festival? - HELPFUL ANSWER: For the 1966 Berkeley Folk Music Festival, held at the University of California, Berkeley from June 30 to July 4, the following musicians and groups were listed as performers: - - Pete Seeger - Jefferson Airplane - Sam Hinton - Greenbriar Boys - Shlomo Carlebach - John Fahey - Los Halcones de Salitrillos - Charley Marshall - Phil Ochs - Ralph J. Gleason - Malvina Reynolds - Robert Pete Williams - Alice Stuart Thomas - Bess Lomax Hawes - Charles Seeger - - Unfortunately, the documents provided do not include information about musicians who performed at the Berkeley Folk Music Festival in other years during the 1960s or 1970s. Therefore, I can only confirm the musicians for the 1966 festival. - - {context} - - QUESTION: {question} - ========= - HELPFUL ANSWER:""" - -def document_template(attributes): - lines = (["Content: {page_content}", "Metadata:"] + - [f" {attribute}: {{{attribute}}}" for attribute in attributes] + - ["Source: {source}"]) - return "\n".join(lines) diff --git a/python/src/setup.py b/python/src/setup.py deleted file mode 100644 index 8869f4d6..00000000 --- a/python/src/setup.py +++ /dev/null @@ -1,34 +0,0 @@ -from langchain.chat_models import AzureChatOpenAI -from langchain.vectorstores import Weaviate -from typing import List -import os -import weaviate - -def openai_chat_client(): - deployment = os.getenv("AZURE_OPENAI_LLM_DEPLOYMENT_ID") - key = os.getenv("AZURE_OPENAI_API_KEY") - resource = os.getenv("AZURE_OPENAI_RESOURCE_NAME") - version = "2023-07-01-preview" - - return AzureChatOpenAI(deployment_name=deployment, - openai_api_key=key, - openai_api_base=f"https://{resource}.openai.azure.com/", - openai_api_version=version) - - - -def weaviate_vector_store(index_name: str, text_key: str, attributes: List[str] = []): - weaviate_url = os.environ['WEAVIATE_URL'] - weaviate_api_key = os.environ['WEAVIATE_API_KEY'] - # openai_api_key = os.environ['AZURE_OPENAI_API_KEY'] - - auth_config = weaviate.AuthApiKey(api_key=weaviate_api_key) - - client = weaviate.Client( - url=weaviate_url, - auth_client_secret=auth_config - ) - return Weaviate(client=client, - index_name=index_name, - text_key=text_key, - attributes=attributes) diff --git a/python/test/__init__.py b/python/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python/test/fixtures/apitoken.py b/python/test/fixtures/apitoken.py deleted file mode 100644 index 0f61693c..00000000 --- a/python/test/fixtures/apitoken.py +++ /dev/null @@ -1,5 +0,0 @@ -TEST_SECRET = "TEST_SECRET" -TEST_TOKEN_NAME = "dcTestToken" -TEST_TOKEN = ('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjQ4NDM1ODY2MDYxNjUs' - 'ImlhdCI6MTY4Nzg5MTM2OSwiZW50aXRsZW1lbnRzIjpbXSwiaXNMb2dnZWRJbiI6d' - 'HJ1ZSwic3ViIjoidGVzdFVzZXIifQ.vIZag1pHE1YyrxsKKlakXX_44ckAvkg7xWOoA_w4x58') diff --git a/python/test/fixtures/events.py b/python/test/fixtures/events.py deleted file mode 100644 index 1b275be7..00000000 --- a/python/test/fixtures/events.py +++ /dev/null @@ -1,56 +0,0 @@ -from copy import deepcopy -from test.fixtures.apitoken import TEST_TOKEN_NAME, TEST_TOKEN - -POST_EVENT = { - "version": "2.0", - "routeKey": "$default", - "rawPath": "/chat", - "cookies": [ - "cookie_1=cookie_value_1", - "cookie_2=cookie_value_2", - ], - "headers": { - "Authorization": f"Bearer {TEST_TOKEN}", - "origin": "https://example.edu" - }, - "queryStringParameters": { - "param1": "value1", - "param2": "value2", - }, - "requestContext": { - "accountId": "123456789012", - "apiId": "api-id", - "domainName": "id.execute-api.us-east-1.amazonaws.com", - "domainPrefix": "id", - "http": { - "method": "POST", - "path": "/chat", - "protocol": "HTTP/1.1", - "sourceIp": "192.168.0.1/32", - "userAgent": "agent" - }, - "requestId": "id", - "routeKey": "$default", - "stage": "$default", - "time": "12/Mar/2020:19:03:58 +0000", - "timeEpoch": 1583348638390 - }, - "body": "UE9TVGVkIENvbnRlbnQ=", - "pathParameters": {}, - "isBase64Encoded": True, - "stageVariables": {} -} - -PLAIN_BODY_EVENT = deepcopy(POST_EVENT) -PLAIN_BODY_EVENT["isBase64Encoded"] = False -PLAIN_BODY_EVENT["body"] = "POSTed Content" - -NO_BODY_EVENT = deepcopy(POST_EVENT) -NO_BODY_EVENT["isBase64Encoded"] = False -NO_BODY_EVENT["body"] = "" - -NO_TOKEN_EVENT = deepcopy(POST_EVENT) -del NO_TOKEN_EVENT["headers"]["Authorization"] - -COOKIE_TOKEN_EVENT = deepcopy(NO_TOKEN_EVENT) -COOKIE_TOKEN_EVENT["cookies"].append(f"{TEST_TOKEN_NAME}={TEST_TOKEN}") diff --git a/python/test/handlers/__init__.py b/python/test/handlers/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python/test/helpers/__init__.py b/python/test/helpers/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/python/test/helpers/test_apitoken.py b/python/test/helpers/test_apitoken.py deleted file mode 100644 index ce6b6ae0..00000000 --- a/python/test/helpers/test_apitoken.py +++ /dev/null @@ -1,24 +0,0 @@ -import os -from src.helpers.apitoken import ApiToken -from test.fixtures.apitoken import TEST_SECRET, TEST_TOKEN -from unittest import mock, TestCase - -@mock.patch.dict( - os.environ, - { - "API_TOKEN_SECRET": TEST_SECRET - } -) -class TestFunction(TestCase): - def test_empty_token(self): - subject = ApiToken() - self.assertFalse(subject.is_logged_in()) - - def test_valid_token(self): - subject = ApiToken(TEST_TOKEN) - self.assertTrue(subject.is_logged_in()) - - def test_invalid_token(self): - subject = ApiToken("INVALID_TOKEN") - self.assertFalse(subject.is_logged_in()) - \ No newline at end of file diff --git a/python/test/helpers/test_event.py b/python/test/helpers/test_event.py deleted file mode 100644 index f497150e..00000000 --- a/python/test/helpers/test_event.py +++ /dev/null @@ -1,63 +0,0 @@ -import os -from unittest import mock, TestCase - -from src.helpers.event import Event -from test.fixtures.apitoken import TEST_TOKEN_NAME, TEST_SECRET -from test.fixtures.events import ( - COOKIE_TOKEN_EVENT, - NO_BODY_EVENT, - NO_TOKEN_EVENT, - PLAIN_BODY_EVENT, - POST_EVENT -) - -@mock.patch.dict( - os.environ, - { - "API_TOKEN_NAME": TEST_TOKEN_NAME, - "API_TOKEN_SECRET": TEST_SECRET - } -) -class TestFunction(TestCase): - def test_method(self): - subject = Event(POST_EVENT) - self.assertTrue(subject.is_post_request()) - self.assertFalse(subject.is_get_request()) - self.assertFalse(subject.is_head_request()) - self.assertFalse(subject.is_options_request()) - - def test_body_base64(self): - subject = Event(POST_EVENT) - self.assertEqual(subject.body(), "POSTed Content") - - def test_body_plain(self): - subject = Event(PLAIN_BODY_EVENT) - self.assertEqual(subject.body(), "POSTed Content") - - def test_body_empty(self): - subject = Event(NO_BODY_EVENT) - self.assertIsNone(subject.body()) - - def test_cookie(self): - subject = Event(POST_EVENT) - self.assertEqual(subject.cookie("cookie_1"), "cookie_value_1") - self.assertEqual(subject.cookie("cookie_2"), "cookie_value_2") - self.assertIsNone(subject.cookie("cookie_3")) - - def test_param(self): - subject = Event(POST_EVENT) - self.assertEqual(subject.param("param1"), "value1") - self.assertEqual(subject.param("param2"), "value2") - self.assertIsNone(subject.param("param3")) - - def test_bearer_auth(self): - subject = Event(POST_EVENT) - self.assertTrue(subject.api_token.is_logged_in()) - - def test_cookie_auth(self): - subject = Event(COOKIE_TOKEN_EVENT) - self.assertTrue(subject.api_token.is_logged_in()) - - def test_unauthorized(self): - subject = Event(NO_TOKEN_EVENT) - self.assertFalse(subject.api_token.is_logged_in()) diff --git a/template.yaml b/template.yaml index 4df7461c..315f00b1 100644 --- a/template.yaml +++ b/template.yaml @@ -679,35 +679,6 @@ Resources: ApiId: !Ref dcApi Path: /chat-endpoint Method: GET - chatFunction: - Type: AWS::Serverless::Function - Properties: - CodeUri: ./python/src - Runtime: python3.9 - Handler: handlers/chat.handler - Timeout: 300 - Environment: - Variables: - AZURE_OPENAI_API_KEY: !Ref AzureOpenaiApiKey - AZURE_OPENAI_EMBEDDING_DEPLOYMENT_ID: !Ref AzureOpenaiEmbeddingDeploymentId - AZURE_OPENAI_LLM_DEPLOYMENT_ID: !Ref AzureOpenaiLlmDeploymentId - AZURE_OPENAI_RESOURCE_NAME: !Ref AzureOpenaiResourceName - WEAVIATE_API_KEY: !Ref WeaviateApiKey - WEAVIATE_URL: !Ref WeaviateUrl - PROTOTYPE_URL: !Ref PrototypeUrl - Events: - GetApiGet: - Type: HttpApi - Properties: - ApiId: !Ref dcApi - Path: /chat - Method: GET - PostApi: - Type: HttpApi - Properties: - ApiId: !Ref dcApi - Path: /chat - Method: POST defaultFunction: Type: AWS::Serverless::Function Properties: