Rajarshi-Roy-research commited on
Commit
e9cd6c4
·
verified ·
1 Parent(s): ae45fa9

Upload 13 files

Browse files
Files changed (13) hide show
  1. .gitattributes +2 -35
  2. Dockerfile +25 -0
  3. LICENSE +21 -0
  4. README.md +290 -10
  5. app copy.py +42 -0
  6. app.py +48 -0
  7. chainlit.md +9 -0
  8. demo_app.py +311 -0
  9. demo_chaillit_app.py +58 -0
  10. demo_main.py +11 -0
  11. requirements.txt +31 -0
  12. setup.py +30 -0
  13. template.py +35 -0
.gitattributes CHANGED
@@ -1,35 +1,2 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ faiss_index/index.faiss filter=lfs diff=lfs merge=lfs -text
2
+ resources/Guide-to-Litiaton-in-India.pdf filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Dockerfile ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY . /app
6
+
7
+
8
+ RUN apt-get update && apt-get install -y --no-install-recommends \
9
+ ca-certificates \
10
+ netbase \
11
+ && rm -rf /var/lib/apt/lists/*
12
+
13
+ RUN pip3 install -r requirements.txt
14
+
15
+ ARG GOOGLE_API_KEY1
16
+ ENV GOOGLE_API_KEY=$GOOGLE_API_KEY1
17
+
18
+ ARG LANGCHAIN_API_KEY1
19
+ ENV LANGCHAIN_API_KEY=$LANGCHAIN_API_KEY1
20
+
21
+ EXPOSE 8501
22
+
23
+ ENTRYPOINT ["streamlit", "run"]
24
+
25
+ CMD ["app.py"]
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Rajarshi Roy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,10 +1,290 @@
1
- ---
2
- title: Legal Agent
3
- emoji: 🔥
4
- colorFrom: yellow
5
- colorTo: blue
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Legal Agent Codebase
2
+
3
+ - [LinkedIn - Rajarshi Roy](https://www.linkedin.com/in/rajarshi-roy-learner/)
4
+
5
+ - [Github - Rajarshi Roy](https://github.com/Rajarshi12321/)
6
+
7
+ - [Medium - Rajarshi Roy](https://medium.com/@rajarshiroy.machinelearning)
8
+
9
+ - [Kaggle - Rajarshi Roy](https://www.kaggle.com/rajarshiroy0123/)
10
+ - [Mail - Rajarshi Roy](mailto:royrajarshi0123@gmail.com)
11
+ - [Personal-Website - Rajarshi Roy](https://rajarshi12321.github.io/rajarshi_portfolio/)
12
+
13
+
14
+ ## Table of Contents
15
+
16
+ - [Legal Agent Codebase](#legal-agent-codebase)
17
+ - [Table of Contents](#table-of-contents)
18
+ - [(DEMO README)](#demo-readme)
19
+ - [About The Project](#about-the-project)
20
+ - [Functionality](#functionality)
21
+ - [Code Structure](#code-structure)
22
+ - [Dependencies](#dependencies)
23
+ - [Working with the code](#working-with-the-code)
24
+ - [Deploying the project from your side (In AWS)](#deploying-the-project-from-your-side-in-aws)
25
+ - [Contributing](#contributing)
26
+ - [Contact](#contact)
27
+ - [License](#license)
28
+
29
+ # (DEMO README)
30
+
31
+ ## About The Project
32
+
33
+ This projects aim to implements a sophisticated document retrieval and question answering system using LangChain, leveraging Google's Gemini-1.5-flash language model and a FAISS vector database. The system is designed to handle legal queries, providing comprehensive and accurate answers by combining information retrieval from a local knowledge base with web search capabilities when necessary.
34
+
35
+ ## Functionality
36
+
37
+ The system follows a multi-stage workflow:
38
+
39
+ 1. **Query Input:** The user provides a query (e.g., a legal question).
40
+
41
+ 2. **FAISS Retrieval:** The query is embedded using Google Generative AI embeddings, and the FAISS index (a local vector database) is queried to retrieve the most relevant documents.
42
+
43
+ 3. **Grounded Response Generation:** A `DocSummarizerPipeline` summarizes the retrieved documents, focusing on the user's query. This summary attempts to directly answer the question using only the retrieved documents.
44
+
45
+ 4. **Response Evaluation:** An `IntermediateStateResponseEvaluator` assesses the quality and completeness of the generated response. This evaluation uses the Gemini model to determine if the response sufficiently answers the query.
46
+
47
+ 5. **Web Search (Conditional):** If the generated response is deemed insufficient, a `WebSearchAgent` performs a web search using DuckDuckGo to gather additional information. The results are then incorporated into the final response.
48
+
49
+ 6. **Response Output:** The final answer, either from the document summary or the combined document/web search result, is returned to the user.
50
+
51
+
52
+ ## Code Structure
53
+
54
+ The code is organized into several classes and functions:
55
+
56
+ * **`FaissRetriever`:** Loads and interacts with the FAISS index, retrieving relevant documents based on a query.
57
+
58
+ * **`DocSummarizerPipeline`:** Summarizes retrieved documents using the Gemini model, generating a concise answer focused on the user's query. It uses a carefully crafted prompt to ensure the response is structured and informative.
59
+
60
+ * **`WebSearchAgent`:** Performs web searches using DuckDuckGo and integrates the results into the response.
61
+
62
+ * **`IntermediateStateResponseEvaluator`:** Evaluates the quality of the generated response using the Gemini model, determining if additional information is needed.
63
+
64
+ * **`State` (TypedDict):** Defines the data structure for passing information between stages of the workflow.
65
+
66
+ * **Workflow Functions (`faiss_content_retriever`, `grounded_response`, `response_judge`, `web_response`):** These functions represent individual nodes in the LangGraph workflow.
67
+
68
+ * **`StateGraph`:** Defines the workflow using LangGraph, managing the flow of data between the different stages. Conditional logic is implemented to determine whether a web search is necessary.
69
+
70
+ * **`run_user_query`:** The main function that takes a user query and processes it through the LangGraph workflow.
71
+ <div align="center">
72
+ Agent Workflow:
73
+
74
+ ![alt text](assets/agent_workflow.png)
75
+ </div>
76
+
77
+ ## Dependencies
78
+
79
+ The code relies on several libraries:
80
+
81
+ * `langgraph`
82
+ * `langchain-core`
83
+ * `langchain-google-genai`
84
+ * `IPython`
85
+ * `dotenv`
86
+ * `google.generativeai`
87
+ * `langchain.chains.question_answering`
88
+ * `langchain.prompts`
89
+ * `langchain.vectorstores`
90
+ * `langchain_community.tools`
91
+ * `langchain.agents`
92
+
93
+
94
+
95
+ ## Working with the code
96
+
97
+
98
+ I have commented most of the neccesary information in the respective files.
99
+
100
+ To run this project locally, please follow these steps:-
101
+
102
+ 1. Clone the repository:
103
+
104
+ ```shell
105
+ git clone https://github.com/Rajarshi12321/legal-agent.git
106
+ ```
107
+
108
+
109
+ 2. **Create a Virtual Environment** (Optional but recommended)
110
+ It's a good practice to create a virtual environment to manage project dependencies. Run the following command:
111
+ ```shell
112
+ conda create -p <Environment_Name> python==<python version> -y
113
+ ```
114
+ Example:
115
+ ```shell
116
+ conda create -p venv python=3.9 -y
117
+ ```
118
+ Note:
119
+ - It is important to use python=3.9 or above for proper use of Langchain or else you would get unexpecterd errors
120
+
121
+
122
+ 3. **Activate the Virtual Environment** (Optional)
123
+ Activate the virtual environment based on your operating system:
124
+ ```shell
125
+ conda activate <Environment_Name>/
126
+ ```
127
+ Example:
128
+ ```shell
129
+ conda activate venv/
130
+ ```
131
+
132
+ 4. **Install Dependencies**
133
+
134
+ - Run the following command to install project dependencies:
135
+ ```
136
+ pip install -r requirements.txt
137
+ ```
138
+
139
+ Ensure you have Python installed on your system (Python 3.9 or higher is recommended).<br />
140
+ Once the dependencies are installed, you're ready to use the project.
141
+
142
+ 5. Create a .env file in the root directory and add your Gemini and Langchain credentials as follows:
143
+ ```shell
144
+ GOOGLE_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
145
+ ```
146
+
147
+
148
+ 6. Run the Flask app: Execute the following code in your terminal.
149
+ ```shell
150
+ chainlit run app.py
151
+ ```
152
+
153
+
154
+ 6. Access the app: Open your web browser and navigate to http://localhost:8000/ to use the House Price Prediction and Property Recommendation app.
155
+
156
+ ## Deploying the project from your side (In AWS)
157
+
158
+ I have already made a github actions file in `.github\workflows\main.yaml`
159
+ To use it you need to the following prerequisites:
160
+
161
+ 1. Make a IAM Role from your aws account
162
+ - 1. Login to AWS console.
163
+
164
+ - 2. Create IAM user for deployment
165
+
166
+ #with specific access
167
+
168
+ 1. EC2 access : It is virtual machine
169
+
170
+ 2. ECR: Elastic Container registry to save your docker image in aws
171
+
172
+
173
+ #Policy: (You need to select these policies when building the user)
174
+
175
+ 1. AmazonEC2ContainerRegistryFullAccess
176
+
177
+ 2. AmazonEC2FullAccess
178
+
179
+ 2. Building the full infrastructure using Terraform </br></br>
180
+ 1st you need to configure your aws account using the created IAM role by the command `aws configure` so that terraform can know which account to use </br></br>
181
+ NOTE: If you don't want to use terraform for building infrastructure you can also build this manually from aws console:</br>
182
+ For reference watch this video from `3:47:20` time frame : [Youtube link](https://www.youtube.com/watch?v=86BKEv0X2xU)</br></br>
183
+ Get to the terraform directory: `infrastructure\terraform` and execute the following commands:
184
+ </br></br>
185
+ Initializing Terraform
186
+ ```shell
187
+ terraform init
188
+ ```
189
+ Forming a plan according the described infrastructure
190
+ ```shell
191
+ terraform plan
192
+ ```
193
+ Applying the planned infrastructure to build necessary resources
194
+ ```shell
195
+ terraform apply -auto-approve
196
+ ```
197
+
198
+ </br></br>
199
+ 3. After this you Need to configure your EC2 instance to install Docker:
200
+ </br>Run The Following commands:
201
+ ```shell
202
+ sudo apt-get update -y
203
+
204
+ sudo apt-get upgrade
205
+
206
+
207
+ curl -fsSL https://get.docker.com -o get-docker.sh
208
+
209
+ sudo sh get-docker.sh
210
+
211
+ sudo usermod -aG docker ubuntu
212
+
213
+ newgrp docker
214
+ ```
215
+ 4. After this you need to configure the self-runner for github actions to actually deploy it to EC2 instance:
216
+ </br></br>
217
+ Check out the [Youtube vidoe](https://www.youtube.com/watch?v=86BKEv0X2xU) for reference from 3:54:38 time frame
218
+ </br></br>
219
+ The commands for settinng up self-hosted runner will be like: </br></br>
220
+ (NOTE: Do use the commands from your actions runner, the below commands are just for your reference)
221
+
222
+ ```shell
223
+ mkdir actions-runner && cd actions-runner
224
+
225
+ curl -o actions-runner-linux-x64-2.316.1.tar.gz -L https://github.com/actions/runner/releases/download/v2.316.1/actions-runner-linux-x64-2.316.1.tar.gz
226
+
227
+
228
+ echo "d62de2400eeeacd195db91e2ff011bfb646cd5d85545e81d8f78c436183e09a8 actions-runner-linux-x64-2.316.1.tar.gz" | shasum -a 256 -c
229
+
230
+
231
+ tar xzf ./actions-runner-linux-x64-2.316.1.tar.gz
232
+
233
+ ./config.sh --url https://github.com/Rajarshi12321/main_app_deploy --token AWSY7XQOYHXWPQKGRAEQWRDGJD2GS
234
+
235
+ ./run.sh
236
+
237
+ ```
238
+
239
+ name the runner as : `self-hosted`
240
+
241
+ 1. Follow the Following [youtube video](https://www.youtube.com/watch?v=86BKEv0X2xU) from `3:57:14` time frame to know which secret Key and Value to add to your github actions secrets. Additionlly you have to add the `GOOGLE_API_KEY` in the secrets to with same key name as used in `.env` and their api keys as the values.
242
+
243
+ 2. Finally after doing all this you can run you github actions smoothly which is run by the instructions of `.github\workflows\main.yaml`
244
+ </br></br>
245
+ **Description: About the deployment by main.yaml**
246
+
247
+ 1. Build docker image of the source code
248
+
249
+ 2. Push your docker image to ECR
250
+
251
+ 3. Launch Your EC2
252
+
253
+ 4. Pull Your image from ECR in EC2
254
+
255
+ 5. Lauch your docker image in EC2
256
+
257
+
258
+ Now making any changes in any file except the readme.md file and assets folder (which contains images for readme) will trigger the github action CI/CD pipeline for development.
259
+
260
+ NOTE: Do keep an eye on the state of the `self-hosted` runner, if its `idle` or `offline` then fix the condition my connecting to ec2 instance and run the `run.sh` file by:
261
+
262
+ ```shell
263
+ cd actions-runner
264
+
265
+ ./run.sh
266
+ ```
267
+
268
+
269
+
270
+ ## Contributing
271
+ I welcome contributions to improve the functionality and performance of the app. If you'd like to contribute, please follow these guidelines:
272
+
273
+ 1. Fork the repository and create a new branch for your feature or bug fix.
274
+
275
+ 2. Make your changes and ensure that the code is well-documented.
276
+
277
+ 3. Test your changes thoroughly to maintain app reliability.
278
+
279
+ 4. Create a pull request, detailing the purpose and changes made in your contribution.
280
+
281
+ ## Contact
282
+
283
+ Rajarshi Roy - [[email protected]](mailto:[email protected])
284
+
285
+
286
+
287
+ ## License
288
+ This project is licensed under the MIT License. Feel free to modify and distribute it as per the terms of the license.
289
+
290
+ I hope this README provides you with the necessary information to get started with the road to Generative AI with Google Gemini and Langchain.
app copy.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from legal_agent.components.full_workflow import run_user_query
3
+
4
+ # Initialize session state for conversation history
5
+ if "conversation" not in st.session_state:
6
+ st.session_state.conversation = []
7
+
8
+ st.title("Legal Agent Chat App")
9
+
10
+
11
+ # Display conversation history
12
+ def display_conversation():
13
+ for chat in st.session_state.conversation:
14
+ if chat["role"] == "user":
15
+ st.markdown(f"**User:** {chat['content']}")
16
+ else:
17
+ st.markdown(f"**Legal Agent:** {chat['content']}")
18
+
19
+
20
+ display_conversation()
21
+
22
+ # Input area for new query
23
+ user_input = st.text_input("Enter your legal query:")
24
+
25
+ if st.button("Send"):
26
+ if user_input.strip():
27
+ # Append user message to conversation
28
+ st.session_state.conversation.append({"role": "user", "content": user_input})
29
+
30
+ # Run the legal agent query workflow
31
+ result = run_user_query(user_input)
32
+ agent_response = result.get("response", "No response received.")
33
+
34
+ # Append agent response to conversation
35
+ st.session_state.conversation.append(
36
+ {"role": "assistant", "content": agent_response}
37
+ )
38
+
39
+ # Clear the text input by rerunning the app
40
+ st.experimental_rerun()
41
+ else:
42
+ st.error("Please enter a valid query.")
app.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import chainlit as cl
2
+ from legal_agent.components.full_workflow import run_user_query
3
+
4
+ # from QA_app.components.data_querying import user_query
5
+ import chainlit as cl
6
+
7
+ # user_query
8
+
9
+
10
+ async def user_query_func(user_question):
11
+ response = run_user_query(user_question)
12
+ # Replace this with your actual logic for processing the user query
13
+ # It could involve interacting with an LLM, searching web documents, etc.
14
+ # For illustration purposes, let's just return a simple response
15
+ return response
16
+
17
+
18
+ @cl.on_chat_start
19
+ def start():
20
+ # user_query
21
+
22
+ print("Chat started!")
23
+
24
+
25
+ @cl.on_message
26
+ async def main(message: cl.Message):
27
+ # user_query
28
+ user_question = message.content
29
+ # response = user_query(user_question)
30
+ # response = await user_query_func("What happended to the birds")
31
+ response = await user_query_func(user_question)
32
+ print(user_question, "see")
33
+ # user_query = cl.make_async(user_query)
34
+
35
+ # await user_query("What happended to the birds")
36
+ # print(user_question, "see22222222")
37
+
38
+ # Use LangchainCallbackHandler to capture the final answer
39
+ # callback_handler = LangchainCallbackHandler(stream_final_answer=True)
40
+ # response = await cl.make_async(user_query)(user_question)
41
+ # response = await cl.make_async(user_query)(user_question)
42
+
43
+ # await message.reply(response)
44
+ await cl.Message(content=response["response"]).send()
45
+
46
+
47
+ # # Run the Chainlit app
48
+ # cl.run()
chainlit.md ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ # Welcome to Game Recommendation APP! 🚀🤖
2
+
3
+ **Objective: Let the Games Begin!**
4
+
5
+ Welcome to the Game Recommendation Party! 🎉 Our mission is simple: to make gaming discovery as thrilling as playing the games themselves! With our vibrant and fun-loving Game Recommendation App, we're here to shake up the gaming world and inject a dose of excitement into every recommendation.
6
+
7
+ Picture this: a magical realm where every gamer finds their perfect match, where the journey to discovering new games is filled with laughter, surprises, and endless joy. Our objective? To sprinkle a dash of fun into the gaming universe and ignite the spark of adventure in every player's heart.
8
+
9
+ So, gear up, grab your controller, and get ready to embark on an epic quest through the world of gaming like never before. Let's turn every recommendation into a memorable adventure, where the only limit is your imagination! 🚀✨
demo_app.py ADDED
@@ -0,0 +1,311 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Importing Important libraries
2
+
3
+ import streamlit as st
4
+ from pathlib import Path
5
+
6
+ import os
7
+
8
+ import google.generativeai as genai
9
+
10
+ from langchain_community.chat_message_histories.streamlit import (
11
+ StreamlitChatMessageHistory,
12
+ )
13
+
14
+
15
+ from datetime import datetime
16
+
17
+ from langchain.memory.buffer import ConversationBufferMemory
18
+ from langchain.schema.runnable import RunnableMap
19
+
20
+ from langchain_core.prompts import ChatPromptTemplate
21
+ from langchain_core.prompts import MessagesPlaceholder
22
+
23
+ from langchain_google_genai import ChatGoogleGenerativeAI
24
+ from langchain.callbacks.tracers.langchain import wait_for_all_tracers
25
+
26
+ import streamlit as st
27
+ from streamlit_feedback import streamlit_feedback
28
+
29
+
30
+ from langsmith import Client
31
+
32
+ from langchain_core.tracers.context import collect_runs
33
+
34
+
35
+ from dotenv import load_dotenv
36
+
37
+ from langchain_community.vectorstores import FAISS
38
+ from langchain_google_genai import ChatGoogleGenerativeAI
39
+ from langchain_google_genai import GoogleGenerativeAIEmbeddings
40
+
41
+ ## Loading APIs
42
+
43
+ load_dotenv()
44
+
45
+ embeddings = GoogleGenerativeAIEmbeddings(model="models/embedding-001")
46
+
47
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
48
+
49
+ gemini_api_key = os.getenv("GOOGLE_API_KEY")
50
+
51
+
52
+ os.environ["LANGCHAIN_PROJECT"] = "GAME RECOMMENDATION" # Set your custom project name
53
+
54
+ os.environ["LANGCHAIN_TRACING_V2"] = "true"
55
+ os.environ["LANGCHAIN_API_KEY"] = os.getenv("LANGCHAIN_API_KEY")
56
+ langchain_api_key = os.getenv("LANGCHAIN_API_KEY")
57
+
58
+ # Update with your API URL if using a hosted instance of Langsmith.
59
+ langchain_endpoint = os.environ["LANGCHAIN_ENDPOINT"] = (
60
+ "https://api.smith.langchain.com"
61
+ )
62
+
63
+ # Used LLM model
64
+
65
+
66
+ # Adding an event loop
67
+ import asyncio
68
+ import aiohttp
69
+
70
+
71
+ loop = asyncio.new_event_loop()
72
+ asyncio.set_event_loop(loop)
73
+
74
+
75
+ model = ChatGoogleGenerativeAI(
76
+ model="gemini-1.5-pro-latest",
77
+ api_key=gemini_api_key,
78
+ temperature=0.3,
79
+ convert_system_message_to_human=True,
80
+ )
81
+
82
+
83
+ # Configuring memory
84
+ memory = ConversationBufferMemory(
85
+ chat_memory=StreamlitChatMessageHistory(key="langchain_messages"),
86
+ return_messages=True,
87
+ memory_key="chat_history",
88
+ )
89
+
90
+
91
+ # Load Vector DB
92
+ new_db = FAISS.load_local(
93
+ "faiss_index", embeddings, allow_dangerous_deserialization=True
94
+ )
95
+
96
+ # Main retriever
97
+ retriever = new_db.as_retriever()
98
+
99
+ # Configuring Langsmith Client
100
+ client = Client(api_url=langchain_endpoint, api_key=langchain_api_key)
101
+
102
+
103
+ # Introducing try catch block in case you don't have a dataset with good feed back examples
104
+ try:
105
+ # Getting best feedback examples to save in the memory context
106
+ examples = client.list_examples(
107
+ dataset_name="Feedbacks"
108
+ ) # Choose your dataset_name here
109
+
110
+ my_examples = []
111
+
112
+ for i in examples:
113
+ print(i.inputs)
114
+ print(i.outputs["output"]["content"])
115
+ print("\n\n--------\n\n")
116
+ my_examples.append(
117
+ (i.inputs["input"], {"output": i.outputs["output"]["content"]})
118
+ )
119
+ except:
120
+ my_examples = []
121
+
122
+
123
+ my_examples = my_examples[:2]
124
+
125
+ # Configuring our runnablemap
126
+ ingress = RunnableMap(
127
+ {
128
+ "input": lambda x: x["input"],
129
+ "chat_history": lambda x: memory.load_memory_variables(x)["chat_history"],
130
+ "time": lambda _: str(datetime.now()),
131
+ "context": lambda x: retriever.get_relevant_documents(x["input"]),
132
+ "examples": lambda x: my_examples,
133
+ }
134
+ )
135
+
136
+ # Making the prompt template
137
+ prompt = ChatPromptTemplate.from_messages(
138
+ [
139
+ (
140
+ "system",
141
+ "Only discuss games. You are a GAME RECOMMENDATION system assistant. Be humble, greet users nicely, and answer their queries."
142
+ """
143
+ "Instructions":
144
+ "Regardless of the input, always adhere to the context provided."
145
+ "You can only make conversations based on the provided context. If a response cannot be formed strictly using the context, politely say you dont have knowledge about that topic."
146
+ "Use the Context section to provide accurate answers, as if you knew this information innately."
147
+ "If unsure, state that you don't know."
148
+
149
+ "Context": {context}
150
+
151
+ "Examples of Human feedback":
152
+ {examples},
153
+ """,
154
+ # "system",
155
+ # "Only and Only talk about games, nothing else, your knowledge is constraint games"
156
+ # "You are a GAME RECOMMENDATION system assistant. You are humble AI. Greet the user nicely and answer their queries"
157
+ # """
158
+ # Use the information from the Context section to provide accurate answers but act as if you knew this information innately.
159
+ # If unsure, simply state that you don't know.
160
+ # Context: {context}
161
+ # Here are some impressive examples of Human feedback, Do your best to try to generate these type of answer format for the specific format of questions
162
+ # The examples are listed below :
163
+ # {examples}
164
+ # Assistant:""",
165
+ ),
166
+ MessagesPlaceholder(variable_name="chat_history"),
167
+ ("human", "{input}"),
168
+ ]
169
+ )
170
+
171
+ llm = model
172
+
173
+ # Our final chain
174
+ chain = ingress | prompt | llm
175
+
176
+
177
+ # Initialize State
178
+ if "trace_link" not in st.session_state:
179
+ st.session_state.trace_link = None
180
+ if "run_id" not in st.session_state:
181
+ st.session_state.run_id = None
182
+
183
+
184
+ # Sidebar to give option for Clearing message history
185
+ if st.sidebar.button("Clear message history"):
186
+ print("Clearing message history")
187
+ memory.clear()
188
+ st.session_state.trace_link = None
189
+ st.session_state.run_id = None
190
+
191
+
192
+ # When we get response from the Chatbot, then only we can see this Trace link
193
+ if st.session_state.trace_link:
194
+ st.sidebar.markdown(
195
+ f'<a href="{st.session_state.trace_link}" target="_blank"><button>Latest Trace: 🛠️</button></a>',
196
+ unsafe_allow_html=True,
197
+ )
198
+
199
+ st.header("Hey Gamers, I am a Game Recommender 🤖", divider="rainbow")
200
+
201
+ for msg in st.session_state.langchain_messages:
202
+ avatar = "🤖" if msg.type == "ai" else None
203
+ with st.chat_message(msg.type, avatar=avatar):
204
+ st.markdown(msg.content)
205
+
206
+
207
+ # The main chatbot configuration to get desired out and create runs for Langsmith
208
+ if prompt := st.chat_input(placeholder="Ask me a question!"):
209
+ st.chat_message("user").write(prompt)
210
+ with st.chat_message("assistant", avatar="🤖"):
211
+ message_placeholder = st.empty()
212
+ full_response = ""
213
+ print("in chat here")
214
+
215
+ # Getting the input
216
+ input_dict = {"input": prompt}
217
+
218
+ # Displaying the response from chatbot and collecting runs
219
+ with collect_runs() as cb:
220
+ for chunk in chain.stream(input_dict, config={"tags": ["Streamlit Chat"]}):
221
+ full_response += chunk.content
222
+ message_placeholder.markdown(full_response + "▌")
223
+ memory.save_context(input_dict, {"output": full_response})
224
+
225
+ # storing the run id in streamlit session
226
+ ## Since the runnable sequence would come after retriever I have chosen `1` instead on `0`
227
+ run_id = cb.traced_runs[1].id
228
+
229
+ st.session_state.run_id = run_id
230
+
231
+ wait_for_all_tracers()
232
+ # Requires langsmith >= 0.0.19
233
+
234
+ # Getting the Trace link
235
+ url = client.share_run(run_id)
236
+
237
+ st.session_state.trace_link = url
238
+
239
+ message_placeholder.markdown(full_response)
240
+
241
+ # Checking if we have messages in chat
242
+ has_chat_messages = len(st.session_state.get("langchain_messages", [])) > 0
243
+
244
+
245
+ # Only show the feedback toggle if there are chat messages
246
+ if has_chat_messages:
247
+ feedback_option = (
248
+ "faces" if st.toggle(label="`Thumbs` ⇄ `Faces`", value=False) else "thumbs"
249
+ )
250
+
251
+ else:
252
+ pass
253
+
254
+ if st.session_state.get("run_id"):
255
+ feedback = streamlit_feedback(
256
+ feedback_type=feedback_option, # Use the selected feedback option
257
+ optional_text_label="[Optional] Please provide an explanation", # Adding a label for optional text input
258
+ key=f"feedback_{st.session_state.run_id}",
259
+ align="flex-start",
260
+ )
261
+
262
+ # Define score mappings for both "thumbs" and "faces" feedback systems
263
+ score_mappings = {
264
+ "thumbs": {"👍": 1, "👎": 0},
265
+ "faces": {"😀": 1, "🙂": 0.75, "😐": 0.5, "🙁": 0.25, "😞": 0},
266
+ }
267
+
268
+ # Get the score mapping based on the selected feedback option
269
+ scores = score_mappings[feedback_option]
270
+
271
+ if feedback:
272
+ # Get the score from the selected feedback option's score mapping
273
+ score = scores.get(feedback["score"])
274
+
275
+ if score is not None:
276
+ # Formulate feedback type string incorporating the feedback option and score value
277
+ feedback_type_str = f"{feedback_option} {feedback['score']}"
278
+
279
+ # Record the feedback with the formulated feedback type string and optional comment
280
+ feedback_record = client.create_feedback(
281
+ st.session_state.run_id,
282
+ feedback_type_str, # Updated feedback type
283
+ score=score,
284
+ comment=feedback.get("text"),
285
+ )
286
+ st.session_state.feedback = {
287
+ "feedback_id": str(feedback_record.id),
288
+ "score": score,
289
+ }
290
+
291
+ # # Incase you want to add this run with feedback to simultaneously add to a dataset
292
+ # run_id = st.session_state.get("run_id")
293
+ # selected_runs = client.list_runs(id=[run_id])
294
+
295
+ # for run in tqdm(selected_runs):
296
+
297
+ # # print(run, "lets see")
298
+ # print(run.inputs)
299
+ # print(run.outputs)
300
+ # print(run.extra)
301
+ # print(run.feedback_stats)
302
+
303
+ # client.create_examples(
304
+ # inputs=[run.inputs],
305
+ # outputs=[run.outputs],
306
+ # feedback_stats=[run.feedback_stats],
307
+ # dataset_id=<your-dataset-id>,
308
+ # )
309
+
310
+ else:
311
+ st.warning("Invalid feedback score.")
demo_chaillit_app.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # from QA_app.components.data_querying import user_query
2
+ from chainlit import on_chat_start, on_message, LangchainCallbackHandler
3
+ import chainlit as cl
4
+ from main_app_deploy.components.data_querying import my_query
5
+
6
+
7
+ import os
8
+
9
+ os.environ["LITERAL_API_KEY"] = os.getenv("LITERAL_API_KEY")
10
+
11
+ os.environ["LANGCHAIN_PROJECT"] = "GAME RECOMMENDATION"
12
+
13
+ os.environ["LANGCHAIN_TRACING_V2"] = "true"
14
+ os.environ["LANGCHAIN_API_KEY"] = os.getenv("LANGCHAIN_API_KEY")
15
+
16
+
17
+ # user_query
18
+
19
+
20
+ async def user_query_func(user_question):
21
+ response = my_query(user_question)
22
+ # Replace this with your actual logic for processing the user query
23
+ # It could involve interacting with an LLM, searching web documents, etc.
24
+ # For illustration purposes, let's just return a simple response
25
+ return response
26
+
27
+
28
+ @cl.on_chat_start
29
+ def start():
30
+ # user_query
31
+
32
+ print("Chat started!")
33
+
34
+
35
+ @cl.on_message
36
+ async def main(message: cl.Message):
37
+ # user_query
38
+ user_question = message.content
39
+ # response = user_query(user_question)
40
+ # response = await user_query_func("What happended to the birds")
41
+ response = await user_query_func(user_question)
42
+ print(user_question, "see")
43
+ # user_query = cl.make_async(user_query)
44
+
45
+ # await user_query("What happended to the birds")
46
+ # print(user_question, "see22222222")
47
+
48
+ # Use LangchainCallbackHandler to capture the final answer
49
+ # callback_handler = LangchainCallbackHandler(stream_final_answer=True)
50
+ # response = await cl.make_async(user_query)(user_question)
51
+ # response = await cl.make_async(user_query)(user_question)
52
+
53
+ # await message.reply(response)
54
+ await cl.Message(content=response).send()
55
+
56
+
57
+ # # Run the Chainlit app
58
+ # cl.run()
demo_main.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from main_app_deploy.components.data_querying import my_query
2
+ import os
3
+
4
+ os.environ["LANGCHAIN_PROJECT"] = "GAME RECOMMENDATION"
5
+
6
+ os.environ["LANGCHAIN_TRACING_V2"] = "true"
7
+ os.environ["LANGCHAIN_API_KEY"] = os.getenv("LANGCHAIN_API_KEY")
8
+
9
+ ans = my_query("can you reccomend me some fantasy games? about 2 games")
10
+
11
+ print(ans)
requirements.txt ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ beautifulsoup4
2
+ chainlit
3
+ chromadb
4
+ duckduckgo_search==6.3.4
5
+ fastapi
6
+ faiss-cpu
7
+ # flashrank[listwise]
8
+ google-generativeai
9
+ # google-play-scraper
10
+ IPython
11
+ ipykernel
12
+ langchain==0.3.7
13
+ langchain-community==0.3.7
14
+ langchain_core
15
+ langchain-docling
16
+ langchain_google_genai==2.0.4
17
+ # langchain_huggingface
18
+ langgraph==0.2.48
19
+ langserve
20
+ langsmith
21
+ pandas>=1.3.6
22
+ pypdf
23
+ PyPDF2
24
+ python-dotenv
25
+ regex
26
+ streamlit
27
+ # streamlit-feedback
28
+ unstructured[pdf]==0.7.12
29
+ # sse_starlette
30
+ # uvicorn
31
+ -e .
setup.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import setuptools
2
+
3
+
4
+ with open("README.md", "r", encoding="utf-8") as f:
5
+ long_description = f.read()
6
+
7
+
8
+ __version__ = "0.0.0.1"
9
+
10
+ REPO_NAME = "legal-agent"
11
+ AUTHOR_USER_NAME = "Rajarshi12321"
12
+ SRC_REPO = "legal_agent"
13
+ AUTHOR_EMAIL = "[email protected]"
14
+
15
+
16
+ setuptools.setup(
17
+ name=SRC_REPO,
18
+ version=__version__,
19
+ author=AUTHOR_USER_NAME,
20
+ author_email=AUTHOR_EMAIL,
21
+ description="A small python package for game recommendation using RAG model",
22
+ long_description=long_description,
23
+ long_description_content="text/markdown",
24
+ url=f"https://github.com/{AUTHOR_USER_NAME}/{REPO_NAME}",
25
+ project_urls={
26
+ "Bug Tracker": f"https://github.com/{AUTHOR_USER_NAME}/{REPO_NAME}/issues",
27
+ },
28
+ package_dir={"": "src"},
29
+ packages=setuptools.find_packages(where="src"),
30
+ )
template.py ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ import logging
4
+
5
+ # logging string
6
+ logging.basicConfig(level=logging.INFO, format="[%(asctime)s]: %(message)s:")
7
+
8
+ project_name = "legal_agent"
9
+
10
+ list_of_files = [
11
+ ".github/workflows/.gitkeep",
12
+ f"src/{project_name}/__init__.py",
13
+ f"src/{project_name}/components/__init__.py",
14
+ f"src/{project_name}/utils/__init__.py",
15
+ "requirements.txt",
16
+ "setup.py",
17
+ "research/trials.ipynb",
18
+ ]
19
+
20
+
21
+ for filepath in list_of_files:
22
+ filepath = Path(filepath)
23
+ filedir, filename = os.path.split(filepath)
24
+
25
+ if filedir != "":
26
+ os.makedirs(filedir, exist_ok=True)
27
+ logging.info(f"Creating directory; {filedir} for the file: {filename}")
28
+
29
+ if (not os.path.exists(filepath)) or (os.path.getsize(filepath) == 0):
30
+ with open(filepath, "w") as f:
31
+ pass
32
+ logging.info(f"Creating empty file: {filepath}")
33
+
34
+ else:
35
+ logging.info(f"{filename} is already exists")