nikhilkomakula commited on
Commit
27b774b
·
1 Parent(s): 4d13c26

Gradio + Streamlit

Browse files
Dockerfile CHANGED
@@ -28,9 +28,8 @@ ENV HOME=/home/user \
28
  # Set the working directory to the user's home directory
29
  WORKDIR $HOME/app
30
 
31
- # Expose the secret HUGGINGFACEHUB_API_TOKEN at buildtime and use its value to clone the repo
32
- RUN --mount=type=secret,id=HUGGINGFACEHUB_API_TOKEN,mode=0444,required=true \
33
- git clone --depth 1 https://github.com/nikhilkomakula/llm-rag-op-chatbot.git $HOME/app
34
 
35
  # Use ENTRYPOINT to specify the command to run when the container starts
36
- ENTRYPOINT ["python", "app.py"]
 
28
  # Set the working directory to the user's home directory
29
  WORKDIR $HOME/app
30
 
31
+ # Clone the Git repo
32
+ RUN git clone --depth 1 https://github.com/nikhilkomakula/llm-rag-op-chatbot.git $HOME/app
 
33
 
34
  # Use ENTRYPOINT to specify the command to run when the container starts
35
+ ENTRYPOINT ["python", "gradio_ui.py"]
README.md CHANGED
@@ -113,6 +113,14 @@ docker ps -a
113
  docker logs -f llm-rag-op-chatbot
114
  ```
115
 
 
 
 
 
 
 
 
 
116
  ## Technologies Used:
117
 
118
  * **PDF Parser :** PyMuPDFLoader
 
113
  docker logs -f llm-rag-op-chatbot
114
  ```
115
 
116
+ ## REST API:
117
+
118
+ **Note:** Navigate to the chat interface UI in the browser and locate `Use via API` and click on it. A fly over opens on the right hand side. Capture the URL under the title named `API documentation`.
119
+
120
+ * **URL:** `<http|https>`://`<hostname`:`<port>`/run/chat
121
+ * **METHOD:** POST
122
+ * **BODY:** { "data": ["`<query>`", ""] }
123
+
124
  ## Technologies Used:
125
 
126
  * **PDF Parser :** PyMuPDFLoader
app.py CHANGED
@@ -1,23 +1,29 @@
1
  # import libraries
2
  import sys
3
- from dotenv import find_dotenv, load_dotenv
4
 
5
- # import functions
6
- from src.test.eval_rag import evaluate_rag
7
- from src.ui.chat_interface import create_chatinterface
8
- from src.generation.generate_response import get_qa_chain, set_global_qa_chain, generate_response
9
 
10
- # find .env automatically by walking up directories until it's found, then
11
- # load up the .env entries as environment variables
12
- load_dotenv(find_dotenv())
 
 
13
 
14
- if __name__ == "__main__":
15
-
16
- # get the qa chain
17
- qa_chain = get_qa_chain()
18
-
19
- if len(sys.argv) > 1:
20
- evaluate_rag("qa_chain", qa_chain)
 
21
  else:
22
- set_global_qa_chain(qa_chain)
23
- create_chatinterface(generate_response).launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
1
  # import libraries
2
  import sys
3
+ import subprocess
4
 
5
+ # Define functions for Gradio and Streamlit interfaces
6
+ def run_gradio_interface():
7
+ subprocess.run(["python", "gradio_ui.py"])
 
8
 
9
+ def run_streamlit_interface():
10
+ subprocess.run(["streamlit", "run", "streamlit_ui.py"])
11
+
12
+ def run_rag_evaluate():
13
+ subprocess.run(["python", "eval.py"])
14
 
15
+ # Main function to determine which interface to run
16
+ def main():
17
+ if "-gradio" in sys.argv:
18
+ print("Initializing Gradio Interface!")
19
+ run_gradio_interface()
20
+ elif "-streamlit" in sys.argv:
21
+ print("Initializing Streamlit Interface!")
22
+ run_streamlit_interface()
23
  else:
24
+ print("Running RAG Evaluation!")
25
+ run_rag_evaluate()
26
+
27
+ # Run the main function
28
+ if __name__ == "__main__":
29
+ main()
eval.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # import libraries
2
+ from dotenv import find_dotenv, load_dotenv
3
+
4
+ # import functions
5
+ from src.test.eval_rag import evaluate_rag
6
+ from src.generation.generate_response import get_qa_chain
7
+
8
+ def main():
9
+
10
+ # find .env automatically by walking up directories until it's found, then
11
+ # load up the .env entries as environment variables
12
+ load_dotenv(find_dotenv())
13
+
14
+ # get the qa chain
15
+ qa_chain = get_qa_chain()
16
+
17
+ # evaluate the qa chain
18
+ evaluate_rag("qa_chain", qa_chain)
19
+
20
+ if __name__ == "__main__":
21
+ main()
gradio_ui.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # import libraries
2
+ from dotenv import find_dotenv, load_dotenv
3
+
4
+ # import functions
5
+ from src.ui.gradio_chat_interface import create_gradio_chatinterface
6
+ from src.generation.generate_response import get_qa_chain, set_global_qa_chain, generate_response_gradio
7
+
8
+ def main():
9
+
10
+ # find .env automatically by walking up directories until it's found, then
11
+ # load up the .env entries as environment variables
12
+ load_dotenv(find_dotenv())
13
+
14
+ # get the qa chain
15
+ qa_chain = get_qa_chain()
16
+
17
+ # set the global qa chain
18
+ set_global_qa_chain(qa_chain)
19
+
20
+ # initiate the chat interface
21
+ create_gradio_chatinterface(generate_response_gradio).launch(server_name="0.0.0.0", server_port=7860)
22
+
23
+ if __name__ == "__main__":
24
+ main()
requirements.txt CHANGED
@@ -7,4 +7,5 @@ pymupdf==1.23.26
7
  sentence-transformers==2.5.1
8
  tensorflow==2.16.1
9
  gradio==4.21.0
10
- pandas==2.2.1
 
 
7
  sentence-transformers==2.5.1
8
  tensorflow==2.16.1
9
  gradio==4.21.0
10
+ pandas==2.2.1
11
+ streamlit==1.32.2
src/generation/generate_response.py CHANGED
@@ -1,9 +1,11 @@
1
  # import libraries
2
  import time
 
3
  from src.retrieval.retriever_chain import get_base_retriever, load_hf_llm, create_qa_chain
4
 
5
  # constants
6
- HF_MODEL = "huggingfaceh4/zephyr-7b-beta" # "mistralai/Mistral-7B-Instruct-v0.2" # "google/gemma-7b"
 
7
 
8
 
9
  # get the qa chain
@@ -16,7 +18,7 @@ def get_qa_chain():
16
  """
17
 
18
  # get retriever
19
- retriever = get_base_retriever(k=4, search_type="mmr")
20
 
21
  # instantiate llm
22
  llm = load_hf_llm(repo_id=HF_MODEL, max_new_tokens=512, temperature=0.4)
@@ -28,17 +30,22 @@ def get_qa_chain():
28
 
29
 
30
  def set_global_qa_chain(local_qa_chain):
 
 
 
 
 
 
31
  global global_qa_chain
32
  global_qa_chain = local_qa_chain
33
-
34
-
35
- # function to generate response
36
- def generate_response(message, history):
37
  """
38
  Generates response based on the question being asked.
39
 
40
  Args:
41
- message (str): Question asked by the user.
42
  history (dict): Chat history. NOT USED FOR NOW.
43
 
44
  Returns:
@@ -46,12 +53,48 @@ def generate_response(message, history):
46
  """
47
 
48
  # invoke chain
49
- print("Question:", message)
 
50
  start_time = time.time()
51
- query = message
52
  response = global_qa_chain.invoke(query)
53
  print("Answer:", response)
54
  end_time = time.time()
55
  print("Response Time:", "{:.2f}".format(round(end_time - start_time, 2)))
56
-
57
  return response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  # import libraries
2
  import time
3
+ from typing import Optional
4
  from src.retrieval.retriever_chain import get_base_retriever, load_hf_llm, create_qa_chain
5
 
6
  # constants
7
+ HF_MODEL = "huggingfaceh4/zephyr-7b-beta" # "mistralai/Mistral-7B-Instruct-v0.2" # "google/gemma-7b"
8
+ EMBEDDING_MODEL = "BAAI/bge-large-en-v1.5"
9
 
10
 
11
  # get the qa chain
 
18
  """
19
 
