Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup/october merge #181

Closed
wants to merge 49 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a808cde
Merge pull request #105 from mit-submit/hotfix/malformed-json-lock-ra…
julius-heitkoetter Oct 16, 2023
364efad
Merge pull request #110 from mit-submit/main
julius-heitkoetter Oct 18, 2023
7c6811c
Merge pull request #116 from mit-submit/main
julius-heitkoetter Oct 20, 2023
5053f3a
Merge pull request #118 from mit-submit/main
mdr223 Oct 21, 2023
15714bb
up query limit and fail gracefully if history is empty
mdr223 Oct 25, 2023
44243d8
Merge pull request #120 from mit-submit/hotfix/up-query-limit-fail-gr…
mdr223 Oct 25, 2023
79b6271
sleep for 5 mins to let data manager catch up
mdr223 Oct 26, 2023
3c6c58d
move sleep inside init
mdr223 Oct 26, 2023
b277f9f
remove sleep
mdr223 Oct 26, 2023
588d64a
move to 7684
mdr223 Oct 26, 2023
34eaaaa
moving back to port 7683
julius-heitkoetter Oct 26, 2023
aa556a8
Merge pull request #128 from mit-submit/cleanup/8.01_release_after_lo…
julius-heitkoetter Oct 26, 2023
dfb9274
adding final changes to include update config command
mdr223 Jan 5, 2024
30149a4
adding summary prompt for future
mdr223 Jan 5, 2024
39fc410
updated 801 course info to f24
Sep 10, 2024
e26e03d
redeploying with f24 syllabus in place
Sep 12, 2024
993b079
adding piazza service for 801
Sep 17, 2024
d99d8bd
removing extra ' in compose yaml
pmlugato Sep 19, 2024
6e8d154
Merge pull request #165 from mit-submit/feature/801_piazza_service
pmlugato Sep 19, 2024
03c0088
missing comma in pyproject.toml
Sep 19, 2024
243660b
Merge pull request #167 from mit-submit/feature/801_piazza_service
pmlugato Sep 19, 2024
f96d11b
wrong filename
Sep 19, 2024
584ea41
changing code to better reflect new deployment scheme; minor bug fixes
julius-heitkoetter Oct 30, 2024
ecf44cb
removing old deployment scheme and million configuration files
julius-heitkoetter Oct 30, 2024
72e8607
small update to requirements and pyproject.toml
julius-heitkoetter Oct 30, 2024
2c159a9
updating cli code to use local image builds with updated code when rerun
julius-heitkoetter Oct 30, 2024
6c4d130
changing configurations such that user configuration is override of w…
julius-heitkoetter Oct 30, 2024
1097092
adding cli documentation
julius-heitkoetter Oct 30, 2024
af44639
changing pyproject to be lightweight
julius-heitkoetter Oct 30, 2024
f2f4ea9
requirements.txt
julius-heitkoetter Oct 30, 2024
157a95d
catching up 801
Oct 30, 2024
5f00e0c
Merge pull request #175 from mit-submit/release-8.01
pmlugato Oct 30, 2024
fef33b2
Merge pull request #176 from mit-submit/staging/801_to_cleanup
pmlugato Oct 30, 2024
77af384
adding uploader service and more documentation
julius-heitkoetter Oct 30, 2024
494ab39
Merge branch 'cleanup/october_merge' of https://github.com/mit-submit…
julius-heitkoetter Oct 30, 2024
498f473
migrating anthropic functionality to cleanup
Oct 30, 2024
47637c5
new langchain new requirements
Oct 30, 2024
5568659
anthropic for base compose and config
Oct 30, 2024
f105d59
adding ability to specify which port things are being run on
julius-heitkoetter Oct 31, 2024
9f3a0c0
little updates and configs folder
Oct 31, 2024
8b9ddf6
bug fixes
Nov 1, 2024
369b122
8511 intitial stuff
Nov 1, 2024
e2848d9
adding first pass at incorperating cleo, need to wait for passwords t…
julius-heitkoetter Nov 5, 2024
518eb24
Merge branch 'cleanup/october_merge' into feature/cleo_and_mailbox_in…
julius-heitkoetter Nov 26, 2024
8cb26bc
more sustainable way of using secrets
julius-heitkoetter Nov 26, 2024
d4d9f89
adding configurations for submit
julius-heitkoetter Nov 26, 2024
e3aeef0
adding where the secrets are located to config
julius-heitkoetter Nov 26, 2024
d670164
SQUASH: of many bug fixes
julius-heitkoetter Nov 26, 2024
50eb489
Merge pull request #180 from mit-submit/feature/cleo_and_mailbox_into…
julius-heitkoetter Nov 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/prod-801-ci-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ jobs:
/bin/bash ${workspace}/deploy/create_secret.sh hf_token.txt ${{ secrets.HF_TOKEN }}
/bin/bash ${workspace}/deploy/create_secret.sh pg_password.txt ${{ secrets.PROD_801_PG_PASSWORD }}
/bin/bash ${workspace}/deploy/create_secret.sh grafana_password.txt ${{ secrets.PROD_801_GRAFANA_PG_PASSWORD }}
/bin/bash ${workspace}/deploy/create_secret.sh piazza_email.txt ${{ secrets.PROD_801_PIAZZA_EMAIL }}
/bin/bash ${workspace}/deploy/create_secret.sh piazza_password.txt ${{ secrets.PROD_801_PIAZZA_PASSWORD }}
/bin/bash ${workspace}/deploy/create_secret.sh slack_webhook.txt ${{ secrets.PROD_801_SLACK_WEBHOOK }}

