Skip to content

Commit be39d86

Browse files
authored
Merge pull request #1 from hteeyeoh/config_yaml
chatqna-core config yaml
2 parents 1267cf6 + b8bf881 commit be39d86

File tree

17 files changed

+533
-193
lines changed

17 files changed

+533
-193
lines changed

sample-applications/chat-question-and-answer-core/app/.env

Lines changed: 0 additions & 8 deletions
This file was deleted.

sample-applications/chat-question-and-answer-core/app/chain.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .config import Settings
1+
from .config import config
22
from .utils import login_to_huggingface, download_huggingface_model, convert_model
33
from .document import load_file_document
44
from .logger import logger
@@ -14,9 +14,10 @@
1414
import os
1515
import pandas as pd
1616

17-
config = Settings()
1817
vectorstore = None
1918

19+
logger.info(f"Chatqna-Core application started with config: {config}")
20+
2021
# The RUN_TEST flag is used to bypass the model download and conversion steps during pytest unit testing.
2122
# By default, the flag is set to 'false', enabling the model download and conversion process in a normal run.
2223
# To skip these steps, set the flag to 'true'.
@@ -38,21 +39,22 @@
3839
convert_model(config.LLM_MODEL_ID, config.CACHE_DIR, "llm")
3940

4041
# Define RAG prompt
41-
template = """
42-
Use the following pieces of context from retrieved
43-
dataset to answer the question. Do not make up an answer if there is no
44-
context provided to help answer it.
45-
46-
Context:
47-
---------
48-
{context}
49-
50-
---------
51-
Question: {question}
52-
---------
53-
54-
Answer:
55-
"""
42+
# template = """
43+
# Use the following pieces of context from retrieved
44+
# dataset to answer the question. Do not make up an answer if there is no
45+
# context provided to help answer it.
46+
47+
# Context:
48+
# ---------
49+
# {context}
50+
51+
# ---------
52+
# Question: {question}
53+
# ---------
54+
55+
# Answer:
56+
# """
57+
template = config.PROMPT_TEMPLATE
5658

5759
prompt = ChatPromptTemplate.from_template(template)
5860

Lines changed: 68 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,87 @@
11
from pydantic_settings import BaseSettings
2-
from os.path import dirname, abspath, join
3-
2+
from os.path import dirname, abspath
3+
from .prompt import get_prompt_template
4+
import os
5+
import yaml
46

57
class Settings(BaseSettings):
68
"""
79
Settings for the Chatqna-Core application.
10+
This class manages configuration settings for the application, supporting loading from a YAML file,
11+
environment variables, or default values. It includes model identifiers, device settings, cache paths,
12+
and other application-specific options.
813
914
Attributes:
1015
APP_DISPLAY_NAME (str): The display name of the application.
1116
BASE_DIR (str): The base directory of the application.
12-
SUPPORTED_FORMATS (set): A set of supported file formats.
17+
SUPPORTED_FORMATS (set): Supported file formats for input documents.
1318
DEBUG (bool): Flag to enable or disable debug mode.
14-
TMP_FILE_PATH (str): The temporary file path for documents.
15-
HF_ACCESS_TOKEN (str): The Hugging Face access token.
16-
EMBEDDING_MODEL_ID (str): The ID of the embedding model.
17-
RERANKER_MODEL_ID (str): The ID of the reranker model.
18-
LLM_MODEL_ID (str): The ID of the large language model.
19-
EMBEDDING_DEVICE (str): The device used for embedding.
20-
RERANKER_DEVICE (str): The device used for reranker.
21-
LLM_DEVICE (str): The device used for LLM inferencing.
22-
CACHE_DIR (str): The directory used for caching.
23-
HF_DATASETS_CACHE (str): The cache directory for Hugging Face datasets.
24-
MAX_TOKENS (int): The maximum number of output tokens.
19+
HF_ACCESS_TOKEN (str): Hugging Face access token for model downloads.
20+
EMBEDDING_MODEL_ID (str): Identifier for the embedding model.
21+
RERANKER_MODEL_ID (str): Identifier for the reranker model.
22+
LLM_MODEL_ID (str): Identifier for the large language model.
23+
PROMPT_TEMPLATE (str): Template for prompts used by the LLM.
24+
EMBEDDING_DEVICE (str): Device to run the embedding model on (e.g., "CPU", "GPU").
25+
RERANKER_DEVICE (str): Device to run the reranker model on.
26+
LLM_DEVICE (str): Device to run the LLM on.
27+
CACHE_DIR (str): Directory for caching models.
28+
HF_DATASETS_CACHE (str): Directory for caching Hugging Face datasets.
29+
MAX_TOKENS (int): Maximum number of tokens for LLM input/output.
2530
ENABLE_RERANK (bool): Flag to enable or disable reranking.
31+
TMP_FILE_PATH (str): Temporary file path for storing documents.
32+
MODEL_CONFIG_PATH (str): Path to the YAML configuration file.
2633
27-
Config:
28-
env_file (str): The path to the environment file.
34+
Methods:
35+
__init__(**kwargs):
36+
Initializes the Settings instance, loading configuration from a YAML file if it exists,
37+
and overriding attributes with values from the file. If PROMPT_TEMPLATE is not set,
38+
it is determined based on the LLM_MODEL_ID.
2939
"""
3040

