mohit-raghavendra commited on
Commit
617c511
·
1 Parent(s): 90c9f68

Upload 5 files

Browse files
Files changed (3) hide show
  1. app.py +21 -27
  2. llm_client.py +31 -27
  3. pinecone_index.py +23 -28
app.py CHANGED
@@ -4,19 +4,20 @@ import gradio as gr
4
 
5
  from typing import List
6
 
7
- from llm_client import PalmClient
8
  from pinecone_index import PinceconeIndex
9
 
10
- SYSTEM_MESSAGE = 'Give a precise answer to the question based on only the \
11
- context and evidence and do not be verbose.'
12
- TOP_K = 2
13
 
14
 
15
  def format_prompt(question: str, evidence: List[str]):
16
- evidence_string = ''
17
  for i, ev in enumerate(evidence):
18
- evidence_string.join(f'\n Evidence {i+1}: {ev}')
19
 
 
20
  content = f"{SYSTEM_MESSAGE} \
21
  \n ### Question:{question} \
22
  \n ### Evidence: {evidence_string} \
@@ -25,39 +26,36 @@ def format_prompt(question: str, evidence: List[str]):
25
  return content
26
 
27
 
28
- if __name__ == '__main__':
29
-
30
- config_path = 'config.yml'
31
- with open('config.yml', 'r') as file:
32
  config = yaml.safe_load(file)
33
 
34
  print(config)
35
 
36
- data_path = config['paths']['data_path']
37
- project = config['paths']['project']
38
 
39
- index_name = config['pinecone']['index-name']
40
- embedding_model = config['sentence-transformers']['model-name']
41
- embedding_dimension = config['sentence-transformers'][
42
- 'embedding-dimension']
43
 
44
  index = PinceconeIndex(index_name, embedding_model)
45
  index.connect_index(embedding_dimension, False)
46
 
47
- palm_client = PalmClient()
48
 
49
  def get_answer(question: str):
50
  evidence = index.query(question, top_k=TOP_K)
51
  prompt_with_evidence = format_prompt(question, evidence)
52
  print(prompt_with_evidence)
53
- response = palm_client.generate_text(prompt_with_evidence)
54
  final_output = [response] + evidence
55
 
56
  return final_output
57
 
58
- context_outputs = [gr.Textbox(label=f'Evidence {i+1}')
59
- for i in range(TOP_K)]
60
- result_output = [gr.Textbox(label='Answer')]
61
 
62
  gradio_outputs = result_output + context_outputs
63
  gradio_inputs = gr.Textbox(placeholder="Enter your question...")
@@ -69,12 +67,8 @@ if __name__ == '__main__':
69
  outputs=gradio_outputs,
70
  title="GT Student Code of Conduct Bot",
71
  description="Get LLM-powered answers to questions about the \
72
- Georgia Tech Student Code of Conduct. The evidence contains exerpts\
73
- from the Code of Conduct. LLMs are prone to make mistakes \
74
- and this is an experimental setup. Please do not consider the \
75
- answers as legal advice. We recommend you to consult the \
76
- actual Student Code of Conduct online for authoritative \
77
- information."
78
  )
79
 
80
  demo.launch()
 
4
 
5
  from typing import List
6
 
7
+ from llm_client import GeminiClient
8
  from pinecone_index import PinceconeIndex
9
 
10
+ SYSTEM_MESSAGE = "Give a precise answer to the question based on only the \
11
+ context and evidence and do not be verbose."
12
+ TOP_K = 1
13
 
14
 
15
  def format_prompt(question: str, evidence: List[str]):
16
+ evidence_string = ""
17
  for i, ev in enumerate(evidence):
18
+ evidence_string = evidence_string.join(f"\n Evidence {i+1}: {ev}")
19
 
20
+ print(f"evidence string - {evidence_string}")
21
  content = f"{SYSTEM_MESSAGE} \
22
  \n ### Question:{question} \
23
  \n ### Evidence: {evidence_string} \
 
26
  return content
27
 
28
 
29
+ if __name__ == "__main__":
30
+ config_path = "config.yml"
31
+ with open("config.yml", "r") as file:
 
32
  config = yaml.safe_load(file)
33
 
34
  print(config)
35
 
36
+ data_path = config["paths"]["data_path"]
37
+ project = config["paths"]["project"]
38
 
39
+ index_name = config["pinecone"]["index-name"]
40
+ embedding_model = config["sentence-transformers"]["model-name"]
41
+ embedding_dimension = config["sentence-transformers"]["embedding-dimension"]
 
42
 
43
  index = PinceconeIndex(index_name, embedding_model)
44
  index.connect_index(embedding_dimension, False)
45
 
46
+ gemini_client = GeminiClient()
47
 
48
  def get_answer(question: str):
49
  evidence = index.query(question, top_k=TOP_K)
50
  prompt_with_evidence = format_prompt(question, evidence)
51
  print(prompt_with_evidence)
52
+ response = gemini_client.generate_text(prompt_with_evidence)
53
  final_output = [response] + evidence
54
 
55
  return final_output
56
 