# create env file to set tag(s) for docker-compose
- name: Create Env File
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/prod-root-ci-cd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ jobs:
/bin/bash ${workspace}/deploy/create_secret.sh flask_uploader_app_secret_key.txt ${{ secrets.PROD_FLASK_UPLOADER_APP_SECRET_KEY }}
/bin/bash ${workspace}/deploy/create_secret.sh uploader_salt.txt ${{ secrets.PROD_UPLOADER_SALT }}
/bin/bash ${workspace}/deploy/create_secret.sh openai_api_key.txt ${{ secrets.OPENAI_API_KEY }}
/bin/bash ${workspace}/deploy/create_secret.sh anthropic_api_key.txt ${{ secrets.ANTHROPIC_API_KEY }}
/bin/bash ${workspace}/deploy/create_secret.sh hf_token.txt ${{ secrets.HF_TOKEN }}
/bin/bash ${workspace}/deploy/create_secret.sh pg_password.txt ${{ secrets.PROD_ROOT_PG_PASSWORD }}
/bin/bash ${workspace}/deploy/create_secret.sh grafana_password.txt ${{ secrets.PROD_ROOT_GRAFANA_PG_PASSWORD }}
Expand All @@ -52,30 +53,30 @@ jobs:
# create deployment directory if it doesn't already exist
- name: Create Directory
run: |
ssh submit06 "mkdir -p ~/A2rchi-prod-root/"
ssh submit-t3desk018 "mkdir -p ~/A2rchi-prod-root/"

# stop any existing docker compose that's running
- name: Stop Docker Compose
run: |
ssh submit06 'bash -s' < ${{ github.workspace }}/deploy/prod-root/prod-root-stop.sh
ssh submit-t3desk018 'bash -s' < ${{ github.workspace }}/deploy/prod-root/prod-root-stop.sh