3141
APP_DISPLAY_NAME: str = "Chatqna-Core"
3242
BASE_DIR: str = dirname(dirname(abspath(__file__)))
3343
SUPPORTED_FORMATS: set = {".pdf", ".txt", ".docx"}
3444
DEBUG: bool = False
3545

36-
HF_ACCESS_TOKEN: str = ...
37-
EMBEDDING_MODEL_ID: str = ...
38-
RERANKER_MODEL_ID: str = ...
39-
LLM_MODEL_ID: str = ...
40-
EMBEDDING_DEVICE: str = ...
41-
RERANKER_DEVICE: str = ...
42-
LLM_DEVICE: str = ...
43-
CACHE_DIR: str = ...
44-
HF_DATASETS_CACHE: str = ...
45-
MAX_TOKENS: int = ...
46-
ENABLE_RERANK: bool = ...
47-
TMP_FILE_PATH: str = ...
48-
49-
class Config:
50-
env_file = join(dirname(abspath(__file__)), ".env")
46+
HF_ACCESS_TOKEN: str = ""
47+
EMBEDDING_MODEL_ID: str = ""
48+
RERANKER_MODEL_ID: str = ""
49+
LLM_MODEL_ID: str = ""
50+
PROMPT_TEMPLATE: str = ""
51+
EMBEDDING_DEVICE: str = "CPU"
52+
RERANKER_DEVICE: str = "CPU"
53+
LLM_DEVICE: str = "CPU"
54+
CACHE_DIR: str = "/tmp/model_cache"
55+
HF_DATASETS_CACHE: str = "/tmp/model_cache"
56+
MAX_TOKENS: int = 1024
57+
ENABLE_RERANK: bool = True
58+
TMP_FILE_PATH: str = "/tmp/chatqna/documents"
59+
MODEL_CONFIG_PATH: str = "/tmp/model_config/config.yaml"
60+
61+
def __init__(self, **kwargs):
62+
super().__init__(**kwargs)
63+
config_file = self.MODEL_CONFIG_PATH
64+
65+
if os.path.isfile(config_file):
66+
print(f"INFO - {config_file} exists. Loading configuration from {config_file}")
67+
with open(config_file, 'r') as f:
68+
config = yaml.safe_load(f)
69+
70+
for key, value in config.get("model_settings", {}).items():
71+
if hasattr(self, key):
72+
setattr(self, key, value)
73+
74+
for key, value in config.get("device_settings", {}).items():
75+
if hasattr(self, key):
76+
setattr(self, key, value)
77+
78+
else:
79+
print(f"WARNING - Expected a file at {config_file}, but found a directory or nothing.")
80+
print("INFO - Proceeding with default settings or previously loaded configurations from env variables.")
81+
82+
if not self.PROMPT_TEMPLATE:
83+
print("INFO - PROMPT_TEMPLATE is not set. Get prompt template based on LLM_MODEL_ID.")
84+
self.PROMPT_TEMPLATE = get_prompt_template(self.LLM_MODEL_ID)
85+
86+
87+
config = Settings()

sample-applications/chat-question-and-answer-core/app/document.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os
2-
from .config import Settings
2+
from .config import config
33
from .logger import logger
44
from pathlib import Path
55
from fastapi import UploadFile
@@ -9,8 +9,6 @@
99
TextLoader
1010
)
1111

12-
config = Settings()
13-
1412

1513
def validate_document(file_object: UploadFile):
1614
"""
@@ -85,4 +83,4 @@ def load_file_document(file_path):
8583

8684
docs = loader.load()
8785

88-
return docs
86+
return docs

sample-applications/chat-question-and-answer-core/app/logger.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
from .config import Settings
1+
from .config import config
22
from typing import Optional
33
import logging
44
import sys
55

6-
config = Settings()
76

87
def initialize_logger(name: Optional[str] = None) -> logging.Logger:
98
"""
@@ -39,5 +38,4 @@ def initialize_logger(name: Optional[str] = None) -> logging.Logger:
3938
return logger
4039