20
  # get retriever
21
+ retriever = get_base_retriever(embedding_model=EMBEDDING_MODEL, k=4, search_type="mmr")
22
 
23
  # instantiate llm
24
  llm = load_hf_llm(repo_id=HF_MODEL, max_new_tokens=512, temperature=0.4)
 
30
 
31
 
32
  def set_global_qa_chain(local_qa_chain):
33
+ """
34
+ Sets the Global QA Chain.
35
+
36
+ Args:
37
+ local_qa_chain: Local QA Chain.
38
+ """
39
  global global_qa_chain
40
  global_qa_chain = local_qa_chain
41
+
42
+ # function to generate streamlit response
43
+ def generate_response(query: str):
 
44
  """
45
  Generates response based on the question being asked.
46
 
47
  Args:
48
+ query (str): Question asked by the user.
49
  history (dict): Chat history. NOT USED FOR NOW.
50
 
51
  Returns:
 
53
  """
54
 
55
  # invoke chain
56
+ print("*" * 100)
57
+ print("Question:", query)
58
  start_time = time.time()
 
59
  response = global_qa_chain.invoke(query)
60
  print("Answer:", response)
61
  end_time = time.time()
62
  print("Response Time:", "{:.2f}".format(round(end_time - start_time, 2)))
63
+ print("*" * 100)
64
  return response
65
+
66
+ # function to generate streamlit response
67
+ def generate_response_streamlit(message: str, history: Optional[dict]):
68
+ """
69
+ Generates response based on the question being asked.
70
+
71
+ Args:
72
+ message (str): Question asked by the user.
73
+ history (dict): Chat history. NOT USED FOR NOW.
74
+
75
+ Returns:
76
+ str: Returns the generated response.
77
+ """
78
+
79
+ response = generate_response(message)
80
+ for word in response.split():
81
+ yield word + " "
82
+ time.sleep(0.05)
83
+
84
+ # function to generate response
85
+ def generate_response_gradio(message: str, history: Optional[dict]):
86
+ """
87
+ Generates response based on the question being asked.
88
+
89
+ Args:
90
+ message (str): Question asked by the user.
91
+ history (dict): Chat history. NOT USED FOR NOW.
92
+
93
+ Returns:
94
+ str: Returns the generated response.
95
+ """
96
+
97
+ response = generate_response(message)
98
+ for i in range(len(response)):
99
+ time.sleep(0.01)
100
+ yield response[: i+1]
src/indexing/build_indexes.py CHANGED
@@ -1,11 +1,11 @@
1
  # import libraries
2
  import os
3
- from typing import List, Optional
4
  from transformers import AutoTokenizer
5
  from langchain_community.vectorstores import Chroma
6
  from sentence_transformers import SentenceTransformer
7
  from langchain.text_splitter import RecursiveCharacterTextSplitter
8
- from langchain_community.embeddings import HuggingFaceBgeEmbeddings
9
  from langchain.docstore.document import Document
10
 
11
  # import functions
@@ -13,13 +13,15 @@ from ..data.load_dataset import load_documents
13
 
14
  # constants
15
  INDEX_DIR = "indexes/"
16
- EMBEDDING_MODEL = "BAAI/bge-large-en-v1.5"
17
 
18
 
19
  # instantiate embedding model
20
- def load_embedding_model():
21
  """
22
  Load the embedding model.
 
 
 
23
 
24
  Returns:
25
  HuggingFaceBgeEmbeddings: Returns the embedding model.
@@ -32,7 +34,7 @@ def load_embedding_model():
32
  print("device:", device)
33
 
34
  hf_bge_embeddings = HuggingFaceBgeEmbeddings(
35
- model_name=EMBEDDING_MODEL,
36
  model_kwargs={"device": device},
37
  encode_kwargs={
38
  "normalize_embeddings": True # set True to compute cosine similarity
@@ -41,17 +43,31 @@ def load_embedding_model():
41
 
42
  # To get the value of the max sequence_length, we will query the underlying `SentenceTransformer` object used in the RecursiveCharacterTextSplitter.
43
  print(
44
- f"Model's maximum sequence length: {SentenceTransformer(EMBEDDING_MODEL).max_seq_length}"
45
  )
46
 
47
  return hf_bge_embeddings
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  # split documents
51
  def chunk_documents(
52
  chunk_size: int,
53
  knowledge_base: List[Document],
54
- tokenizer_name: Optional[str] = EMBEDDING_MODEL,
55
  ) -> List[Document]:
56
  """