57
+ context_outputs = [gr.Textbox(label=f"Evidence {i+1}") for i in range(TOP_K)]
58
+ result_output = [gr.Textbox(label="Answer")]
 
59
 
60
  gradio_outputs = result_output + context_outputs
61
  gradio_inputs = gr.Textbox(placeholder="Enter your question...")
 
67
  outputs=gradio_outputs,
68
  title="GT Student Code of Conduct Bot",
69
  description="Get LLM-powered answers to questions about the \
70
+ Georgia Tech Student Code of Conduct. The evidences are exerpts\
71
+ from the Code of Conduct.",
 
 
 
 
72
  )
73
 
74
  demo.launch()
llm_client.py CHANGED
@@ -1,41 +1,45 @@
1
  import os
2
 
3
- import google.generativeai as palm
4
 
5
 
6
- class PalmClient:
7
  def __init__(self):
8
  self.connect_client()
9
 
10
  def connect_client(self):
11
- if (not os.getenv('GOOGLE_PALM_KEY')):
12
- raise Exception('Please set your Google MakerSuite API key')
13
-
14
- api_key = os.getenv('GOOGLE_PALM_KEY')
15
- palm.configure(api_key=api_key)
16
-
17
- safety_overrides = [
18
- {"category": "HARM_CATEGORY_DEROGATORY", "threshold": 4},
19
- {"category": "HARM_CATEGORY_TOXICITY", "threshold": 4},
20
- {"category": "HARM_CATEGORY_VIOLENCE", "threshold": 4},
21
- {"category": "HARM_CATEGORY_SEXUAL", "threshold": 4},
22
- {"category": "HARM_CATEGORY_MEDICAL", "threshold": 4},
23
- {"category": "HARM_CATEGORY_DANGEROUS", "threshold": 4}
24
- ]
 
 
 
 
25
 
26
  defaults = {
27
- 'model': 'models/text-bison-001',
28
- 'temperature': 0.7,
29
- 'candidate_count': 1,
30
- 'top_k': 40,
31
- 'top_p': 0.95,
32
- 'max_output_tokens': 1024,
33
- 'stop_sequences': [],
34
- 'safety_settings': safety_overrides,
35
  }
36
 
37
- self.defaults = defaults
 
 
 
 
38
 
39
  def generate_text(self, prompt: str) -> str:
40
- response = palm.generate_text(**self.defaults, prompt=prompt)
41
- return response.candidates[0]['output']
 
1
  import os
2
 
3
+ import google.generativeai as genai
4
 
5
 
6
+ class GeminiClient:
7
  def __init__(self):
8
  self.connect_client()
9
 
10
  def connect_client(self):