4140

42-
# Optional: create a default logger instance for convenience
4341
logger = initialize_logger(config.APP_DISPLAY_NAME)
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Defaul prompt template for RAG (Retrieval-Augmented Generation)
2+
default_rag_prompt_template = """
3+
Use the following pieces of context from retrieved
4+
dataset to answer the question. Do not make up an answer if there is no
5+
context provided to help answer it.
6+
7+
Context:
8+
---------
9+
{context}
10+
11+
---------
12+
Question: {question}
13+
---------
14+
15+
Answer:
16+
"""
17+
18+
# Define the prompt templates for validated model IDs
19+
model_prompt_templates = {
20+
"microsoft/Phi-3.5-mini-instruct": """
21+
<|system|>
22+
Use the following pieces of context from retrieved
23+
dataset to answer the question. Do not make up an answer if there is no
24+
context provided to help answer it.<|end|>
25+
26+
<|context|>
27+
Context:
28+
---------
29+
{context}
30+
<|end|>
31+
32+
<|user|>
33+
---------
34+
Question: {question}
35+
---------
36+
<|end|>
37+
38+
<|assistant|>
39+
Answer:
40+
""",
41+
"Intel/neural-chat-7b-v3-3": """
42+
### System:
43+
Use the following pieces of context from retrieved
44+
dataset to answer the question. Do not make up an answer if there is no
45+
context provided to help answer it.
46+
47+
### Context:
48+
{context}
49+
50+
### User:
51+
{question}
52+
53+
### Assistant:
54+
""",
55+
"meta-llama/Llama-3.1-8B-Instruct":
56+
"""
57+
<|start_header_id|>system<|end_header_id|>
58+
Use the following pieces of context from retrieved
59+
dataset to answer the question. Do not make up an answer if there is no
60+
context provided to help answer it.
61+
62+
<context>
63+
Context:
64+
{context}
65+
</context>
66+
67+
<|start_header_id|>user<|end_header_id|>
68+
Question: {question}
69+
<|eot_id|>
70+
71+
<|start_header_id|>assistant<|end_header_id|>
72+
""",
73+
"Qwen/Qwen2.5-7B-Instruct": """
74+
<|im_start|>
75+
system:
76+
Use the following pieces of context from retrieved
77+
dataset to answer the question. Do not make up an answer if there is no
78+
context provided to help answer it.
79+
80+
context:
81+
{context}
82+
<|im_end|>
83+
84+
<|im_start|>
85+
user:
86+
{question}
87+
<|im_end|>
88+
89+
<|im_start|>assistant
90+
"""
91+
}
92+
93+
def get_prompt_template(llm_model_id: str) -> str:
94+
"""
95+
Get the prompt template for a given model ID.
96+
97+
Args:
98+
model_id (str): The model ID to get the prompt template for.
99+
100+
Returns:
101+
str: The prompt template for the specified model ID.
102+
"""
103+
104+
# If the model ID is not in the predefined templates, return the default RAG prompt template
105+
return model_prompt_templates.get(llm_model_id, default_rag_prompt_template)

sample-applications/chat-question-and-answer-core/app/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from http import HTTPStatus
99
from pydantic import BaseModel
1010
from typing import Annotated
11-
from .config import Settings
11+
from .config import config
1212
from .logger import logger
1313
from .chain import (
1414
create_faiss_vectordb,
@@ -23,8 +23,6 @@
2323

2424
app = FastAPI(root_path="/v1/chatqna")
2525

26-
config = Settings()
27-
2826
app.add_middleware(
2927
CORSMiddleware,
3028
allow_origins=os.getenv("CORS_ALLOW_ORIGINS", "*").split(
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
apiVersion: v1
2+
kind: ConfigMap
3+
metadata:
4+
name: model-config
5+
data:
6+
config.yaml: |
7+
model_settings:
8+
EMBEDDING_MODEL_ID: "BAAI/bge-small-en-v1.5"
9+
RERANKER_MODEL_ID: "BAAI/bge-reranker-base"
10+
LLM_MODEL_ID: "microsoft/Phi-3.5-mini-instruct"
11+
PROMPT_TEMPLATE: "
12+
<|system|>
13+
Use the following pieces of context from retrieved
14+
dataset to answer the question. Do not make up an answer if there is no
15+
context provided to help answer it.<|end|>
16+
17+
<|context|>
18+
Context:
19+
---------
20+
{context}
21+
<|end|>
22+
23+
<|user|>
24+
---------
25+
Question: {question}
26+
---------
27+
<|end|>
28+
29+
<|assistant|>
30+
Answer:
31+
"

0 commit comments

Comments
 (0)