57
  Split documents into chunks of maximum size `chunk_size` tokens and return a list of documents.
@@ -90,9 +106,12 @@ def chunk_documents(
90
 
91
 
92
  # generate indexes
93
- def generate_indexes():
94
  """
95
  Generates indexes.
 
 
 
96
 
97
  Returns:
98
  ChromaCollection: Returns vector store.
@@ -104,16 +123,16 @@ def generate_indexes():
104
  # chunk documents to honor the context length
105
  chunked_documents = chunk_documents(
106
  SentenceTransformer(
107
- EMBEDDING_MODEL
108
  ).max_seq_length, # We choose a chunk size adapted to our model
109
  documents,
110
- tokenizer_name=EMBEDDING_MODEL,
111
  )
112
 
113
  # save indexes to disk
114
  vector_store = Chroma.from_documents(
115
  documents=chunked_documents,
116
- embedding=load_embedding_model(),
117
  collection_metadata={"hnsw:space": "cosine"},
118
  persist_directory=INDEX_DIR,
119
  )
@@ -122,24 +141,30 @@ def generate_indexes():
122
 
123
 
124
  # load indexes from disk
125
- def load_indexes():
126
  """
127
  Loads indexes into memory.
 
 
 
128
 
129
  Returns:
130
  ChromaCollection: Returns vector store.
131
  """
132
 
133
  vector_store = Chroma(
134
- persist_directory=INDEX_DIR, embedding_function=load_embedding_model()
135
  )
136
  return vector_store
137
 
138
 
139
  # retrieve vector store
140
- def retrieve_indexes():
141
  """
142
  Retrieves indexes.
 
 
 
143
 
144
  Returns:
145
  ChromaCollection: Returns vector store.
@@ -147,7 +172,7 @@ def retrieve_indexes():
147
 
148
  if [f for f in os.listdir(INDEX_DIR) if not f.startswith(".")] == []:
149
  print("Generating indexes...")
150
- return generate_indexes()
151
  else:
152
  print("Loading existing indexes!")
153
- return load_indexes()
 
1
  # import libraries
2
  import os
3
+ from typing import List
4
  from transformers import AutoTokenizer
5
  from langchain_community.vectorstores import Chroma
6
  from sentence_transformers import SentenceTransformer
7
  from langchain.text_splitter import RecursiveCharacterTextSplitter
8
+ from langchain_community.embeddings import HuggingFaceBgeEmbeddings, HuggingFaceInferenceAPIEmbeddings
9
  from langchain.docstore.document import Document
10
 
11
  # import functions
 
13
 
14
  # constants
15
  INDEX_DIR = "indexes/"
 
16
 
17
 
18
  # instantiate embedding model
19
+ def load_embedding_model(embedding_model):
20
  """
21
  Load the embedding model.
22
+
23
+ Args:
24
+ embedding_model(str): Hugging Face Embedding Model name.
25
 
26
  Returns:
27
  HuggingFaceBgeEmbeddings: Returns the embedding model.
 
34
  print("device:", device)
35
 
36
  hf_bge_embeddings = HuggingFaceBgeEmbeddings(
37
+ model_name=embedding_model,
38
  model_kwargs={"device": device},
39
  encode_kwargs={
40
  "normalize_embeddings": True # set True to compute cosine similarity
 
43
 
44
  # To get the value of the max sequence_length, we will query the underlying `SentenceTransformer` object used in the RecursiveCharacterTextSplitter.
45
  print(
46
+ f"Model's maximum sequence length: {SentenceTransformer(embedding_model).max_seq_length}"
47
  )
48
 
49
  return hf_bge_embeddings
50
 
51
+ # instantiate embedding model
52
+ def load_inference_embedding_model(embedding_model):
53
+ """
54
+ Load the inference embedding model.
55
+
56
+ Args:
57
+ embedding_model(str): Hugging Face Embedding Model name.
58
+
59
+ Returns:
60
+ HuggingFaceInferenceAPIEmbeddings: Returns the inference embedding model.
61
+ """
62
+ hf_inference_bge_embeddings = HuggingFaceInferenceAPIEmbeddings(model_name=embedding_model, api_key=os.environ["HUGGINGFACEHUB_API_TOKEN"])
63
+ return hf_inference_bge_embeddings
64
+
65
 
66
  # split documents
67
  def chunk_documents(
68
  chunk_size: int,
69
  knowledge_base: List[Document],
70
+ tokenizer_name: str,
71
  ) -> List[Document]:
72
  """
73
  Split documents into chunks of maximum size `chunk_size` tokens and return a list of documents.
 
106
 
107
 
108
  # generate indexes
109
+ def generate_indexes(embedding_model):
110
  """
111
  Generates indexes.
112
+
113
+ Args:
114
+ embedding_model(str): Hugging Face Embedding Model name.
115
 
116
  Returns:
117
  ChromaCollection: Returns vector store.
 
123
  # chunk documents to honor the context length
124
  chunked_documents = chunk_documents(
125
  SentenceTransformer(
126
+ embedding_model
127
  ).max_seq_length, # We choose a chunk size adapted to our model
128
  documents,
129
+ tokenizer_name=embedding_model,
130
  )
131
 
132
  # save indexes to disk
133
  vector_store = Chroma.from_documents(
134
  documents=chunked_documents,
135
+ embedding=load_embedding_model(embedding_model),
136
  collection_metadata={"hnsw:space": "cosine"},
137
  persist_directory=INDEX_DIR,
138
  )
 
141
 
142
 
143
  # load indexes from disk
144
+ def load_indexes(embedding_model):
145
  """
146
  Loads indexes into memory.
147
+
148
+ Args:
149
+ embedding_model(str): Hugging Face Embedding Model name.
150
 
151
  Returns:
152
  ChromaCollection: Returns vector store.
153
  """
154
 
155
  vector_store = Chroma(
156
+ persist_directory=INDEX_DIR, embedding_function=load_inference_embedding_model(embedding_model)
157
  )
158
  return vector_store
159
 
160
 
161
  # retrieve vector store
162
+ def retrieve_indexes(embedding_model):
163
  """
164
  Retrieves indexes.
165
+
166
+ Args:
167
+ embedding_model(str): Hugging Face Embedding Model name.
168
 
169
  Returns:
170
  ChromaCollection: Returns vector store.
 
172
 
173
  if [f for f in os.listdir(INDEX_DIR) if not f.startswith(".")] == []:
174
  print("Generating indexes...")
175
+ return generate_indexes(embedding_model)
176
  else:
177
  print("Loading existing indexes!")
178
+ return load_indexes(embedding_model)
src/retrieval/retriever_chain.py CHANGED
@@ -10,11 +10,12 @@ from ..indexing.build_indexes import retrieve_indexes
10
 
11
 
12
  # instantiate base retriever
13
- def get_base_retriever(k=4, search_type="mmr"):
14
  """
15
  Instantiates base retriever.
16
 
17
  Args:
 
18
  k (int, optional): Top k results to retrieve. Defaults to 4.
19
  search_type (str, optional): Search type (mmr or similarity). Defaults to 'mmr'.
20
 
@@ -23,7 +24,7 @@ def get_base_retriever(k=4, search_type="mmr"):
23
  """
24
 
25
  # get the vector store of indexes
26
- vector_store = retrieve_indexes()
27
 
28
  base_retriever = vector_store.as_retriever(
29
  search_type=search_type, search_kwargs={"k": k}
 
10
 
11
 
12
  # instantiate base retriever
13
+ def get_base_retriever(embedding_model, k=4, search_type="mmr"):
14
  """
15
  Instantiates base retriever.
16
 
17
  Args:
18
+ embedding_model(str): Hugging Face Embedding Model name.
19
  k (int, optional): Top k results to retrieve. Defaults to 4.
20
  search_type (str, optional): Search type (mmr or similarity). Defaults to 'mmr'.
21
 
 
24
  """
25
 
26
  # get the vector store of indexes
27
+ vector_store = retrieve_indexes(embedding_model)
28
 
29
  base_retriever = vector_store.as_retriever(
30
  search_type=search_type, search_kwargs={"k": k}
src/test/eval_rag.py CHANGED
@@ -56,6 +56,12 @@ def evaluate_rag(chain_name, rag_chain):
56
  "Response": answer,
57
  "Time": "{:.2f}".format(round(end_time - start_time, 2)),
58
  }
 
 
 
 
 
 
59
 
60
  df = pd.concat([df, pd.DataFrame.from_records([row])])
61
 
 
56
  "Response": answer,
57
  "Time": "{:.2f}".format(round(end_time - start_time, 2)),
58
  }
59
+
60
+ print("*" * 100)
61
+ print("Question:", question)
62
+ print("Answer:", answer)
63
+ print("Response Time:", "{:.2f}".format(round(end_time - start_time, 2)))
64
+ print("*" * 100)
65
 
66
  df = pd.concat([df, pd.DataFrame.from_records([row])])
67
 
src/test/eval_results_20240325111437.csv ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Chain,Question,Response,Time
2
+ qa_chain,What is FastMap?," FastMap is a productivity tool that integrates with IBM OpenPages with Watson's export feature and automates the process of importing and batch processing object data into OpenPages with Watson. It uses a data load template, typically in Microsoft Excel format, to capture data for import. When importing data into OpenPages with Watson, FastMap validates the data and, if no errors are found, populates the repository with the new or updated records. It supports the import of various types of objects, but not File and Signature objects or the Comment field's system field. Some general rules apply when entering object data into a FastMap data load template, such as associating child objects using specific columns and not importing certain fields like read-only fields or those not in the Admin view for the object. Additionally, FastMap import does not evaluate field dependency rules, allowing users to stage data requiring them to enter required data during subsequent updates. Overall, FastMap helps streamline the process of importing large amounts of data into OpenPages with Watson, reducing manual input and increasing efficiency.",4.01
3
+ qa_chain,What is a Role Template?," A Role Template in IBM OpenPages with Watson solutions is a predefined set of permissions and access controls that determine the level of access and functionality granted to a user in the system. It includes application permissions, feature access, and Object Access Controls (OACs) for specific object types. Role Templates help simplify the process of managing user access and ensure consistent security policies across the organization. By assigning a Role Template to a user, you can quickly and easily grant them the required permissions and access levels for their job function.",1.85
4
+ qa_chain,What is the purpose of Object Reset?," The purpose of Object Reset in IBM OpenPages with Watson is to allow users to efficiently update multiple objects at once based on predefined rules. This feature helps to simplify repetitive data entry tasks and reduce errors associated with manually updating large numbers of objects. It also provides flexibility in terms of what objects are affected by the reset, as users can choose specific business entities and define rulesets to control the behavior of the reset. Overall, Object Reset helps to streamline data management processes and improve efficiency in IBM OpenPages with Watson.",2.56
5
+ qa_chain,What is the purpose of Reporting Periods?," Reporting periods in IBM OpenPages with Watson serve as ""snapshots"" of the current state of the repository during specific points in time, typically at the end of a quarter or year. These periods allow organizations to archive and report on historical data while maintaining the ability to view and analyze current data. Reporting periods facilitate compliance and regulatory requirements, provide insights into trends and patterns, and enable comparisons between different periods. Additionally, they can be used to automate object resets, which modify object properties based on predefined rulesets. Overall, reporting periods help organizations manage and analyze their data more efficiently and effectively.",2.05
6
+ qa_chain,List the system variables used in Expressions.,"1. $APPLICATION_URL$: A URL for OpenPages.
7
+ 2. $COGNOS_URL$: A URL for IBM Cognos Analytics.
8
+ 3. $ApplicationText/application text key$): Application text content.
9
+ 4. $TASK_VIEW_URL$): A URL to an object task view.
10
+ 5. $System Fields:Task View URL$): Deprecated. Use [$TASK_VIEW_URL$].
11
+ 6. $Setting/OpenPages/...$): A registry setting value.
12
+ 7. $END_USER$): The user name of the signed on user.
13
+ 8. $TODAY$): Today's date.
14
+ 9. $DaysFromNow/field group:field name$): A day count from today to a given date.
15
+ 10. ${asset.id}$: Inserts the identifier of the underlying asset.
16
+ 11. ${asset.name}$: Inserts the asset name of the underlying asset.
17
+ 12. ${asset.description}$: Inserts the asset description of the underlying asset.",2.46
18
+ qa_chain,Provide the steps to configure Watson Assistant in OpenPages?," Unfortunately, I don't have access to your specific environment or installation details. However, here are the general steps to configure Watson Assistant in OpenPages:
19
+
20
+ 1. Ensure that you have a Watson Assistant service instance created and configured with the necessary intents and entities.
21
+
22
+ 2. In OpenPages, go to the Administration Console > Integrations > Watson Assistant.
23
+
24
+ 3. Click on the ""Add"" button to create a new Watson Assistant integration.
25
+
26
+ 4. Enter a name and description for the integration and select the appropriate Watson Assistant service instance from the list.
27
+
28
+ 5. Configure the authentication settings by providing the API key and URL of your Watson Assistant service.
29
+
30
+ 6. Select the appropriate language and version of Watson Assistant.
31
+
32
+ 7. Map the Watson Assistant intents and entities to the corresponding OpenPages business objects and fields.
33
+
34
+ 8. Save the configuration and test the integration by running a sample request through the Watson Assistant REST API.
35
+
36
+ 9. Verify that the response is correctly mapped to the appropriate OpenPages business object and field values.
37
+
38
+ 10. Deploy the integration to make it available to users in the OpenPages application.
39
+
40
+ Note: These steps may vary depending on your specific implementation and version of OpenPages and Watson Assistant. It's recommended to refer to the official documentation for detailed instructions and best practices.",1.94
41
+ qa_chain,What is the difference between PRE and POST position in Triggers?,"
42
+ In Triggers, the position ""PRE"" refers to events that occur prior to the actual execution of an operation by the system. These triggers allow for additional processing of business logic before the operation is carried out. For example, during the creation of a GRC object, a PRE trigger has access to all the necessary information about the object to be created, but the system has not yet taken action to create the object and persist its values. PRE triggers are mandatory for deletions, associations, and disassociations.
43
+
44
+ On the other hand, the position ""POST"" refers to events that occur after an operation has been performed by the system but before the transaction is committed. These triggers provide further processing of additional business logic after the operation has been completed. POST triggers are mandatory for creating and updating operations.
45
+
46
+ In summary, PRE triggers execute before the operation takes place, while POST triggers execute after the operation has been completed.",2.56
47
+ qa_chain,What are the features of Operational Risk Management in OpenPages?,"1. Loss Events: This feature allows organizations to track, assess, and manage both internal and external events that could lead to operational losses. Multiple impact events and recoveries associated with operational losses can also be managed through this feature.
48
+
49
+ 2. Risk and Control Self Assessments (RCSA): This feature helps in identifying, measuring, and mitigating risks, as well as testing and documenting internal controls.
50
+
51
+ 3. Key Risk Indicators (KRIs) and Key Performance Indicators (KPIs): These features enable tracking of performance metrics that may indicate the presence or state of a risk condition or trend.
52
+
53
+ 4. Scenario Analysis: This feature is used to identify and measure specific types of risks, particularly low-frequency, high-severity events.
54
+
55
+ 5. External Loss Events: This feature allows for the import of loss data from various sources such as IBM FIRST Risk Case Studies, ORX, and ORIC loss databases for scenario analysis, benchmarking, and report generation.
56
+
57
+ 6. Issue Management and Remediation (IMR): This feature includes issue creation and assignment, action creation and assignment, remediation performance, issue closure, and reporting.
58
+
59
+ 7. Reporting, Monitoring, and Analytics: This feature provides reporting, monitoring, and analytics capabilities for operational risk management.
60
+
61
+ Note: The above features are part of IBM OpenPages Operational Risk Management. Other related features like Regulatory Compliance Management, Third Party Risk Management, and IT Governance with RiskLens are also available in IBM OpenPages.",2.56
62
+ qa_chain,What are the different permissions that can be delegated to a user group administrator?," There are six security management permissions that can be delegated to a user group administrator: Manage, Lock, Unlock, Reset Password, Assign Role, and Browse. These permissions allow the administrator to perform various user-provisioning functions such as creating, modifying, and associating users and groups, locking and unlocking user accounts, resetting passwords, assigning roles to users and groups, and browsing users and groups within their respective groups. The specific permissions required for each user-provisioning function are listed in Table 38 provided in the text material. It's important to note that these permissions should be granted carefully and only to trusted individuals as they have significant impact on the overall security and functionality of the system.",8.57
63
+ qa_chain,What are the different access controls available for non-participants for a standard stage within a workflow?," Table 142 in the text provides the different access controls available for non-participants for a standard stage within a workflow:
64
+
65
+ Access control for the stage
66
+ Can view the object when it’s at this stage
67
+ Can edit the object when it’s at this stage
68
+ Can see the Actions button in views
69
+ Strict
70
+ No
71
+ No
72
+ No
73
+ Read
74
+ Yes
75
+ No
76
+ No
77
+ Open
78
+ Depends on standard access controls
79
+ Depends on standard access controls
80
+ No
81
+ No Override
82
+ Depends on standard access controls
83
+ Depends on standard access controls
84
+ Yes
85
+
86
+ Note: For workflow participants (assignees, oversight users, and subscribers), the standard access controls apply, and they only know their part of the process. Non-participants may require additional access controls based on their roles and responsibilities within the organization. The ""Override"" option allows you to define whether to override these standard access controls for the workflow stage for non-participants.",41.15
src/ui/{chat_interface.py → gradio_chat_interface.py} RENAMED
@@ -6,7 +6,7 @@ from src.test.eval_rag import load_eval_questions
6
 