11
+ if not os.getenv("GOOGLE_PALM_KEY"):
12
+ raise Exception("Please set your Google AI Studio key")
13
+
14
+ api_key = os.getenv("GOOGLE_PALM_KEY")
15
+ genai.configure(api_key=api_key)
16
+
17
+ safety_settings = [
18
+ {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_ONLY_HIGH"},
19
+ {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_ONLY_HIGH"},
20
+ {
21
+ "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
22
+ "threshold": "BLOCK_ONLY_HIGH",
23
+ },
24
+ {
25
+ "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
26
+ "threshold": "BLOCK_ONLY_HIGH",
27
+ },
28
+ ]
29
 
30
  defaults = {
31
+ "temperature": 0.7,
32
+ "top_k": 40,
33
+ "top_p": 0.95,
34
+ "max_output_tokens": 1024,
 
 
 
 
35
  }
36
 
37
+ self.model = genai.GenerativeModel(
38
+ model_name="gemini-pro",
39
+ generation_config=defaults,
40
+ safety_settings=safety_settings,
41
+ )
42
 
43
  def generate_text(self, prompt: str) -> str:
44
+ response = self.model.generate_content(prompt)
45
+ return response.text
pinecone_index.py CHANGED
@@ -19,18 +19,17 @@ class PinceconeIndex:
19
  self.index_name = index_name
20
  self._embeddingModel = HuggingFaceEmbeddings(model_name=model_name)
21
 
22
- def connect_index(self, embedding_dimension: int,
23
- delete_existing: bool = False):
24
  index_name = self.index_name
25
 
26
  # load pinecone env variables within Google Colab
27
- if (not os.getenv('PINECONE_KEY')) or (not os.getenv('PINECONE_ENV')):
28
- dotenv_path = Path('/content/gt-policy-bot/config.env')
29
  load_dotenv(dotenv_path=dotenv_path)
30
 
31
  pinecone.init(
32
- api_key=os.getenv('PINECONE_KEY'),
33
- environment=os.getenv('PINECONE_ENV'),
34
  )
35
 
36
  if index_name in pinecone.list_indexes() and delete_existing:
@@ -47,9 +46,8 @@ class PinceconeIndex:
47
  def upsert_docs(self, df: pd.DataFrame, text_col: str):
48
  loader = DataFrameLoader(df, page_content_column=text_col)
49
  docs = loader.load()
50
- Pinecone.from_documents(docs, self._embeddingModel,
51
- index_name=self.index_name)
52
-
53
  def get_embedding_model(self):
54
  return self._embeddingModel
55
 
@@ -57,47 +55,44 @@ class PinceconeIndex:
57
  return self.index_name
58
 
59
  def query(self, query: str, top_k: int = 5) -> List[str]:
60
- docsearch = Pinecone.from_existing_index(self.index_name,
61
- self._embeddingModel)
62
  res = docsearch.similarity_search(query, k=top_k)
63
 
64
  return [doc.page_content for doc in res]
65
 
66
 
67
- if __name__ == '__main__':
68
- config_path = 'config.yml'
69
- with open('config.yml', 'r') as file:
70
  config = yaml.safe_load(file)
71
 
72
  print(config)
73
 
74
- data_path = config['paths']['data_path']
75
- project = config['paths']['project']
76
- format = '.csv'
77
 
78
- index_name = config['pinecone']['index-name']
79
- embedding_model = config['sentence-transformers'][
80
- 'model-name']
81
- embedding_dimension = config['sentence-transformers'][
82
- 'embedding-dimension']
83
  delete_existing = True
84
 
85
- if config['paths']['chunking'] == 'manual':
86
  print("Using manual chunking")
87
- file_path_embedding = config['paths']['manual_chunk_file']
88
- df = pd.read_csv(file_path_embedding, header=None, names=['chunks'])
89
  else:
90
  print("Using automatic chunking")
91
- file_path_embedding = config['paths']['auto_chunk_file']
92
  df = pd.read_csv(file_path_embedding, index_col=0)
93
 
94
  print(df)
95
  start_time = time.time()
96
  index = PinceconeIndex(index_name, embedding_model)
97
  index.connect_index(embedding_dimension, delete_existing)
98
- index.upsert_docs(df, 'chunks')
99
  end_time = time.time()
100
- print(f'Indexing took {end_time - start_time} seconds')
101
 
102
  index = PinceconeIndex(index_name, embedding_model)
103
  index.connect_index(embedding_dimension, delete_existing=False)
 
19
  self.index_name = index_name
20
  self._embeddingModel = HuggingFaceEmbeddings(model_name=model_name)
21
 
22
+ def connect_index(self, embedding_dimension: int, delete_existing: bool = False):
 
23
  index_name = self.index_name
24
 
25
  # load pinecone env variables within Google Colab
26
+ if (not os.getenv("PINECONE_KEY")) or (not os.getenv("PINECONE_ENV")):
27
+ dotenv_path = Path("/content/gt-policy-bot/config.env")
28
  load_dotenv(dotenv_path=dotenv_path)
29
 
30
  pinecone.init(
31
+ api_key=os.getenv("PINECONE_KEY"),
32
+ environment=os.getenv("PINECONE_ENV"),
33
  )
34
 
35
  if index_name in pinecone.list_indexes() and delete_existing:
 
46
  def upsert_docs(self, df: pd.DataFrame, text_col: str):
47
  loader = DataFrameLoader(df, page_content_column=text_col)
48
  docs = loader.load()
49
+ Pinecone.from_documents(docs, self._embeddingModel, index_name=self.index_name)
50
+
 
51
  def get_embedding_model(self):
52
  return self._embeddingModel
53
 
 
55
  return self.index_name
56
 
57
  def query(self, query: str, top_k: int = 5) -> List[str]:
58
+ docsearch = Pinecone.from_existing_index(self.index_name, self._embeddingModel)
 
59
  res = docsearch.similarity_search(query, k=top_k)
60
 
61
  return [doc.page_content for doc in res]
62
 
63
 
64
+ if __name__ == "__main__":
65
+ config_path = "config.yml"
66
+ with open("config.yml", "r") as file:
67
  config = yaml.safe_load(file)
68
 
69
  print(config)
70
 
71
+ data_path = config["paths"]["data_path"]
72
+ project = config["paths"]["project"]
73
+ format = ".csv"
74
 
75
+ index_name = config["pinecone"]["index-name"]
76
+ embedding_model = config["sentence-transformers"]["model-name"]
77
+ embedding_dimension = config["sentence-transformers"]["embedding-dimension"]
 
 
78
  delete_existing = True
79
 
80
+ if config["paths"]["chunking"] == "manual":
81
  print("Using manual chunking")
82
+ file_path_embedding = config["paths"]["manual_chunk_file"]
83
+ df = pd.read_csv(file_path_embedding, header=None, names=["chunks"])
84
  else:
85
  print("Using automatic chunking")
86
+ file_path_embedding = config["paths"]["auto_chunk_file"]
87
  df = pd.read_csv(file_path_embedding, index_col=0)
88
 
89
  print(df)
90
  start_time = time.time()
91
  index = PinceconeIndex(index_name, embedding_model)
92
  index.connect_index(embedding_dimension, delete_existing)
93
+ index.upsert_docs(df, "chunks")
94
  end_time = time.time()
95
+ print(f"Indexing took {end_time - start_time} seconds")
96
 
97
  index = PinceconeIndex(index_name, embedding_model)
98
  index.connect_index(embedding_dimension, delete_existing=False)