# copy repository to machine
- name: Copy Repository
run: |
rsync -e ssh -r ${{ github.workspace}}/* --exclude .git/ --delete submit06:~/A2rchi-prod-root/
rsync -e ssh -r ${{ github.workspace}}/* --exclude .git/ --delete submit-t3desk018:~/A2rchi-prod-root/

# run deploy script
- name: Run Deploy Script
run: |
export tag="${GITHUB_REF#refs/heads/}"
export tag="${tag//\//-}.${GITHUB_SHA}"
sed -i "s/BASE_TAG/${tag}/" ${{ github.workspace }}/deploy/prod-root/prod-root-install.sh
ssh submit06 'bash -s' < ${{ github.workspace }}/deploy/prod-root/prod-root-install.sh
ssh submit-t3desk018 'bash -s' < ${{ github.workspace }}/deploy/prod-root/prod-root-install.sh

# clean up secret files
- name: Remove Secrets from Runner
run: |
rm ${{ github.workspace }}/deploy/prod-root/secrets/*.txt

# print job status
- run: echo "🍏 This job's status is ${{ job.status }}."
- run: echo "🍏 This job's status is ${{ job.status }}."
2 changes: 2 additions & 0 deletions a2rchi/bin/service_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
import os

# set openai
os.environ['ANTHROPIC_API_KEY'] = read_secret("ANTHROPIC_API_KEY")
os.environ['OPENAI_API_KEY'] = read_secret("OPENAI_API_KEY")
os.environ['HUGGING_FACE_HUB_TOKEN'] = read_secret("HUGGING_FACE_HUB_TOKEN")
config = Config_Loader().config["interfaces"]["chat_app"]
global_config = Config_Loader().config["global"]
print(f"Starting Chat Service with (host, port): ({config['HOST']}, {config['PORT']})")
print(f"Accessible externally at (host, port): ({config['HOSTNAME']}, {config['EXTERNAL_PORT']})")

def generate_script(config):
"""
Expand Down
1 change: 1 addition & 0 deletions a2rchi/bin/service_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@


# set openai
os.environ['ANTHROPIC_API_KEY'] = read_secret("ANTHROPIC_API_KEY")
os.environ['OPENAI_API_KEY'] = read_secret("OPENAI_API_KEY")
os.environ['HUGGING_FACE_HUB_TOKEN'] = read_secret("HUGGING_FACE_HUB_TOKEN")

Expand Down
31 changes: 19 additions & 12 deletions a2rchi/chains/base.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
"""Chain for chatting with a vector database."""
from __future__ import annotations
from pydantic import BaseModel
from loguru import logger
from langchain.callbacks import FileCallbackHandler
from langchain_core.callbacks.file import FileCallbackHandler

from a2rchi.chains.prompts import CONDENSE_QUESTION_PROMPT, QA_PROMPT
from a2rchi.chains.prompts import CONDENSE_QUESTION_PROMPT, QA_PROMPT #SUMMARY_PROMPT
from a2rchi.utils.config_loader import Config_Loader

from langchain.base_language import BaseLanguageModel
from langchain.chains.combine_documents.stuff import StuffDocumentsChain
from langchain_core.language_models.base import BaseLanguageModel
from langchain.chains.combine_documents.stuff import StuffDocumentsChain # deprecated, should update
from langchain.chains.conversational_retrieval.base import BaseConversationalRetrievalChain
from langchain.chains.llm import LLMChain
from langchain.schema import BaseRetriever, Document
from langchain.schema.prompt_template import BasePromptTemplate
from langchain.chains.llm import LLMChain # deprecated, should update
from langchain_core.retrievers import BaseRetriever
from langchain_core.documents import Document
from langchain_core.prompts.base import BasePromptTemplate
from langchain_core.runnables import RunnableSequence, RunnablePassthrough
from typing import Any, Dict, List, Optional, Tuple
from typing import Callable
import os


Expand Down Expand Up @@ -46,7 +50,7 @@ class BaseSubMITChain(BaseConversationalRetrievalChain):
"""
retriever: BaseRetriever # Index to connect to
max_tokens_limit: Optional[int] = None # restrict doc length to return from store, enforced only for StuffDocumentChain
get_chat_history: Optional[function] = _get_chat_history
get_chat_history: Optional[Callable[[List[Tuple[str, str]]], str]] = _get_chat_history

def _reduce_tokens_below_limit(self, docs: List[Document]) -> List[Document]:
num_docs = len(docs)
Expand Down Expand Up @@ -81,22 +85,25 @@ def from_llm(
cls,
llm: BaseLanguageModel,
retriever: BaseRetriever,
qa_prompt: BasePromptTemplate = QA_PROMPT,
condense_question_prompt: BasePromptTemplate = CONDENSE_QUESTION_PROMPT,
summary_prompt: BasePromptTemplate = CONDENSE_QUESTION_PROMPT,
chain_type: str = "stuff",
verbose: bool = False,
condense_question_llm: Optional[BaseLanguageModel] = None,
summary_llm: Optional[BaseLanguageModel] = None,
combine_docs_chain_kwargs: Optional[Dict] = None,
**kwargs: Any,
) -> BaseConversationalRetrievalChain:
# Load chain from LLM
combine_docs_chain_kwargs = combine_docs_chain_kwargs or {}
_prompt = QA_PROMPT
_prompt = qa_prompt
document_variable_name = "context"

#Add logger for storing input to the QA chain, ie filled QA template
logfile = os.path.join(data_path,config["logging"]["input_output_filename"])
logfile = os.path.join(data_path, config["logging"]["input_output_filename"])
logger.add(logfile, colorize=True, enqueue=True)
handler = FileCallbackHandler(logfile)
handler = FileCallbackHandler(logfile)

llm_chain = LLMChain(
llm=llm,
Expand All @@ -121,4 +128,4 @@ def from_llm(
question_generator=condense_question_chain,
**kwargs,
)


87 changes: 74 additions & 13 deletions a2rchi/chains/chain.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from a2rchi.chains.base import BaseSubMITChain as BaseChain
from a2rchi.chains.prompts import read_prompt
from a2rchi.utils.config_loader import Config_Loader

from chromadb.config import Settings
from langchain.vectorstores import Chroma
from langchain.prompts.prompt import PromptTemplate
from langchain_chroma.vectorstores import Chroma

from langchain.chains.conversation.memory import ConversationSummaryMemory
from langchain.chains import ConversationChain

import chromadb
import time


class Chain() :
Expand All @@ -16,29 +21,59 @@ def __init__(self):
those documents.
"""
self.kill = False
self.update_config()


from a2rchi.utils.config_loader import Config_Loader
self.config = Config_Loader().config["chains"]["chain"]
self.global_config = Config_Loader().config["global"]
self.utils_config = Config_Loader().config["utils"]
def update_config(self):
print("Chain Updating Config")
self.config = Config_Loader().config
self.chain_config = self.config["chains"]["chain"]
self.global_config = self.config["global"]
self.utils_config = self.config["utils"]
self.prompt_config = self.config["chains"]["prompts"]

embedding_class_map = self.utils_config["embeddings"]["EMBEDDING_CLASS_MAP"]
embedding_name = self.utils_config["embeddings"]["EMBEDDING_NAME"]
self.embedding_model = embedding_class_map[embedding_name]["class"](**embedding_class_map[embedding_name]["kwargs"])
self.collection_name = self.utils_config["data_manager"]["collection_name"] + "_with_" + embedding_name

print("Using collection: ", self.collection_name)

model_class_map = self.config["MODEL_CLASS_MAP"]
model_name = self.config["MODEL_NAME"]

model_class_map = self.chain_config["MODEL_CLASS_MAP"]
model_name = self.chain_config["MODEL_NAME"]
condense_model_name = self.chain_config.get("CONDENSE_MODEL_NAME", model_name)
summary_model_name = self.chain_config.get("SUMMARY_MODEL_NAME", model_name)
self.llm = model_class_map[model_name]["class"](**model_class_map[model_name]["kwargs"])
self.condense_llm = model_class_map[condense_model_name]["class"](**model_class_map[condense_model_name]["kwargs"])
self.summary_llm = model_class_map[summary_model_name]["class"](**model_class_map[summary_model_name]["kwargs"])

print("Using model ", model_name, " with parameters: ")
for param_name in model_class_map[model_name]["kwargs"].keys():
print("\t" , param_name , ": " , model_class_map[model_name]["kwargs"][param_name])

print("Using condense model ", condense_model_name, " with parameters: ")
for param_name in model_class_map[condense_model_name]["kwargs"].keys():
print("\t" , param_name , ": " , model_class_map[condense_model_name]["kwargs"][param_name])

# self.qa_prompt = PromptTemplate(
# template=read_prompt(self.prompt_config["MAIN_PROMPT"], is_main_prompt=True), input_variables=["history", "input"]
# )
self.qa_prompt = PromptTemplate(
template=read_prompt(self.prompt_config["MAIN_PROMPT"], is_main_prompt=True), input_variables=["context", "question"]
)

self.condense_question_prompt = PromptTemplate(
template=read_prompt(self.prompt_config["CONDENSING_PROMPT"], is_condense_prompt=True), input_variables=["chat_history", "question"]
)

def update_vectorstore_and_create_chain(self):
self.summary_prompt = PromptTemplate(
template=read_prompt(self.prompt_config["SUMMARY_PROMPT"]), input_variables=["summary", "new_lines"]
)

# TODO: may want to add this back if we allow ConversationChain + ConversationSummaryMemory
# self.memory_map = {}

def update_vectorstore_and_create_chain(self, conversation_id):
# connect to chromadb server
client = None
if self.utils_config["data_manager"]["use_HTTP_chromadb_client"]:
Expand All @@ -59,10 +94,31 @@ def update_vectorstore_and_create_chain(self):
collection_name=self.collection_name,
embedding_function=self.embedding_model,
)
chain = BaseChain.from_llm(self.llm, vectorstore.as_retriever(), return_source_documents=True)
chain = BaseChain.from_llm(
self.llm,
vectorstore.as_retriever(),
qa_prompt=self.qa_prompt,
condense_question_prompt=self.condense_question_prompt,
summary_prompt=self.summary_prompt,
condense_question_llm=self.condense_llm,
summary_llm=self.summary_llm,
return_source_documents=True,
)
print(f"N entries: {client.get_collection(self.collection_name).count()}")
print("Updated chain with new vectorstore")

# TODO: make it eas(ier) for users to use diff. LangChain chains
# # TODO: try to load/construct memory from past conversation if not in memory map (i.e. check postgres)
# if conversation_id not in self.memory_map:
# self.memory_map[conversation_id] = ConversationSummaryMemory(
# llm=self.summary_llm,
# prompt=self.summary_prompt,
# max_token_limit=256,
# )

# memory = self.memory_map[conversation_id]
# chain = ConversationChain(llm=self.llm, memory=memory, prompt=self.qa_prompt, verbose=True)

return chain


Expand Down Expand Up @@ -106,7 +162,7 @@ def similarity_search(self, input):
return score


def __call__(self, history):
def __call__(self, history, conversation_id = None):
"""
Call for the chain to answer a question

Expand All @@ -117,7 +173,7 @@ def __call__(self, history):
Output: a dictionary containing the answer and some meta data.
"""
# create chain w/up-to-date vectorstore
chain = self.update_vectorstore_and_create_chain()
chain = self.update_vectorstore_and_create_chain(conversation_id)

# seperate out the history into past interaction and current question input
if len(history) > 0 and len(history[-1]) > 1:
Expand All @@ -132,6 +188,11 @@ def __call__(self, history):

# make the request to the chain
answer = chain({"question": question, "chat_history": chat_history})

# TODO: this was used with ConversationChain w/ConversationSummaryMemory
# answer = chain(question)
# answer['answer'] = answer['response']
# answer['source_documents'] = []
print(f" INFO - answer: {answer}")

# delete chain object to release chain, vectorstore, and client for garbage collection
Expand Down
Loading