7
 
8
  # create chatbot interface
9
- def create_chatinterface(generate_response):
10
  """
11
  Instantiates the gradio chat interface.
12
 
 
6
 
7
 
8
  # create chatbot interface
9
+ def create_gradio_chatinterface(generate_response):
10
  """
11
  Instantiates the gradio chat interface.
12
 
src/ui/streamlit_chat_interface.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # import libraries
2
+ import streamlit as st
3
+
4
+ # import functions
5
+ from src.test.eval_rag import load_eval_questions
6
+
7
+ # initialize streamlit
8
+ def create_streamlit_chatinterface(generate_response):
9
+ """
10
+ Instantiates the streamlit chat interface.
11
+
12
+ Args:
13
+ generate_response (callable): Function that generates the response.
14
+ """
15
+
16
+ st.title("OpenPages IntelliBot")
17
+ st.caption("Ask me about OpenPages (v9.0), its features, solutions / modules it offers and the trigger framework. Authored by Nikhil Komakula ([email protected]).")
18
+ st.divider()
19
+
20
+ # Initialize chat history
21
+ if "messages" not in st.session_state:
22
+ st.session_state.messages = []
23
+
24
+ # Display chat messages from history on app rerun
25
+ for message in st.session_state.messages:
26
+ with st.chat_message(message["role"]):
27
+ st.markdown(message["content"])
28
+
29
+ # Accept user input
30
+ if prompt := st.chat_input("Type your question here!"):
31
+ # Add user message to chat history
32
+ st.session_state.messages.append({"role": "user", "content": prompt})
33
+ # Display user message in chat message container
34
+ with st.chat_message("user"):
35
+ st.markdown(prompt)
36
+
37
+ # Display assistant response in chat message container
38
+ with st.chat_message("assistant"):
39
+ with st.spinner(""):
40
+ response = st.write_stream(generate_response(prompt, st.session_state.messages))
41
+
42
+ # Add assistant response to chat history
43
+ st.session_state.messages.append({"role": "assistant", "content": response})
44
+
45
+ # option = st.selectbox("Examples:", tuple(load_eval_questions()))
46
+ # if option:
47
+ # st.chat_message(option)
streamlit_ui.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # import libraries
2
+ from dotenv import find_dotenv, load_dotenv
3
+
4
+ # import functions
5
+ from src.ui.streamlit_chat_interface import create_streamlit_chatinterface
6
+ from src.generation.generate_response import get_qa_chain, set_global_qa_chain, generate_response_streamlit
7
+
8
+ def main():
9
+
10
+ # find .env automatically by walking up directories until it's found, then
11
+ # load up the .env entries as environment variables
12
+ load_dotenv(find_dotenv())
13
+
14
+ # get the qa chain
15
+ qa_chain = get_qa_chain()
16
+
17
+ # set the global qa chain
18
+ set_global_qa_chain(qa_chain)
19
+
20
+ # initiate the chat interface
21
+ create_streamlit_chatinterface(generate_response_streamlit)
22
+
23
+ if __name__ == "__main__":
24
+ main()