├── DemoAgent
├── HumanInTheLoop.py
├── README
├── app.py
├── hil1_streamlit.py
└── reflectionmathapp.py
├── DemoRAG
├── REAMDE
├── agentjson.ipynb
├── app.py
├── llm_batch_run.ipynb
├── newagen2.ipynb
├── newagen3.ipynb
└── newagen_onlyfunction.ipynb
├── LangGraph
├── README
├── langGraph_breakpoints_turorial_04.ipynb
├── langGraph_memory_turorial_03.ipynb
├── langGraph_router_turorial_02.ipynb
├── langGraph_state_turorial_01.ipynb
└── text_to_sql.ipynb
├── LangGraphStudio
├── .env
├── README
├── agent.py
├── langgraph.json
└── requirements.txt
├── README.md
├── agentapp.py
├── chatbot_deployment_intent.py
├── chatbot_deployment_intent_withmemory.py
├── clientsurvey.py
├── document_summarize.py
└── requirements.txt
/DemoAgent/HumanInTheLoop.py:
--------------------------------------------------------------------------------
1 | import os
2 | from langchain_openai import ChatOpenAI
3 | from langchain.agents import AgentExecutor, create_react_agent
4 | from langchain_core.prompts import PromptTemplate
5 | import streamlit as st
6 | from langchain.agents import AgentExecutor
7 | from langchain.agents import create_react_agent
8 | from langchain_experimental.tools import PythonREPLTool
9 | import re
10 | from langchain_core.runnables import chain
11 |
12 |
13 | OPENAI_API_KEY="sk-proj-xxxxxxxxxx" # https://platform.openai.com/account/api-keys
14 | os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
15 | llm = ChatOpenAI(model='gpt-4')
16 |
17 | template="""
18 |
19 | {instructions}
20 |
21 | TOOLS:
22 |
23 | ------
24 |
25 | You have access to the following tools:
26 |
27 | {tools}
28 |
29 | To use a tool, please use the following format:
30 |
31 | ```
32 |
33 | Thought: Do I need to use a tool? Yes
34 |
35 | Action: the action to take, should be one of [{tool_names}]
36 |
37 | Action Input: the input to the action
38 |
39 | Observation: the result of the action
40 |
41 | ```
42 |
43 | When you have a response to say to the Human
44 |
45 | ```
46 |
47 | Final Answer: [your response here]
48 |
49 | ```
50 |
51 | Begin!
52 |
53 | messages: {messages}
54 |
55 | {agent_scratchpad}
56 |
57 | """
58 |
59 | base_prompt = PromptTemplate.from_template(template)
60 |
61 | tools = [PythonREPLTool()]
62 |
63 | instructions = """You are an agent designed to print and execute python code to answer questions.
64 | You have access to a python REPL, which you can use to execute python code.
65 | If you get an error, debug your code and try again.
66 | Only use the output of your code to answer the question.
67 | Unfortunately, the Assistant is terrible at maths. When provided with math questions,
68 | no matter how simple, you should always refer to its trusty tools and absolutely does NOT try to answer math questions by yerself.
69 | You have to make sure, tools should be always used for all kind of math problem
70 | """
71 | #base_prompt = hub.pull("langchain-ai/react-agent-template")
72 | prompt_agent = base_prompt.partial(instructions=instructions)
73 | agent = create_react_agent(llm, tools, prompt_agent)
74 |
75 | generate = AgentExecutor(agent=agent, tools=tools, verbose=True, return_intermediate_steps=True,
76 | handle_parsing_errors=True, force_tool=True)
77 |
78 |
79 | def extract_python_code(text):
80 | # Define a regular expression pattern to find Python code blocks
81 | pattern = re.compile(r'```python(.*?)```', re.DOTALL)
82 | pattern1 = r"```(.*?)```"
83 | match = pattern.search(text)
84 | match1 = re.search(pattern1, text, re.DOTALL)
85 |
86 | if match:
87 | # Return the extracted code block without the backticks
88 | return match.group(1).strip()
89 | elif match1:
90 | return match1.group(1).strip()
91 | else:
92 | # Return a message if no code block is found
93 | return text
94 | #return "No Python code block found."
95 |
96 | def extract_final_output(text):
97 | # Search for the starting point of the phrase "final output is:"
98 | start_index = text.find("final output is:")
99 |
100 | if start_index == -1:
101 | # Phrase not found, return a failure message
102 | return "Calculation fails."
103 |
104 | # Extract and return the text following "final output is:"
105 | # Adding the length of "final output is:" to start_index and trimming any leading spaces or colons
106 | output_text = text[start_index + len("final output is:"):].strip()
107 | return output_text
108 |
109 |
110 |
111 | def code_gen_run(question):
112 | # Simulate invoking an external process (replace with your actual implementation)
113 | output = generate.invoke({"messages": question})
114 | final_output = {
115 | 'input': question,
116 | 'output': output['output'],
117 | 'code': extract_python_code(output['intermediate_steps'][-1][0].tool_input)
118 | }
119 | return final_output
120 |
121 | def streamlit_app():
122 | st.title("Python Code Execution Agent")
123 | question = st.text_input("Enter your question:", key="question")
124 |
125 | if "approved" not in st.session_state:
126 | st.session_state.approved = None
127 |
128 | if st.button("Generate Code"):
129 | st.session_state.original_msg = code_gen_run(question)
130 |
131 | if "original_msg" in st.session_state:
132 | original_result, original_code = st.session_state.original_msg['output'], st.session_state.original_msg['code']
133 | st.subheader("Original Output:")
134 | st.write(original_result)
135 | st.subheader("Original Python Code:")
136 | st.code(original_code, language="python")
137 |
138 | st.session_state.approved = st.radio("Do you accept the solution provided?", ('Yes', 'No'))
139 |
140 | if st.session_state.approved == 'No':
141 | regenerated_msg = code_gen_run(question)
142 | regenerated_result, regenerated_code = regenerated_msg['output'], regenerated_msg['code']
143 |
144 | st.subheader("Regenerated Output:")
145 | st.write(regenerated_result)
146 | st.subheader("Regenerated Python Code:")
147 | st.code(regenerated_code, language="python")
148 |
149 | if __name__ == "__main__":
150 | streamlit_app()
--------------------------------------------------------------------------------
/DemoAgent/README:
--------------------------------------------------------------------------------
1 | ##
2 |
--------------------------------------------------------------------------------
/DemoAgent/app.py:
--------------------------------------------------------------------------------
1 | import os
2 | import operator
3 | from typing import Annotated, Any, Dict, List, Optional, Sequence, TypedDict
4 | import functools
5 | import streamlit as st
6 | from streamlit_chat import message
7 |
8 | # Langchain imports
9 | from langchain_community.tools.tavily_search import TavilySearchResults
10 | from langchain_core.tools import tool, Tool
11 | from langchain_experimental.tools import PythonREPLTool
12 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
13 | from langchain_community.utilities import OpenWeatherMapAPIWrapper
14 | from langchain.agents import AgentExecutor, create_openai_tools_agent,load_tools
15 | from langchain_core.messages import BaseMessage, HumanMessage
16 | from langchain_openai import ChatOpenAI
17 | from langchain.chains import LLMMathChain
18 | from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
19 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
20 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
21 | from langgraph.graph import StateGraph, END
22 |
23 | os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
24 | os.environ['TAVILY_API_KEY'] = TAVILY_API_KEY
25 | os.environ['LANGCHAIN_API_KEY'] = LANGCHAIN_API_KEY
26 | os.environ['OPENWEATHERMAP_API_KEY'] = OPENWEATHERMAP_API_KEY
27 | os.environ['E2B_API_KEY'] = E2B_API_KEY
28 | os.environ['SERPAPI_API_KEY'] = SERPAPI_API_KEY
29 |
30 | st.title('Multi-Agent Framework Controlled by Supervisor')
31 |
32 | image_path = 'multiagent.png' # Adjust the path to your image file
33 | st.image(image_path, caption='Multi-Agent Framework', width=800)
34 |
35 | # Optional, add tracing in LangSmith
36 | # os.environ["LANGCHAIN_TRACING_V2"] = "true"
37 | # os.environ["LANGCHAIN_PROJECT"] = "Reflection"
38 |
39 | from langchain_openai import ChatOpenAI
40 | from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage
41 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
42 | from typing import List
43 |
44 | # For visualization of the graph, Optional
45 | from IPython.display import Image
46 | import pygraphviz
47 | from IPython.display import Image
48 |
49 |
50 | ## Creating LLM
51 |
52 | ## Tools and llm setup
53 | llm = ChatOpenAI(model="gpt-4-1106-preview")
54 |
55 | # Weather tools
56 | weather_tool = load_tools(["openweathermap-api"], llm)
57 |
58 | # Tavily tools - Search tools
59 | tavily_tool = TavilySearchResults(max_results=5)
60 |
61 | ### Math tools
62 | problem_chain = LLMMathChain.from_llm(llm=llm)
63 | math_tool = Tool.from_function(name="Calculator",func=problem_chain.run,description=\
64 | "Useful for when you need to answer questions \
65 | about math. This tool is only for math questions and nothing else. Only input\
66 | math expressions.")
67 |
68 | # Python REPL tool
69 | python_repl_tool = PythonREPLTool()
70 |
71 | ## Youtube tool
72 | from langchain_community.tools import YouTubeSearchTool
73 | youtube_tool = YouTubeSearchTool()
74 |
75 | ## Google Finace
76 | from langchain_community.tools.google_finance import GoogleFinanceQueryRun
77 | from langchain_community.utilities.google_finance import GoogleFinanceAPIWrapper
78 | google_finance_tool = GoogleFinanceQueryRun(api_wrapper=GoogleFinanceAPIWrapper())
79 |
80 |
81 | ## Google Job Search
82 | from langchain_community.tools.google_jobs import GoogleJobsQueryRun
83 | from langchain_community.utilities.google_jobs import GoogleJobsAPIWrapper
84 | jobsearch_tool = GoogleJobsQueryRun(api_wrapper=GoogleJobsAPIWrapper())
85 |
86 |
87 | # Dall.E image
88 | from langchain_community.utilities.dalle_image_generator import DallEAPIWrapper
89 | dalle_tool = DallEAPIWrapper()
90 |
91 | ## Wikipedia
92 | from langchain.tools import WikipediaQueryRun
93 | from langchain_community.utilities import WikipediaAPIWrapper
94 | wiki_tool = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
95 | # response=wikipedia.run("Barak Obama")
96 | # response
97 |
98 | def create_agent(llm: ChatOpenAI, tools: list, system_prompt: str):
99 | # Each worker node will be given a name and some tools.
100 | prompt = ChatPromptTemplate.from_messages(
101 | [
102 | (
103 | "system",
104 | system_prompt,
105 | ),
106 | MessagesPlaceholder(variable_name="messages"),
107 | MessagesPlaceholder(variable_name="agent_scratchpad"),
108 | ]
109 | )
110 | agent = create_openai_tools_agent(llm, tools, prompt)
111 | executor = AgentExecutor(agent=agent, tools=tools)
112 | return executor
113 |
114 | def agent_node(state, agent, name):
115 | result = agent.invoke(state)
116 | return {"messages": [HumanMessage(content=result["output"], name=name)]}
117 |
118 | members = ["Researcher", "Coder", "Weather", "Calculator", "Youtuber", "GoogleFinace", "JobSearch", "Wikipedia"]
119 | system_prompt = (
120 | "You are a supervisor tasked with managing a conversation between the"
121 | " following workers: {members}. Given the following user request,"
122 | " respond with the worker to act next. Each worker will perform a"
123 | " task and respond with their results and status. When finished,"
124 | " respond with FINISH."
125 | )
126 | # Our team supervisor is an LLM node. It just picks the next agent to process
127 | # and decides when the work is completed
128 | options = ["FINISH"] + members
129 | # Using openai function calling can make output parsing easier for us
130 | function_def = {
131 | "name": "route",
132 | "description": "Select the next role.",
133 | "parameters": {
134 | "title": "routeSchema",
135 | "type": "object",
136 | "properties": {
137 | "next": {
138 | "title": "Next",
139 | "anyOf": [
140 | {"enum": options},
141 | ],
142 | }
143 | },
144 | "required": ["next"],
145 | },
146 | }
147 | prompt = ChatPromptTemplate.from_messages(
148 | [
149 | ("system", system_prompt),
150 | MessagesPlaceholder(variable_name="messages"),
151 | (
152 | "system",
153 | "Given the conversation above, who should act next?"
154 | " Or should we FINISH? Select one of: {options}",
155 | ),
156 | ]
157 | ).partial(options=str(options), members=", ".join(members))
158 |
159 | ### Supervisor Chain
160 | supervisor_chain = (
161 | prompt
162 | | llm.bind_functions(functions=[function_def], function_call="route")
163 | | JsonOutputFunctionsParser()
164 | )
165 |
166 |
167 | # The agent state is the input to each node in the graph
168 | class AgentState(TypedDict):
169 | messages: Annotated[Sequence[BaseMessage], operator.add]
170 | next: str
171 | recursion_count: int = 0
172 |
173 | def check_recursion(state):
174 | if state.recursion_count >= 1: # Limit set to 1
175 | return "END"
176 | state.recursion_count += 1
177 | return "CONTINUE"
178 |
179 |
180 | research_agent = create_agent(llm, [tavily_tool], "You are a Web searcher.")
181 | research_node = functools.partial(agent_node, agent=research_agent, name="Researcher")
182 |
183 | # NOTE: THIS PERFORMS ARBITRARY CODE EXECUTION. PROCEED WITH CAUTION
184 | code_agent = create_agent(
185 | llm,
186 | [python_repl_tool],
187 | "You may generate safe python code to analyze data and generate charts using matplotlib.",
188 | )
189 | code_node = functools.partial(agent_node, agent=code_agent, name="Coder")
190 |
191 | #Weather nodes
192 | weather_agent = create_agent(
193 | llm,
194 | weather_tool,
195 | "You are a weather finder. You can provide weather information for a given location.",
196 | )
197 | weather_node = functools.partial(agent_node, agent=weather_agent, name="Weather")
198 |
199 | # Math node
200 |
201 | math_agent = create_agent(
202 | llm,
203 | [math_tool],
204 | "Useful for when you need to answer questions about math",
205 | )
206 | math_node = functools.partial(agent_node, agent=math_agent, name="Calculator")
207 |
208 | youtube_agent = create_agent(
209 | llm,
210 | [youtube_tool],
211 | "You are helpful for finding videos from Youtube"
212 | )
213 | youtube_node = functools.partial(agent_node, agent=youtube_agent, name="Youtuber")
214 |
215 | google_finance_agent = create_agent(
216 | llm,
217 | [google_finance_tool],
218 | "You are helpful for finding videos from Youtube"
219 | )
220 | google_finance_node = functools.partial(agent_node, agent=google_finance_agent, name="GoogleFinace")
221 |
222 |
223 | jobsearch_agent = create_agent(
224 | llm,
225 | [jobsearch_tool],
226 | "You are helpful for finding job related information"
227 | )
228 | jobsearch_node = functools.partial(agent_node, agent=jobsearch_agent, name="JobSearch")
229 |
230 |
231 | wiki_search_agent = create_agent(
232 | llm,
233 | [wiki_tool],
234 | "You are helpful for finding information from Wikipedia"
235 | )
236 | wiki_search_node = functools.partial(agent_node, agent=jobsearch_agent, name="Wikipedia")
237 |
238 |
239 | workflow = StateGraph(AgentState)
240 | workflow.add_node("Researcher", research_node)
241 | workflow.add_node("Coder", code_node)
242 | workflow.add_node("Weather", weather_node)
243 | workflow.add_node("Calculator", math_node)
244 | workflow.add_node("Youtuber", youtube_node)
245 | workflow.add_node("GoogleFinace", google_finance_node)
246 | workflow.add_node("JobSearch", jobsearch_node)
247 | workflow.add_node("Wikipedia", wiki_search_node)
248 | workflow.add_node("supervisor", supervisor_chain)
249 |
250 | for member in members:
251 | # We want our workers to ALWAYS "report back" to the supervisor when done
252 | workflow.add_edge(member, "supervisor")
253 | # The supervisor populates the "next" field in the graph state
254 | # which routes to a node or finishes
255 | conditional_map = {k: k for k in members}
256 | conditional_map["FINISH"] = END
257 | workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map)
258 | # Finally, add entrypoint
259 | workflow.set_entry_point("supervisor")
260 | graph = workflow.compile()
261 |
262 | # Graph Visualization
263 | # os.environ["PATH"] += os.pathsep + '/opt/homebrew/bin'
264 | # Image(graph.get_graph().draw_png())
265 |
266 |
267 | # user_query = "find the weather in New York City today"
268 | # user_query = "weather in ST. Louis MO and find one job related to data science in St. Louis?"
269 | # #user_query = "what is the google's stock today?"
270 | # user_query = "Why students are protesting in Columbia Univeristy this year?"
271 |
272 | question = st.text_input("User question", key="input")
273 | #question = "find the weather in New York City today"
274 |
275 |
276 | if question:
277 | state=[]
278 | try:
279 | for s in graph.stream(
280 | {
281 | "messages": [
282 | HumanMessage(content=f"{question}")
283 | ]
284 | }
285 | ):
286 | state.append(s)
287 | if "__end__" not in s:
288 | #st.write(s)
289 | print("----")
290 | if len(state) > 5:
291 | break
292 | print(len(state))
293 | except:
294 | print("There is an issue")
295 |
296 | if len(state) > 1:
297 |
298 | key_name=list(state[-1].keys())[0]
299 |
300 | content=state[-1][key_name]['messages'][0].content
301 |
302 | final_agent=state[-1][key_name]['messages'][0].name
303 |
304 | st.write(content)
305 | st.write(f"Final Agent: {final_agent}")
306 | st.write("Check the entire state")
307 | st.write(state)
308 | st.write("Thank you for using this demo")
309 | else:
310 | st.write("service is not available currenlty")
311 |
312 |
313 |
--------------------------------------------------------------------------------
/DemoAgent/hil1_streamlit.py:
--------------------------------------------------------------------------------
1 | import os
2 | import uuid
3 | import json
4 | from typing import Optional
5 | from langchain_openai import ChatOpenAI
6 | from langgraph.prebuilt import ToolExecutor
7 | from langgraph.checkpoint.memory import MemorySaver
8 | from IPython.display import Image, display
9 | from typing import Annotated
10 | from typing_extensions import TypedDict
11 | from langgraph.graph.message import add_messages
12 | from langgraph.prebuilt import ToolExecutor
13 | from langchain_core.messages import ToolMessage
14 | from langgraph.prebuilt import ToolInvocation
15 | from langgraph.graph import END, StateGraph
16 | from langchain_core.messages import AIMessage
17 | from langchain_core.messages import HumanMessage
18 | from langgraph.checkpoint.sqlite import SqliteSaver
19 | from langchain_core.tools import tool
20 | from langchain_core.messages import AIMessage
21 | import streamlit as st
22 | from langchain_community.tools.tavily_search import TavilySearchResults
23 |
24 |
25 | ## Environment Variable
26 | OPENAI_API_KEY="sk-proj-xxx" # https://platform.openai.com/account/api-keys
27 | TAVILY_API_KEY="tvly-xxxx" # https://tavily.com/account/api-keys
28 | os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
29 | os.environ['TAVILY_API_KEY'] = TAVILY_API_KEY
30 |
31 | # define model - try different models
32 | model = ChatOpenAI(model='gpt-4o')
33 |
34 | class State(TypedDict):
35 | messages: Annotated[list, add_messages]
36 |
37 | ## define two tools- internet search and simply add
38 | @tool
39 | def add(x,y):
40 | "adding two numbers"
41 | return x+y
42 |
43 | tools = [TavilySearchResults(max_results=1), add]
44 |
45 | #
46 | tool_executor = ToolExecutor(tools)
47 | model = model.bind_tools(tools)
48 |
49 | # Define the function that determines whether to continue or not
50 | def should_continue(state):
51 | messages = state["messages"]
52 | last_message = messages[-1]
53 | # If there is no function call, then we finish
54 | if not last_message.tool_calls:
55 | return "end"
56 | # Otherwise if there is, we continue
57 | else:
58 | return "continue"
59 |
60 |
61 | # Define the function that calls the model
62 | def call_model(state):
63 | messages = state["messages"]
64 | response = model.invoke(messages)
65 | # We return a list, because this will get added to the existing list
66 | return {"messages": [response]}
67 |
68 |
69 | # Define the function to execute tools
70 | def call_tool(state):
71 | messages = state["messages"]
72 | # Based on the continue condition
73 | # we know the last message involves a function call
74 | last_message = messages[-1]
75 | # We construct an ToolInvocation from the function_call
76 | tool_call = last_message.tool_calls[0]
77 | action = ToolInvocation(
78 | tool=tool_call["name"],
79 | tool_input=tool_call["args"],
80 | )
81 | # We call the tool_executor and get back a response
82 | response = tool_executor.invoke(action)
83 | # We use the response to create a ToolMessage
84 | tool_message = ToolMessage(
85 | content=str(response), name=action.tool, tool_call_id=tool_call["id"]
86 | )
87 | # We return a list, because this will get added to the existing list
88 | return {"messages": [tool_message]}
89 |
90 | # Define a new graph
91 | workflow = StateGraph(State)
92 |
93 | # Define the two nodes we will cycle between
94 | workflow.add_node("agent", call_model)
95 | workflow.add_node("action", call_tool)
96 |
97 | # Set the entrypoint as `agent`
98 | # This means that this node is the first one called
99 | workflow.set_entry_point("agent")
100 |
101 | # We now add a conditional edge
102 | workflow.add_conditional_edges(
103 | # First, we define the start node. We use `agent`.
104 | # This means these are the edges taken after the `agent` node is called.
105 | "agent",
106 | # Next, we pass in the function that will determine which node is called next.
107 | should_continue,
108 | # Finally we pass in a mapping.
109 | # The keys are strings, and the values are other nodes.
110 | # END is a special node marking that the graph should finish.
111 | # What will happen is we will call `should_continue`, and then the output of that
112 | # will be matched against the keys in this mapping.
113 | # Based on which one it matches, that node will then be called.
114 | {
115 | # If `tools`, then we call the tool node.
116 | "continue": "action",
117 | # Otherwise we finish.
118 | "end": END,
119 | },
120 | )
121 |
122 | # We now add a normal edge from `tools` to `agent`.
123 | # This means that after `tools` is called, `agent` node is called next.
124 | workflow.add_edge("action", "agent")
125 |
126 | memory = SqliteSaver.from_conn_string(":memory:")
127 | app = workflow.compile(checkpointer=memory, interrupt_before=["action"])
128 |
129 | # from IPython.display import Image, display
130 |
131 | # display(Image(app.get_graph().draw_mermaid_png()))
132 |
133 |
134 | # Helper function to construct message asking for verification
135 | def generate_verification_message(message: AIMessage) -> None:
136 | """Generate "verification message" from message with tool calls."""
137 | serialized_tool_calls = json.dumps(
138 | message.tool_calls,
139 | indent=2,
140 | )
141 | return AIMessage(
142 | content=(
143 | "I plan to invoke the following tools, do you approve?\n\n"
144 | "Type 'y' if you do, anything else to stop.\n\n"
145 | f"{serialized_tool_calls}"
146 | ),
147 | id=message.id,
148 | )
149 |
150 | # Helper function to stream output from the graph
151 | def stream_app_catch_tool_calls(inputs, thread) -> Optional[AIMessage]:
152 | """Stream app, catching tool calls."""
153 | tool_call_message = None
154 | for event in app.stream(inputs, thread, stream_mode="values"):
155 | message = event["messages"][-1]
156 | if isinstance(message, AIMessage) and message.tool_calls:
157 | tool_call_message = message
158 | else:
159 | #print(message)
160 | message.pretty_print()
161 | if isinstance(message, AIMessage):
162 | st.write(message.content)
163 |
164 | return tool_call_message
165 |
166 | st.title('Human in The Loop - Agent')
167 |
168 | user_input = st.text_input("Enter your question:", key="input1")
169 | #if st.button("Submit Question"):
170 |
171 | if user_input:
172 | thread = {"configurable": {"thread_id": "5"}}
173 | #inputs = [HumanMessage(content="what's the weather in sf now?")]
174 |
175 | inputs = [HumanMessage(content=user_input)]
176 | # for event in app.stream({"messages": inputs}, thread, stream_mode="values"):
177 | # event["messages"][-1].pretty_print()
178 |
179 | tool_call_message = stream_app_catch_tool_calls(
180 | {"messages": inputs},
181 | thread,
182 | )
183 |
184 | # tool name:
185 | tool_name=tool_call_message.tool_calls[-1]['name']
186 | #st.write(tool_call_message.tool_calls[-1])
187 | st.write(f":blue[tool invoked]: {tool_name} ")
188 |
189 | st.write(":green[Please approve the tool picked up by the agent - select either 'yes' or 'no' ]")
190 |
191 | verification_message = generate_verification_message(tool_call_message)
192 | #verification_message.pretty_print()
193 |
194 | #st.write(verification_message)
195 |
196 | #human_input=input("Please provide your response")
197 | human_input = st.text_input('Please provide your response', key='keyname')
198 | if human_input:
199 |
200 | input_message = HumanMessage(human_input)
201 | # if input_message.content == "exit":
202 | # break
203 |
204 | #st.write(input_message)
205 | #input_message.pretty_print()
206 |
207 | # First we update the state with the verification message and the input message.
208 | # note that `generate_verification_message` sets the message ID to be the same
209 | # as the ID from the original tool call message. Updating the state with this
210 | # message will overwrite the previous tool call.
211 | snapshot = app.get_state(thread)
212 | snapshot.values["messages"] += [verification_message, input_message]
213 |
214 | if input_message.content == "yes":
215 | tool_call_message.id = str(uuid.uuid4())
216 | # If verified, we append the tool call message to the state
217 | # and resume execution.
218 | snapshot.values["messages"] += [tool_call_message]
219 | app.update_state(thread, snapshot.values, as_node="agent")
220 | tool_call_message = stream_app_catch_tool_calls(None, thread)
221 | else:
222 | # Otherwise, resume execution from the input message.
223 | app.update_state(thread, snapshot.values, as_node="__start__")
224 | tool_call_message = stream_app_catch_tool_calls(None, thread)
225 |
--------------------------------------------------------------------------------
/DemoAgent/reflectionmathapp.py:
--------------------------------------------------------------------------------
1 | import os
2 | from langchain.chains import LLMMathChain
3 | from langchain_openai import ChatOpenAI
4 | from langchain.agents import Tool
5 | from langchain.chains import LLMMathChain
6 | from langchain import hub
7 | from langchain_community.llms import OpenAI
8 | from langchain.agents import AgentExecutor, create_react_agent
9 | from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
10 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
11 | from langchain_core.prompts import PromptTemplate
12 | from langchain_experimental.tools import PythonREPLTool
13 | from langchain_core.messages import AIMessage, BaseMessage, HumanMessage
14 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
15 | from typing import List, Sequence
16 | from langgraph.graph import END, MessageGraph
17 | import re
18 | import streamlit as st
19 |
20 | st.title("Solving Math Problem with LLM")
21 |
22 | ## Sample Questions
23 | question = "The greatest common divisor of positive integers m and n is 6.The least common multiple of m and n is 126. What is the leastpossible value of m + n?"
24 |
25 | question="The cafeteria had 23 apples. If they used 20 for lunch and bought 6 more,how many apples do they have?"
26 |
27 | question="Today is 27 Feb, 2023. I was born exactly 35 years ago. What is the date I was born in MM/DD/YYYY"
28 |
29 |
30 |
31 | question = st.text_area("Provide your question here")
32 |
33 |
34 |
35 |
36 | OPENAI_API_KEY="xxxx" # https://platform.openai.com/account/api-keys
37 | os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
38 |
39 | llm = ChatOpenAI(model='gpt-4')
40 |
41 |
42 | ######################################################## Generator ###########################
43 | #Define agent for generating code
44 | #Define PythonREPLTool
45 |
46 | tools = [PythonREPLTool()]
47 |
48 |
49 | template="""
50 |
51 | {instructions}
52 |
53 | TOOLS:
54 |
55 | ------
56 |
57 | You have access to the following tools:
58 |
59 | {tools}
60 |
61 | To use a tool, please use the following format:
62 |
63 | ```
64 |
65 | Thought: Do I need to use a tool? Yes
66 |
67 | Action: the action to take, should be one of [{tool_names}]
68 |
69 | Action Input: the input to the action
70 |
71 | Observation: the result of the action
72 |
73 | ```
74 |
75 | When you have a response to say to the Human, or if you do not need to use a tool, you MUST use the format:
76 |
77 | ```
78 |
79 | Thought: Do I need to use a tool? No
80 |
81 | Final Answer: [your response here]
82 |
83 | ```
84 |
85 | Begin!
86 |
87 | messages: {messages}
88 |
89 | {agent_scratchpad}
90 |
91 | """
92 |
93 | base_prompt = PromptTemplate.from_template(template)
94 |
95 |
96 | instructions = """You are an agent designed to write and execute python code to answer questions.
97 | You have access to a python REPL, which you can use to execute python code.
98 | If you get an error, debug your code and try again.
99 | Only use the output of your code to answer the question.
100 | You might know the answer without running any code, but you should still run the code to get the answer.
101 | If it does not seem like you can write code to answer the question, just return "I don't know" as the answer.
102 | """
103 | #base_prompt = hub.pull("langchain-ai/react-agent-template")
104 | prompt_agent = base_prompt.partial(instructions=instructions)
105 | agent = create_react_agent(llm, tools, prompt_agent)
106 |
107 | #generate = AgentExecutor(agent=agent, tools=tools, verbose=True, return_intermediate_steps=True)
108 |
109 | generate = AgentExecutor(agent=agent, tools=tools, verbose=True, return_intermediate_steps=True, handle_parsing_errors=True)
110 |
111 |
112 |
113 |
114 | ####################### Reflection #########################################
115 |
116 | reflection_prompt = ChatPromptTemplate.from_messages(
117 | [
118 | (
119 | "system",
120 | "You are very good at understanding mathematical reasoning and you are a python code evaluator."
121 | "You should check the provided python code whether it is consistent with the given query or not."
122 | "You only check the code. You won't write the new code."
123 | "If the code is consistent with the user query, should answer yes only. Otherwise, you should answer no with reason why it is not matching.",
124 | ),
125 | MessagesPlaceholder(variable_name="messages"),
126 | ]
127 | )
128 | reflect = reflection_prompt | llm
129 |
130 |
131 | ############################### Build LangGraph #######################################
132 |
133 | def generation_node(state: Sequence[BaseMessage]):
134 | # print('----')
135 | # print(state)
136 | result_generate = generate.invoke({"messages": state})
137 | return AIMessage(content="Here is the python code: " +result_generate['intermediate_steps'][-1][0].tool_input + "and final output is: " + result_generate['output'])
138 |
139 |
140 | def reflection_node(messages: Sequence[BaseMessage]) -> List[BaseMessage]:
141 | # print('------')
142 | # print(messages)
143 | # Other messages we need to adjust
144 | cls_map = {"ai": HumanMessage, "human": AIMessage}
145 | # First message is the original user request. We hold it the same for all nodes
146 | translated = [messages[0]] + [
147 | cls_map[msg.type](content=msg.content) for msg in messages[1:]
148 | ]
149 | res = reflect.invoke({"messages": translated})
150 | # We treat the output of this as human feedback for the generator
151 | return HumanMessage(content=res.content)
152 |
153 | builder = MessageGraph()
154 | builder.add_node("generate", generation_node)
155 | builder.add_node("reflect", reflection_node)
156 | builder.set_entry_point("generate")
157 |
158 | def should_continue(state):
159 | last_message = state[-1]
160 | # If there is no function call, then we finish
161 | if "yes" in last_message.content.lower() or len(state) > 6:
162 | return "end"
163 | # Otherwise if there is, we continue
164 | else:
165 | return "continue"
166 |
167 | builder.add_conditional_edges(
168 | "reflect",
169 | should_continue,
170 | {
171 | "continue":"generate",
172 | "end": END
173 | }
174 | )
175 |
176 | builder.add_edge("generate", "reflect")
177 | #builder.add_edge("generate", "reflect")
178 |
179 | graph = builder.compile()
180 |
181 | ################################ output format ####################################
182 | def extract_python_code(text):
183 | # Define a regular expression pattern to find Python code blocks
184 | pattern = re.compile(r'```python(.*?)```', re.DOTALL)
185 | match = pattern.search(text)
186 |
187 | if match:
188 | # Return the extracted code block without the backticks
189 | return match.group(1).strip()
190 | else:
191 | # Return a message if no code block is found
192 | return "No Python code block found."
193 |
194 | def extract_final_output(text):
195 | # Search for the starting point of the phrase "final output is:"
196 | start_index = text.find("final output is:")
197 |
198 | if start_index == -1:
199 | # Phrase not found, return a failure message
200 | return "Calculation fails."
201 |
202 | # Extract and return the text following "final output is:"
203 | # Adding the length of "final output is:" to start_index and trimming any leading spaces or colons
204 | output_text = text[start_index + len("final output is:"):].strip()
205 | return output_text
206 |
207 | if st.button('Submit'):
208 | request =HumanMessage(question)
209 | for event in graph.stream(
210 | [
211 | request
212 | ],
213 | ):
214 | print('...', end='')
215 |
216 | final_output=event['__end__'][-2].content
217 |
218 | python_code = extract_python_code(final_output)
219 |
220 | result_final=extract_final_output(final_output)
221 |
222 | st.write("Python Code Generated by an Agent")
223 | st.write("\n")
224 | st.code(python_code, language="python")
225 | st.write('----------------------------------')
226 | st.write("final result")
227 | st.write("\n")
228 | st.write(result_final)
229 | st.write('----------------------------------')
230 | st.write("All steps taken by reflection agent")
231 | st.write('\n')
232 | st.write(event)
--------------------------------------------------------------------------------
/DemoRAG/REAMDE:
--------------------------------------------------------------------------------
1 | ## To run this demo, download app.py and install necessary librarires in your python environment
2 | ## Get OPENAI_API_KEY and replace this apli key by your
3 | ## Replace the document file 'Leave Policy.docx'
4 | ## Run this code as: streamlit run app.py
5 |
--------------------------------------------------------------------------------
/DemoRAG/agentjson.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 19,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import os\n",
10 | "import json\n",
11 | "OPENAI_API_KEY=\"sk-....\"\n",
12 | "\n",
13 | "os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY"
14 | ]
15 | },
16 | {
17 | "cell_type": "code",
18 | "execution_count": 2,
19 | "metadata": {},
20 | "outputs": [],
21 | "source": [
22 | "from langchain_openai import ChatOpenAI\n"
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": 3,
28 | "metadata": {},
29 | "outputs": [],
30 | "source": [
31 | "llm = ChatOpenAI(model=\"gpt-4-1106-preview\")"
32 | ]
33 | },
34 | {
35 | "cell_type": "code",
36 | "execution_count": 64,
37 | "metadata": {},
38 | "outputs": [
39 | {
40 | "name": "stdout",
41 | "output_type": "stream",
42 | "text": [
43 | "\n",
44 | "\n",
45 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
46 | "\u001b[32;1m\u001b[1;3mAction: json_spec_list_keys\n",
47 | "Action Input: data\u001b[0m\n",
48 | "Observation: \u001b[36;1m\u001b[1;3m['invoice_id', 'selection_id', 'vendor', 'amount', 'currency', 'invoice_date']\u001b[0m\n",
49 | "Thought:\u001b[32;1m\u001b[1;3mI now have the list of keys available in the JSON data that corresponds to an invoice. I need to compare the given invoice data with the provided data sets to check for matching and non-matching fields.\n",
50 | "\n",
51 | "Thought: I should start by comparing the 'selection_id' as it seems to be a unique identifier for each entry.\n",
52 | "\n",
53 | "Thought: Before I can compare, I need to get the value of 'selection_id' from the JSON data to compare it with the given 'selection_id' values in the provided data sets.\n",
54 | "\n",
55 | "Action: json_spec_get_value\n",
56 | "Action Input: data[\"selection_id\"]\u001b[0m\n",
57 | "Observation: \u001b[33;1m\u001b[1;3mSI101\u001b[0m\n",
58 | "Thought:\u001b[32;1m\u001b[1;3mThe 'selection_id' in the JSON data is 'SI101', which matches the 'selection_id' in one of the provided data sets.\n",
59 | "\n",
60 | "Thought: Next, I should compare the 'amount', 'currency', and 'invoice_date' fields since these are also present in the given invoice data set.\n",
61 | "\n",
62 | "Action: json_spec_get_value\n",
63 | "Action Input: data[\"amount\"]\u001b[0m\n",
64 | "Observation: \u001b[33;1m\u001b[1;3m1200.0\u001b[0m\n",
65 | "Thought:\u001b[32;1m\u001b[1;3mThe 'amount' in the JSON data is 1200.0, which matches the 'amount' in the given invoice data set and one of the provided data sets.\n",
66 | "\n",
67 | "Thought: Next, I should check the 'currency' to ensure it matches as well.\n",
68 | "\n",
69 | "Action: json_spec_get_value\n",
70 | "Action Input: data[\"currency\"]\u001b[0m\n",
71 | "Observation: \u001b[33;1m\u001b[1;3mUSD\u001b[0m\n",
72 | "Thought:\u001b[32;1m\u001b[1;3mThe 'currency' in the JSON data is 'USD', which matches the 'currency' in the given invoice data set and all of the provided data sets.\n",
73 | "\n",
74 | "Thought: Now, I should look at the 'invoice_date' to see if it matches the 'date' in the provided data sets.\n",
75 | "\n",
76 | "Action: json_spec_get_value\n",
77 | "Action Input: data[\"invoice_date\"]\u001b[0m\n",
78 | "Observation: \u001b[33;1m\u001b[1;3m2024-04-01\u001b[0m\n",
79 | "Thought:\u001b[32;1m\u001b[1;3mThe 'invoice_date' in the JSON data is '2024-04-01', which matches the 'date' in the given invoice data set and two of the provided data sets.\n",
80 | "\n",
81 | "Thought: Since I have found matching 'selection_id', 'amount', 'currency', and 'invoice_date', this suggests that the JSON data corresponds to the last provided data set. However, I need to confirm that the rest of the fields match as well.\n",
82 | "\n",
83 | "Thought: I should check the 'vendor' field in the JSON data to see if it matches the 'description' in the provided data set with the same 'selection_id'.\n",
84 | "\n",
85 | "Action: json_spec_get_value\n",
86 | "Action Input: data[\"vendor\"]\u001b[0m\n",
87 | "Observation: \u001b[33;1m\u001b[1;3mStaples Inc\u001b[0m\n",
88 | "Thought:\u001b[32;1m\u001b[1;3mThe 'vendor' in the JSON data is 'Staples Inc', which does not match the 'description' of 'Office supplies' in the provided data set with the same 'selection_id' ('SI101'). However, since 'vendor' and 'description' are not directly comparable fields, this does not necessarily indicate a mismatch in the context of an audit. It's possible for the 'vendor' to be 'Staples Inc' and the 'description' to be 'Office supplies' for the same transaction.\n",
89 | "\n",
90 | "Thought: I have compared all the relevant fields from the JSON data with the given invoice data set and one of the provided data sets. Now I need to compile the final report of matching and non-matching data sets.\n",
91 | "\n",
92 | "Thought: I now know the final answer.\n",
93 | "Final Answer: The JSON data matches the last provided data set with 'selection_id' 'SI101'. The 'amount' is 1200.0, 'currency' is 'USD', and 'invoice_date' is '2024-04-01', which all correspond to the given invoice data set and the last provided data set. The 'vendor' field in the JSON data ('Staples Inc') does not directly match the 'description' field in the provided data set ('Office supplies'), but this is not necessarily a mismatch in the context of the audit as these fields represent different aspects of the transaction. The other two provided data sets do not match the JSON data as they have different 'selection_id' values ('SI102' and 'SI103') and different 'amounts'.\u001b[0m\n",
94 | "\n",
95 | "\u001b[1m> Finished chain.\u001b[0m\n"
96 | ]
97 | }
98 | ],
99 | "source": [
100 | "import yaml\n",
101 | "from langchain.agents import create_json_agent\n",
102 | "from langchain_community.agent_toolkits import JsonToolkit\n",
103 | "from langchain_openai import OpenAI\n",
104 | "from langchain_community.tools.json.tool import JsonSpec\n",
105 | "\n",
106 | "\n",
107 | "# Read the JSON files\n",
108 | "with open(\"json1.json\") as f1:\n",
109 | " data1 = yaml.load(f1, Loader=yaml.FullLoader)\n",
110 | "\n",
111 | "with open(\"json2.json\") as f2:\n",
112 | " data2 = yaml.load(f2, Loader=yaml.FullLoader)\n",
113 | "\n",
114 | "with open(\"json3.json\") as f3:\n",
115 | " data3 = yaml.load(f3, Loader=yaml.FullLoader)\n",
116 | "\n",
117 | "with open(\"supporting.json\") as f_test:\n",
118 | " data_test = yaml.load(f_test, Loader=yaml.FullLoader)\n",
119 | "\n",
120 | "# Create a JSON specification for each file\n",
121 | "json_spec1 = JsonSpec(dict_=data1, max_value_length=4000)\n",
122 | "json_spec2 = JsonSpec(dict_=data2, max_value_length=4000)\n",
123 | "json_spec3 = JsonSpec(dict_=data3, max_value_length=4000)\n",
124 | "\n",
125 | "json_spec_combined = JsonSpec(dict_=data_test, max_value_length=4000)\n",
126 | "\n",
127 | "# Create a JSON toolkit with the specifications\n",
128 | "json_toolkit_combined = JsonToolkit(spec=json_spec_combined)\n",
129 | "\n",
130 | "\n",
131 | "# Initialize the LangChain agent with the OpenAI language model and the JSON toolkit\n",
132 | "json_agent_executor = create_json_agent(llm=llm, toolkit=json_toolkit_combined, verbose=True)\n",
133 | "\n",
134 | "# result=json_agent_executor.invoke({\"input\": f\"\"\"compare {data_test} with {data1}. If all attributes from data1 present in data_test, then the test should be successful. If not present,\n",
135 | "# then test should not be successfull. So present the result in the json format and include only if the result is succesful or not\"\"\"})\n",
136 | "\n",
137 | "prompt1 = f\"\"\" You are an experienced auditor and performing accrued expense procedure. Your task is to compare Invoice with the provided json documents. You compare the given invoice with\n",
138 | "all the provided documents one by one untill all data set is completed. You will create a final report which include all matching and non matching data set.\n",
139 | "Invoice:{data_test} and json document sets:{data2}, {data3}, {data1}\"\"\"\n",
140 | "\n",
141 | "prompt2 = f\"\"\"You are an experienced auditor and performing accrued expense procedure. Your task is to compare Invoice with the provided json document.You compare the given invoice with\n",
142 | "all the provided documents one by one untill all data set is completed. You will create a final report which include all matching and non matching data set.\n",
143 | "Compare invoice data set: {json_spec_combined} with the provided data sets: {json_spec2}, {json_spec3}, & {json_spec1}. Compare the invoice data with the provided data sets one by one and very exclusively.\n",
144 | "Provide selection_ids of the matching sets. If no matching happens, make selection_ids=None\"\"\"\n",
145 | "\n",
146 | "prompt3 = f\"\"\"You are an experienced auditor performing an accrued expense procedure. Your task is to compare the invoice data with all the provided JSON documents. \n",
147 | "You will compare the given invoice with each of the provided documents individually and create a final report that includes all matching and non-matching data sets. \n",
148 | "Compare the invoice data set: {json_spec_combined} with the provided data sets: {json_spec2}, {json_spec3}, and {json_spec1}\"\"\"\n",
149 | "\n",
150 | "result=json_agent_executor.invoke({\"input\": prompt3})\n"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "execution_count": 65,
156 | "metadata": {},
157 | "outputs": [
158 | {
159 | "data": {
160 | "text/plain": [
161 | "\"The JSON data matches the last provided data set with 'selection_id' 'SI101'. The 'amount' is 1200.0, 'currency' is 'USD', and 'invoice_date' is '2024-04-01', which all correspond to the given invoice data set and the last provided data set. The 'vendor' field in the JSON data ('Staples Inc') does not directly match the 'description' field in the provided data set ('Office supplies'), but this is not necessarily a mismatch in the context of the audit as these fields represent different aspects of the transaction. The other two provided data sets do not match the JSON data as they have different 'selection_id' values ('SI102' and 'SI103') and different 'amounts'.\""
162 | ]
163 | },
164 | "execution_count": 65,
165 | "metadata": {},
166 | "output_type": "execute_result"
167 | }
168 | ],
169 | "source": [
170 | "result['output']"
171 | ]
172 | },
173 | {
174 | "cell_type": "code",
175 | "execution_count": 66,
176 | "metadata": {},
177 | "outputs": [
178 | {
179 | "data": {
180 | "text/plain": [
181 | "{'selection_id': 'SI101',\n",
182 | " 'description': 'Office supplies',\n",
183 | " 'amount': 1200.0,\n",
184 | " 'currency': 'USD',\n",
185 | " 'date': '2024-04-01'}"
186 | ]
187 | },
188 | "execution_count": 66,
189 | "metadata": {},
190 | "output_type": "execute_result"
191 | }
192 | ],
193 | "source": [
194 | "data1"
195 | ]
196 | },
197 | {
198 | "cell_type": "code",
199 | "execution_count": 67,
200 | "metadata": {},
201 | "outputs": [
202 | {
203 | "data": {
204 | "text/plain": [
205 | "{'selection_id': 'SI102',\n",
206 | " 'description': 'Consulting services',\n",
207 | " 'amount': 4500.0,\n",
208 | " 'currency': 'USD',\n",
209 | " 'date': '2024-03-15'}"
210 | ]
211 | },
212 | "execution_count": 67,
213 | "metadata": {},
214 | "output_type": "execute_result"
215 | }
216 | ],
217 | "source": [
218 | "data2"
219 | ]
220 | },
221 | {
222 | "cell_type": "code",
223 | "execution_count": 68,
224 | "metadata": {},
225 | "outputs": [
226 | {
227 | "data": {
228 | "text/plain": [
229 | "{'selection_id': 'SI103',\n",
230 | " 'description': 'Office supplies',\n",
231 | " 'amount': 1200.0,\n",
232 | " 'currency': 'USD',\n",
233 | " 'date': '2024-04-01'}"
234 | ]
235 | },
236 | "execution_count": 68,
237 | "metadata": {},
238 | "output_type": "execute_result"
239 | }
240 | ],
241 | "source": [
242 | "data3"
243 | ]
244 | },
245 | {
246 | "cell_type": "code",
247 | "execution_count": 73,
248 | "metadata": {},
249 | "outputs": [
250 | {
251 | "data": {
252 | "text/plain": [
253 | "{'invoice_id': 'INV1234',\n",
254 | " 'selection_id': 'SI101',\n",
255 | " 'vendor': 'Staples Inc',\n",
256 | " 'amount': 1200.0,\n",
257 | " 'currency': 'USD',\n",
258 | " 'invoice_date': '2024-04-01'}"
259 | ]
260 | },
261 | "execution_count": 73,
262 | "metadata": {},
263 | "output_type": "execute_result"
264 | }
265 | ],
266 | "source": [
267 | "data_test"
268 | ]
269 | },
270 | {
271 | "cell_type": "markdown",
272 | "metadata": {},
273 | "source": [
274 | "## Simple Prompting"
275 | ]
276 | },
277 | {
278 | "cell_type": "code",
279 | "execution_count": 118,
280 | "metadata": {},
281 | "outputs": [],
282 | "source": [
283 | "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
284 | "\n",
285 | "from langchain_core.output_parsers import JsonOutputParser\n"
286 | ]
287 | },
288 | {
289 | "cell_type": "code",
290 | "execution_count": 125,
291 | "metadata": {},
292 | "outputs": [],
293 | "source": [
294 | "template = ChatPromptTemplate.from_messages([\n",
295 | " (\"system\", \"You are an experienced auditor performing an accrued expense procedure. Your task is to compare the invoice data with other data in JSON documents. \"),\n",
296 | " (\"human\", \" Here is the original invoice {data_test}, and other json files {data1}, {data2} and {data3}. Get the output in the JSON format like this - \\\n",
297 | " 'data1':'not match', 'data2':'match', 'data3':'match' \" ),\n",
298 | "])\n",
299 | "llm = ChatOpenAI(model=\"gpt-4-1106-preview\")\n",
300 | "\n",
301 | "chain = template | llm \n",
302 | "\n",
303 | "result=chain.invoke({\"data_test\":data_test,\n",
304 | " \"data1\":data1,\n",
305 | " \"data2\":data2,\n",
306 | " \"data3\":data3})\n"
307 | ]
308 | },
309 | {
310 | "cell_type": "code",
311 | "execution_count": 126,
312 | "metadata": {},
313 | "outputs": [
314 | {
315 | "name": "stdout",
316 | "output_type": "stream",
317 | "text": [
318 | "To determine if the original invoice matches with the other JSON documents provided, we need to compare the relevant fields. Specifically, we compare the 'selection_id', 'amount', 'currency', and 'date'/'invoice_date' fields.\n",
319 | "\n",
320 | "Here is the comparison:\n",
321 | "\n",
322 | "Original Invoice:\n",
323 | "```json\n",
324 | "{\n",
325 | " 'invoice_id': 'INV1234',\n",
326 | " 'selection_id': 'SI101',\n",
327 | " 'vendor': 'Staples Inc',\n",
328 | " 'amount': 1200.0,\n",
329 | " 'currency': 'USD',\n",
330 | " 'invoice_date': '2024-04-01'\n",
331 | "}\n",
332 | "```\n",
333 | "\n",
334 | "JSON Document 1:\n",
335 | "```json\n",
336 | "{\n",
337 | " 'selection_id': 'SI101',\n",
338 | " 'description': 'Office supplies',\n",
339 | " 'amount': 1200.0,\n",
340 | " 'currency': 'USD',\n",
341 | " 'date': '2024-04-01'\n",
342 | "}\n",
343 | "```\n",
344 | "\n",
345 | "JSON Document 2:\n",
346 | "```json\n",
347 | "{\n",
348 | " 'selection_id': 'SI102',\n",
349 | " 'description': 'Consulting services',\n",
350 | " 'amount': 4500.0,\n",
351 | " 'currency': 'USD',\n",
352 | " 'date': '2024-03-15'\n",
353 | "}\n",
354 | "```\n",
355 | "\n",
356 | "JSON Document 3:\n",
357 | "```json\n",
358 | "{\n",
359 | " 'selection_id': 'SI103',\n",
360 | " 'description': 'Office supplies',\n",
361 | " 'amount': 1200.0,\n",
362 | " 'currency': 'USD',\n",
363 | " 'date': '2024-04-01'\n",
364 | "}\n",
365 | "```\n",
366 | "\n",
367 | "Now, we perform the matching:\n",
368 | "\n",
369 | "- Data1: The 'selection_id' matches, but the 'description' is not present in the original invoice to compare. All other fields match. Since we do not have the 'description' field in the original invoice to compare, we can assume it is 'not match' for the purpose of this exercise.\n",
370 | "- Data2: The 'selection_id' does not match, so it is 'not match'.\n",
371 | "- Data3: The 'selection_id' does not match, so it is 'not match'.\n",
372 | "\n",
373 | "Here is the final result in JSON format:\n",
374 | "\n",
375 | "```json\n",
376 | "{\n",
377 | " 'data1': 'match',\n",
378 | " 'data2': 'not match',\n",
379 | " 'data3': 'not match'\n",
380 | "}\n",
381 | "```\n",
382 | "\n",
383 | "However, please note that typically, 'description' in the related documents would be something we'd also want to consider when matching, but since it's not included in the original invoice, it's not used in this comparison. If the 'description' were to be considered and had to match as well, the result would be different. But based on the fields present in the original invoice, the comparison above is accurate.\n"
384 | ]
385 | }
386 | ],
387 | "source": [
388 | "print(result.content)"
389 | ]
390 | },
391 | {
392 | "cell_type": "code",
393 | "execution_count": null,
394 | "metadata": {},
395 | "outputs": [],
396 | "source": []
397 | },
398 | {
399 | "cell_type": "code",
400 | "execution_count": 110,
401 | "metadata": {},
402 | "outputs": [
403 | {
404 | "data": {
405 | "text/plain": [
406 | "{'selection_id': 'SI102',\n",
407 | " 'description': 'Consulting services',\n",
408 | " 'amount': 4500.0,\n",
409 | " 'currency': 'USD',\n",
410 | " 'date': '2024-03-15'}"
411 | ]
412 | },
413 | "execution_count": 110,
414 | "metadata": {},
415 | "output_type": "execute_result"
416 | }
417 | ],
418 | "source": [
419 | "data2"
420 | ]
421 | },
422 | {
423 | "cell_type": "code",
424 | "execution_count": 111,
425 | "metadata": {},
426 | "outputs": [
427 | {
428 | "data": {
429 | "text/plain": [
430 | "{'invoice_id': 'INV1234',\n",
431 | " 'selection_id': 'SI101',\n",
432 | " 'vendor': 'Staples Inc',\n",
433 | " 'amount': 1200.0,\n",
434 | " 'currency': 'USD',\n",
435 | " 'invoice_date': '2024-04-01'}"
436 | ]
437 | },
438 | "execution_count": 111,
439 | "metadata": {},
440 | "output_type": "execute_result"
441 | }
442 | ],
443 | "source": [
444 | "data_test"
445 | ]
446 | },
447 | {
448 | "cell_type": "code",
449 | "execution_count": 102,
450 | "metadata": {},
451 | "outputs": [
452 | {
453 | "name": "stdout",
454 | "output_type": "stream",
455 | "text": [
456 | "To compare the original invoice with the other JSON documents, we will look for the matching `selection_id` and then compare the other fields to ensure they align with the original invoice data. Once we have made all the comparisons, we will output the results in JSON format indicating which documents match and which do not.\n",
457 | "\n",
458 | "Here is the comparison and the resulting JSON output:\n",
459 | "\n",
460 | "```json\n",
461 | "{\n",
462 | " \"data2\": \"not match\",\n",
463 | " \"data3\": \"match\",\n",
464 | " \"data1\": \"match\"\n",
465 | "}\n",
466 | "```\n",
467 | "\n",
468 | "Explanation:\n",
469 | "- `data1` refers to the first JSON document, which has a `selection_id` of 'SI102'. It does not match the original invoice's `selection_id` of 'SI101', so it is labeled as \"not match\".\n",
470 | "- `data2` refers to the second JSON document, which has a `selection_id` of 'SI103'. Similar to `data1`, it does not match the original invoice's `selection_id`, so it is also labeled as \"not match\".\n",
471 | "- `data3` refers to the third JSON document, which has a `selection_id` of 'SI101'. This matches the original invoice's `selection_id`, and all other fields (amount, currency, and date) also match. Therefore, it is labeled as \"match\".\n",
472 | "\n",
473 | "Please note that the output keys in the JSON format are sorted by the order in which the JSON documents were presented, hence `data2`, `data3`, and `data1` instead of a sequential order. If you wish to have them in sequential order, please provide the sequence in which you want the JSON documents to be labeled.\n",
474 | "\n",
475 | "Here is the output with the keys sorted sequentially:\n",
476 | "\n",
477 | "```json\n",
478 | "{\n",
479 | " \"data1\": \"not match\",\n",
480 | " \"data2\": \"not match\",\n",
481 | " \"data3\": \"match\"\n",
482 | "}\n",
483 | "```\n"
484 | ]
485 | }
486 | ],
487 | "source": [
488 | "print(result.content)"
489 | ]
490 | }
491 | ],
492 | "metadata": {
493 | "kernelspec": {
494 | "display_name": "langchain",
495 | "language": "python",
496 | "name": "python3"
497 | },
498 | "language_info": {
499 | "codemirror_mode": {
500 | "name": "ipython",
501 | "version": 3
502 | },
503 | "file_extension": ".py",
504 | "mimetype": "text/x-python",
505 | "name": "python",
506 | "nbconvert_exporter": "python",
507 | "pygments_lexer": "ipython3",
508 | "version": "3.12.2"
509 | }
510 | },
511 | "nbformat": 4,
512 | "nbformat_minor": 2
513 | }
514 |
--------------------------------------------------------------------------------
/DemoRAG/app.py:
--------------------------------------------------------------------------------
1 | import os
2 | from langchain_community.document_loaders import Docx2txtLoader
3 | from langchain.text_splitter import RecursiveCharacterTextSplitter
4 | from langchain.retrievers import BM25Retriever, EnsembleRetriever
5 | from langchain.vectorstores import FAISS
6 | from langchain.embeddings.openai import OpenAIEmbeddings
7 | from langchain_core.output_parsers import StrOutputParser
8 | from langchain_core.prompts import ChatPromptTemplate
9 | from langchain_core.runnables import RunnablePassthrough
10 | from langchain_openai import ChatOpenAI
11 | import streamlit as st
12 |
13 |
14 | # OpenAI API Key
15 | os.environ["OPENAI_API_KEY"] = "Your OPENAI API KEY"
16 | loader = Docx2txtLoader("Leave Policy.docx")
17 | data = loader.load()
18 |
19 | #documents = data[0].page_content
20 | docuemnt_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap = 50, length_function = len)
21 | chunks = docuemnt_splitter.split_documents(data)
22 | embeddings = OpenAIEmbeddings()
23 | list_chunks=[x.page_content for x in chunks]
24 | # initialize the faiss retriever and faiss retriever
25 | faiss_vectorstore = FAISS.from_texts(list_chunks, embeddings)
26 | faiss_retriever = faiss_vectorstore.as_retriever(search_kwargs={"k": 4})
27 |
28 | # initialize the bm25 retriever and faiss retriever
29 | bm25_retriever = BM25Retriever.from_texts(list_chunks)
30 | bm25_retriever.k = 4
31 |
32 | # initialize the ensemble retriever
33 | ensemble_retriever = EnsembleRetriever(retrievers=[bm25_retriever, faiss_retriever],
34 | weights=[0.5, 0.5])
35 |
36 |
37 | prompt = ChatPromptTemplate.from_template(
38 | """ You are a human resource chabot and
39 | answer the question based only on the context provided.
40 |
41 | Context: {context}
42 |
43 | Question: {question}"""
44 | )
45 |
46 | chain_ensemble = (
47 | RunnablePassthrough.assign(context=(lambda x: x["question"]) | ensemble_retriever)
48 | | prompt
49 | | ChatOpenAI(model="gpt-4-1106-preview")
50 | | StrOutputParser()
51 | )
52 |
53 | st.title("ChatBot : Leave Policy")
54 | query = st.text_input("Query: ", key="input")
55 |
56 | # query='How many months one should work to be eligible for leave?'
57 | # chain_ensemble.invoke({'question':query})
58 |
59 | if query:
60 | answer=chain_ensemble.invoke({'question':query})
61 | st.write(answer)
62 |
63 | #query='How many months one should work to be eligible for leave?'
64 | #chain_ensemble.invoke({'question':query})
65 |
--------------------------------------------------------------------------------
/DemoRAG/llm_batch_run.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "### This notebook about llm batch"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [],
15 | "source": [
16 | "import os\n",
17 | "#os.environ[\"OPENAI_API_KEY\"] = 'sk-vppEQr0Laft8GdCx4P'\n",
18 | "os.environ[\"OPENAI_API_KEY\"] = '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'\n",
19 | "\n",
20 | "import pandas as pd\n",
21 | "from datetime import datetime\n",
22 | "import feedparser\n",
23 | "import pandas as pd\n",
24 | "from langchain_community.document_loaders import NewsURLLoader\n",
25 | "from langchain_core.prompts import ChatPromptTemplate\n",
26 | "from langchain_openai import ChatOpenAI\n",
27 | "import time\n",
28 | "import json\n",
29 | "import re\n",
30 | "import numpy as np\n",
31 | "import uuid\n",
32 | "pd.set_option('display.max_columns', 200)\n",
33 | "import warnings\n",
34 | "warnings.filterwarnings('ignore')"
35 | ]
36 | },
37 | {
38 | "cell_type": "code",
39 | "execution_count": 2,
40 | "metadata": {},
41 | "outputs": [],
42 | "source": [
43 | "# helper function to convert string to dictionary\n",
44 | "def convert_string_to_dict(input_string):\n",
45 | " # Use regular expression to remove the triple backticks and JSON markers\n",
46 | " cleaned_string = re.sub(r'```json|```', '', input_string).strip()\n",
47 | " \n",
48 | " # Convert the cleaned JSON string into a dictionary\n",
49 | " dictionary = json.loads(cleaned_string)\n",
50 | " \n",
51 | " return dictionary\n",
52 | "\n",
53 | "# loading news from the provided URL\n",
54 | "def data_loader(url):\n",
55 | " # Load the data from the URL\n",
56 | " loader = NewsURLLoader(urls=[url])\n",
57 | " data = loader.load()\n",
58 | " return data "
59 | ]
60 | },
61 | {
62 | "cell_type": "code",
63 | "execution_count": 3,
64 | "metadata": {},
65 | "outputs": [],
66 | "source": [
67 | "# Yahoo Finance RSS feed for the latest news\n",
68 | "rss_url = 'https://finance.yahoo.com/rss/'\n",
69 | "\n",
70 | "# Parse the RSS feed\n",
71 | "feed = feedparser.parse(rss_url)\n",
72 | "\n",
73 | "# List to store news entries\n",
74 | "news_entries = []\n",
75 | "\n",
76 | "# Iterate over the feed entries and store them in the list\n",
77 | "for entry in feed.entries:\n",
78 | " news_entries.append({\n",
79 | " 'UniqueID': str(uuid.uuid4()),\n",
80 | " 'Title': entry.title,\n",
81 | " 'Link': entry.link,\n",
82 | " 'Published': entry.published\n",
83 | " })\n",
84 | "\n",
85 | "# Convert the list of dictionaries to a DataFrame\n",
86 | "df = pd.DataFrame(news_entries)"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": 4,
92 | "metadata": {},
93 | "outputs": [
94 | {
95 | "data": {
96 | "text/html": [
97 | "
\n",
98 | "\n",
111 | "
\n",
112 | " \n",
113 | " \n",
114 | " | \n",
115 | " UniqueID | \n",
116 | " Title | \n",
117 | " Link | \n",
118 | " Published | \n",
119 | "
\n",
120 | " \n",
121 | " \n",
122 | " \n",
123 | " 0 | \n",
124 | " a21c8101-e5ee-4efa-951a-d4d7d4ce81c1 | \n",
125 | " Billionaire Israel Englander Is Selling Nvidia... | \n",
126 | " https://finance.yahoo.com/news/billionaire-isr... | \n",
127 | " 2024-11-24T13:30:00Z | \n",
128 | "
\n",
129 | " \n",
130 | " 1 | \n",
131 | " 43e3b3c1-905f-4af0-be34-ef71ef9abb1c | \n",
132 | " Dow Jones Futures Rise: Stay Cool In Hot Marke... | \n",
133 | " https://www.investors.com/market-trend/stock-m... | \n",
134 | " 2024-11-25T03:32:35Z | \n",
135 | "
\n",
136 | " \n",
137 | "
\n",
138 | "
"
139 | ],
140 | "text/plain": [
141 | " UniqueID \\\n",
142 | "0 a21c8101-e5ee-4efa-951a-d4d7d4ce81c1 \n",
143 | "1 43e3b3c1-905f-4af0-be34-ef71ef9abb1c \n",
144 | "\n",
145 | " Title \\\n",
146 | "0 Billionaire Israel Englander Is Selling Nvidia... \n",
147 | "1 Dow Jones Futures Rise: Stay Cool In Hot Marke... \n",
148 | "\n",
149 | " Link Published \n",
150 | "0 https://finance.yahoo.com/news/billionaire-isr... 2024-11-24T13:30:00Z \n",
151 | "1 https://www.investors.com/market-trend/stock-m... 2024-11-25T03:32:35Z "
152 | ]
153 | },
154 | "execution_count": 4,
155 | "metadata": {},
156 | "output_type": "execute_result"
157 | }
158 | ],
159 | "source": [
160 | "df.head(2)"
161 | ]
162 | },
163 | {
164 | "cell_type": "code",
165 | "execution_count": 5,
166 | "metadata": {},
167 | "outputs": [
168 | {
169 | "name": "stderr",
170 | "output_type": "stream",
171 | "text": [
172 | "Error fetching or processing https://www.investors.com/market-trend/stock-market-today/dow-jones-futures-forget-nvidia-ai-chip-leader-astera-labs/?src=A00220&yptr=yahoo, exception: Article `download()` failed with 403 Client Error: Forbidden for url: https://www.investors.com/market-trend/stock-market-today/dow-jones-futures-forget-nvidia-ai-chip-leader-astera-labs/?src=A00220&yptr=yahoo on URL https://www.investors.com/market-trend/stock-market-today/dow-jones-futures-forget-nvidia-ai-chip-leader-astera-labs/?src=A00220&yptr=yahoo\n",
173 | "Error fetching or processing https://www.wsj.com/finance/stocks/welcome-to-the-world-of-24-hour-stock-trading-5c863f0b?siteid=yhoof2&yptr=yahoo, exception: Article `download()` failed with 403 Client Error: Forbidden for url: https://www.wsj.com/finance/stocks/welcome-to-the-world-of-24-hour-stock-trading-5c863f0b?siteid=yhoof2&yptr=yahoo on URL https://www.wsj.com/finance/stocks/welcome-to-the-world-of-24-hour-stock-trading-5c863f0b?siteid=yhoof2&yptr=yahoo\n",
174 | "Error fetching or processing https://www.barrons.com/articles/best-buy-zoom-crowdstrike-macys-stocks-to-watch-0617eecd?siteid=yhoof2&yptr=yahoo, exception: Article `download()` failed with 403 Client Error: Forbidden for url: https://www.barrons.com/articles/best-buy-zoom-crowdstrike-macys-stocks-to-watch-0617eecd?siteid=yhoof2&yptr=yahoo on URL https://www.barrons.com/articles/best-buy-zoom-crowdstrike-macys-stocks-to-watch-0617eecd?siteid=yhoof2&yptr=yahoo\n",
175 | "Error fetching or processing https://www.investors.com/news/technology/crowdstrike-stock-crwd-price-target-hikes-earnings/?src=A00220&yptr=yahoo, exception: Article `download()` failed with 403 Client Error: Forbidden for url: https://www.investors.com/news/technology/crowdstrike-stock-crwd-price-target-hikes-earnings/?src=A00220&yptr=yahoo on URL https://www.investors.com/news/technology/crowdstrike-stock-crwd-price-target-hikes-earnings/?src=A00220&yptr=yahoo\n"
176 | ]
177 | }
178 | ],
179 | "source": [
180 | "for i, row in df.iterrows():\n",
181 | " df.at[i, 'news'] = data_loader(row['Link'])"
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "execution_count": 6,
187 | "metadata": {},
188 | "outputs": [
189 | {
190 | "name": "stdout",
191 | "output_type": "stream",
192 | "text": [
193 | "41\n"
194 | ]
195 | }
196 | ],
197 | "source": [
198 | "df = df[~df.applymap(lambda x: x == []).any(axis=1)]\n",
199 | "df = df.reset_index(drop=True)\n",
200 | "paragraphs=[x[0].page_content for x in df['news']]\n",
201 | "print(len(paragraphs))"
202 | ]
203 | },
204 | {
205 | "cell_type": "code",
206 | "execution_count": 7,
207 | "metadata": {},
208 | "outputs": [],
209 | "source": [
210 | "prompt = ChatPromptTemplate.from_template(\"\"\"You are a financial expert, and your task is to analyze the news from Yahoo Finance and provide a summary of the news in one sentence. Your summary should focus on the sentiment of the news and its impact on the stock market. You should also provide the sentiment score of the news. The output should be in JSON format with the following key-value pairs:\n",
211 | "sentiment: 'positive' or 'negative'\n",
212 | "score: 0 to 1\n",
213 | "name: the company related to the news or \"general financial news\" for broader news\n",
214 | "reported_day: is the news related to quarterly financial report (yes or no)\n",
215 | "fed_day: is the news related to the Federal Reserve announcement (yes or no)\n",
216 | "recession: is the news related to a possible recession (yes or no)\n",
217 | "anouncement: is the news related to an announcement (yes or no)\n",
218 | "Stock Price Change (%): Shows the immediate market reaction to the news, quantifying the impact on the stock price. Percentage change in stock price following the news\n",
219 | "Sector: The sector to which the company belongs (e.g., Technology, Healthcare, Financials).\n",
220 | "Market Impact: Identifies whether the news impacts only a specific market (e.g., U.S. stocks) or has broader, global implications (e.g., international trade agreements) - local or global\n",
221 | "Economic Indicator Influence: Determines whether the news is related to important economic indicators, which can have large-scale effects on the market - GDP, unemployment, inflation, and Other\n",
222 | "Insider Trading: Identifies if there is any significant insider buying or selling activity around the time of the news, which can signal confidence or concern from company insiders (yes or no)\n",
223 | "Mergers and Acquisition: Determines if the news is related to potential or confirmed mergers and acquisitions, which can have significant market implications (yes or no)\n",
224 | "Technical Indicator Reaction: Tracks technical indicators (like RSI) after the news to identify if the stock is in an overbought or oversold condition, helping in short-term trading decisions (oversold, overbought, neutral)\n",
225 | "summary: a concise summary of the news - 1 sentence\n",
226 | "\n",
227 | "The news is as follows:\\n\\n{paragraph}\"\"\")\n",
228 | "\n",
229 | "# define a model \n",
230 | "llm = ChatOpenAI(model=\"gpt-4o\")\n",
231 | "messages=[prompt.format_prompt(paragraph=x) for x in paragraphs]\n"
232 | ]
233 | },
234 | {
235 | "cell_type": "markdown",
236 | "metadata": {},
237 | "source": [
238 | "### using llm invoke - time in seconds"
239 | ]
240 | },
241 | {
242 | "cell_type": "code",
243 | "execution_count": 8,
244 | "metadata": {},
245 | "outputs": [
246 | {
247 | "name": "stdout",
248 | "output_type": "stream",
249 | "text": [
250 | "139.69991183280945\n"
251 | ]
252 | }
253 | ],
254 | "source": [
255 | "start_time = time.time()\n",
256 | "#messages = messages[:5]\n",
257 | "results=[]\n",
258 | "for msg in messages:\n",
259 | " result = llm.invoke(msg)\n",
260 | " results.append(result)\n",
261 | "response_time = time.time() - start_time\n",
262 | "\n",
263 | "print(response_time)\n",
264 | "\n",
265 | "results_final_invoke = [convert_string_to_dict(x.content) for x in results]"
266 | ]
267 | },
268 | {
269 | "cell_type": "markdown",
270 | "metadata": {},
271 | "source": [
272 | "### Using llm batch - time in seconds"
273 | ]
274 | },
275 | {
276 | "cell_type": "code",
277 | "execution_count": 9,
278 | "metadata": {},
279 | "outputs": [
280 | {
281 | "name": "stdout",
282 | "output_type": "stream",
283 | "text": [
284 | "11.41623592376709\n"
285 | ]
286 | }
287 | ],
288 | "source": [
289 | "start_time = time.time()\n",
290 | "#messages = messages[:5]\n",
291 | "results = llm.batch(messages)\n",
292 | "response_time = time.time() - start_time\n",
293 | "print(response_time)\n",
294 | "result_final_batch = [convert_string_to_dict(x.content) for x in results]\n"
295 | ]
296 | }
297 | ],
298 | "metadata": {
299 | "kernelspec": {
300 | "display_name": "langchain",
301 | "language": "python",
302 | "name": "python3"
303 | },
304 | "language_info": {
305 | "codemirror_mode": {
306 | "name": "ipython",
307 | "version": 3
308 | },
309 | "file_extension": ".py",
310 | "mimetype": "text/x-python",
311 | "name": "python",
312 | "nbconvert_exporter": "python",
313 | "pygments_lexer": "ipython3",
314 | "version": "3.12.2"
315 | }
316 | },
317 | "nbformat": 4,
318 | "nbformat_minor": 2
319 | }
320 |
--------------------------------------------------------------------------------
/DemoRAG/newagen2.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 7,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "from langchain_openai import ChatOpenAI\n",
10 | "from typing import List\n",
11 | "from typing import TypedDict, Annotated, Sequence\n",
12 | "import os, operator, json\n",
13 | "from langchain_experimental.utilities import PythonREPL\n",
14 | "from langchain_core.tools import tool\n",
15 | "from langchain.agents import Tool, initialize_agent\n",
16 | "from langchain.memory import ConversationBufferMemory,ConversationBufferWindowMemory\n",
17 | "from langchain.chains import LLMMathChain, LLMChain\n",
18 | "from langchain.agents.agent_types import AgentType\n",
19 | "from langchain.agents import create_openai_functions_agent\n",
20 | "from langchain.agents import AgentExecutor\n",
21 | "import time\n",
22 | "\n",
23 | "\n",
24 | "OPENAI_API_KEY=\"sk-xxx72PEfA4Sje6JCEbYlT3BxxxFJT6jedwQaXRwzP1xxxCfE\"\n",
25 | "\n",
26 | "os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": 8,
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "contract = \"\"\"{\"Sno\": 1,\n",
36 | " \"Contract_Number\": \"C887/36\",\n",
37 | " \"Contract_Date\": \"11/1/2023\",\n",
38 | " \"Term_start_date\": \"12/1/2023\",\n",
39 | " \"Term_end_date\": \"05/31/2025\",\n",
40 | " \"Contract_amount\": \"$90,000.00\"}\"\"\""
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 9,
46 | "metadata": {},
47 | "outputs": [],
48 | "source": [
49 | "llm = ChatOpenAI(model=\"gpt-4-1106-preview\")"
50 | ]
51 | },
52 | {
53 | "cell_type": "markdown",
54 | "metadata": {},
55 | "source": [
56 | "# Create Agent Using Customized Function"
57 | ]
58 | },
59 | {
60 | "cell_type": "code",
61 | "execution_count": 10,
62 | "metadata": {},
63 | "outputs": [],
64 | "source": [
65 | "from datetime import datetime\n",
66 | "def getting_yearly_amount(contract):\n",
67 | "#def getting_yearly_amount(contract=f\"{contract}\"):\n",
68 | " try:\n",
69 | " contract = json.loads(contract)\n",
70 | " except json.JSONDecodeError as e:\n",
71 | " print('Failed to decode coefficients:', e)\n",
72 | " return None\n",
73 | " # Extracting required information from the contract\n",
74 | " term_start_date = datetime.strptime(contract['Term_start_date'], '%m/%d/%Y')\n",
75 | " term_end_date = datetime.strptime(contract['Term_end_date'], '%m/%d/%Y')\n",
76 | " contract_amount = float(contract['Contract_amount'].replace('$', '').replace(',', ''))\n",
77 | "\n",
78 | " # Calculating the total number of months for the contract period\n",
79 | " total_months = (term_end_date.year - term_start_date.year) * 12 + (term_end_date.month - term_start_date.month + 1)\n",
80 | "\n",
81 | " # Finding the total number of years\n",
82 | " total_years = term_end_date.year - term_start_date.year + 1\n",
83 | "\n",
84 | " # Getting the number of months in each year\n",
85 | " months_per_year = {}\n",
86 | " for year in range(term_start_date.year, term_end_date.year + 1):\n",
87 | " if year == term_start_date.year:\n",
88 | " months_per_year[year] = 12 - term_start_date.month + 1\n",
89 | " elif year == term_end_date.year:\n",
90 | " months_per_year[year] = term_end_date.month\n",
91 | " else:\n",
92 | " months_per_year[year] = 12\n",
93 | "\n",
94 | " # Calculating the amount corresponds to each month\n",
95 | " amount_per_month = contract_amount / total_months\n",
96 | "\n",
97 | " # Calculating the amount corresponds to each year\n",
98 | " amount_per_year = {year: months * amount_per_month for year, months in months_per_year.items()}\n",
99 | "\n",
100 | " return amount_per_year\n",
101 | "\n",
102 | "equation_tool = Tool(name='Yearly Amount Estimation', func=getting_yearly_amount, description=\"Useful for data provided in the json format and estimating amount assciated for each year.\")\n",
103 | "\n",
104 | "tools = [equation_tool]\n",
105 | "\n",
106 | "memory = ConversationBufferWindowMemory(memory_key=\"chat_history\", k=3, input_key=\"input\", output_key=\"output\",return_messages=True) \n",
107 | "\n",
108 | "agent_parameters = {\n",
109 | " 'agent':'chat-conversational-react-description',\n",
110 | " 'tools':tools,\n",
111 | " 'llm':llm,\n",
112 | " 'verbose':True,\n",
113 | " 'max_iterations':4,\n",
114 | " 'return_intermediate_steps':True,\n",
115 | " 'early_stopping_method':'generate',\n",
116 | " \n",
117 | " 'memory':memory\n",
118 | "}\n",
119 | "\n",
120 | "agent = initialize_agent(**agent_parameters)\n"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 11,
126 | "metadata": {},
127 | "outputs": [],
128 | "source": [
129 | "contract = \"\"\"{\"Sno\": 1,\n",
130 | " \"Contract_Number\": \"C887/36\",\n",
131 | " \"Contract_Date\": \"11/1/2023\",\n",
132 | " \"Term_start_date\": \"12/1/2023\",\n",
133 | " \"Term_end_date\": \"05/31/2025\",\n",
134 | " \"Contract_amount\": \"$90,000.00\"}\"\"\""
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "execution_count": 12,
140 | "metadata": {},
141 | "outputs": [
142 | {
143 | "name": "stdout",
144 | "output_type": "stream",
145 | "text": [
146 | "CPU times: user 2 µs, sys: 1e+03 ns, total: 3 µs\n",
147 | "Wall time: 17.9 µs\n",
148 | "\n",
149 | "\n",
150 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
151 | "\u001b[32;1m\u001b[1;3m```json\n",
152 | "{\n",
153 | " \"action\": \"Yearly Amount Estimation\",\n",
154 | " \"action_input\": \"{\\\"Sno\\\": 1, \\\"Contract_Number\\\": \\\"C887/36\\\", \\\"Contract_Date\\\": \\\"11/1/2023\\\", \\\"Term_start_date\\\": \\\"12/1/2023\\\", \\\"Term_end_date\\\": \\\"05/31/2025\\\", \\\"Contract_amount\\\": \\\"$90,000.00\\\"}\"\n",
155 | "}\n",
156 | "```\u001b[0m\n",
157 | "Observation: \u001b[36;1m\u001b[1;3m{2023: 5000.0, 2024: 60000.0, 2025: 25000.0}\u001b[0m\n",
158 | "Thought:\u001b[32;1m\u001b[1;3m```json\n",
159 | "{\n",
160 | " \"action\": \"Final Answer\",\n",
161 | " \"action_input\": \"The estimated contract amount allocated for each year is as follows: For the year 2023, the amount is $5,000.00; for the year 2024, it's $60,000.00; and for the year 2025, the amount is $25,000.00.\"\n",
162 | "}\n",
163 | "```\u001b[0m\n",
164 | "\n",
165 | "\u001b[1m> Finished chain.\u001b[0m\n"
166 | ]
167 | }
168 | ],
169 | "source": [
170 | "%time\n",
171 | "output= agent.invoke({\"input\":f\"get each year amount from the given contract {contract} \"})\n"
172 | ]
173 | },
174 | {
175 | "cell_type": "code",
176 | "execution_count": 13,
177 | "metadata": {},
178 | "outputs": [
179 | {
180 | "data": {
181 | "text/plain": [
182 | "{2023: 5000.0, 2024: 60000.0, 2025: 25000.0}"
183 | ]
184 | },
185 | "execution_count": 13,
186 | "metadata": {},
187 | "output_type": "execute_result"
188 | }
189 | ],
190 | "source": [
191 | "result=output['intermediate_steps'][-1][-1]\n",
192 | "result"
193 | ]
194 | },
195 | {
196 | "cell_type": "markdown",
197 | "metadata": {},
198 | "source": [
199 | "# Creating an Agent Using Standard Tool and Prompt"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 14,
205 | "metadata": {},
206 | "outputs": [],
207 | "source": [
208 | "problem_chain = LLMMathChain.from_llm(llm=llm)\n",
209 | "\n",
210 | "math_tool = Tool.from_function(name=\"Calculator\",func=problem_chain.run,description=\"Useful for when you need to answer questions \\\n",
211 | "about math. This tool is only for math questions and nothing else. Only input\\\n",
212 | "math expressions.\")\n",
213 | "\n",
214 | "agent = initialize_agent(\n",
215 | " tools=[math_tool],\n",
216 | " llm=llm,\n",
217 | " agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n",
218 | " verbose=False,\n",
219 | " handle_parsing_errors=True\n",
220 | ")"
221 | ]
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": 15,
226 | "metadata": {},
227 | "outputs": [],
228 | "source": [
229 | "\n",
230 | "contract={'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/2023', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'},\n",
231 | "\n",
232 | "instruction=f\"\"\"\n",
233 | "From this dictionay {contract} extract the value of each key and perform the following steps\n",
234 | "1. Get the total number of months for the given contract period. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final months in calculating the total number of months.\n",
235 | "2. Find the total number of years in this contract. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final years in calculating the total number of years.\n",
236 | "3. Get the number of months in each year. For example, if the Term_start_date is 11/1/2023 and Term_end_date is 8/1/2025, then there will be 2, 12 and 8 months in 2023, 2024 and 2025, respectively\n",
237 | "4. Get the amount corresponds to each month. This will be Contract_amount divided by total number of months for the given contract period.\n",
238 | "5. Get the amount corresponds to each year. This will be the multiplication of the amount corresponds to each month and the number of months in each year.\n",
239 | "Provide the final result in the json format where year will be key and the amount corresponds to each year will be value. Don't put addional text in the final output.\n",
240 | "\"\"\""
241 | ]
242 | },
243 | {
244 | "cell_type": "code",
245 | "execution_count": 16,
246 | "metadata": {},
247 | "outputs": [
248 | {
249 | "data": {
250 | "text/plain": [
251 | "'{\\n \"2023\": 15000,\\n \"2024\": 75000\\n}'"
252 | ]
253 | },
254 | "execution_count": 16,
255 | "metadata": {},
256 | "output_type": "execute_result"
257 | }
258 | ],
259 | "source": [
260 | "output=agent.invoke({'input':instruction})\n",
261 | "output['output']"
262 | ]
263 | },
264 | {
265 | "cell_type": "markdown",
266 | "metadata": {},
267 | "source": [
268 | "# Create an agent using python repl"
269 | ]
270 | },
271 | {
272 | "cell_type": "code",
273 | "execution_count": 17,
274 | "metadata": {},
275 | "outputs": [],
276 | "source": [
277 | "from langchain import hub\n",
278 | "from langchain_experimental.tools import PythonREPLTool\n",
279 | "tools = [PythonREPLTool()]\n"
280 | ]
281 | },
282 | {
283 | "cell_type": "code",
284 | "execution_count": 48,
285 | "metadata": {},
286 | "outputs": [],
287 | "source": [
288 | "instructions = \"\"\"You are an agent designed to write and execute python code to answer questions.\n",
289 | "You have access to a python REPL, which you can use to execute python code.\n",
290 | "If you get an error, debug your code and try again.\n",
291 | "Only use the output of your code to answer the question. \n",
292 | "You might know the answer without running any code, but you should still run the code to get the answer.\n",
293 | "User are encouraged to provide query with json data in this format.\n",
294 | "{'Sno': 1,\n",
295 | " 'Contract_Number': 'C887/36',\n",
296 | " 'Contract_Date': '11/1/2023',\n",
297 | " 'Term_start_date': '12/1/202323',\n",
298 | " 'Term_end_date': '05/31/2024',\n",
299 | " 'Contract_amount': '$90,000.00'}\n",
300 | "If the user provide the json fomated input in the query, follow the following steps for to generate the final result.\n",
301 | "1. Get the total number of months for the given contract period. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final months in calculating the total number of months.\n",
302 | "2. Find the total number of years in this contract. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final years in calculating the total number of years.\n",
303 | "3. Get the number of months in each year. For example, if the Term_start_date is 11/1/2023 and Term_end_date is 8/1/2025, then there will be 2, 12 and 8 months in 2023, 2024 and 2025, respectively\n",
304 | "4. Get the amount corresponds to each month. This will be Contract_amount divided by total number of months for the given contract period.\n",
305 | "5. Get the amount corresponds to each year. This will be the multiplication of the amount corresponds to each month and the number of months in each year.\n",
306 | "Provide the final result in the json format where year will be a key and the amount corresponds to each year will be the value. Don't put addional text in the final output.\n",
307 | "\"\"\"\n"
308 | ]
309 | },
310 | {
311 | "cell_type": "code",
312 | "execution_count": 49,
313 | "metadata": {},
314 | "outputs": [],
315 | "source": [
316 | "base_prompt = hub.pull(\"langchain-ai/openai-functions-template\")\n",
317 | "prompt = base_prompt.partial(instructions=instructions)"
318 | ]
319 | },
320 | {
321 | "cell_type": "code",
322 | "execution_count": 53,
323 | "metadata": {},
324 | "outputs": [],
325 | "source": [
326 | "agent = create_openai_functions_agent(llm, tools, prompt)\n",
327 | "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n"
328 | ]
329 | },
330 | {
331 | "cell_type": "code",
332 | "execution_count": 54,
333 | "metadata": {},
334 | "outputs": [],
335 | "source": [
336 | "query={'Sno': 1,\n",
337 | " 'Contract_Number': 'C887/36',\n",
338 | " 'Contract_Date': '11/1/2023',\n",
339 | " 'Term_start_date': '12/1/202323',\n",
340 | " 'Term_end_date': '05/31/2024',\n",
341 | " 'Contract_amount': '$90,000.00'}\n"
342 | ]
343 | },
344 | {
345 | "cell_type": "code",
346 | "execution_count": 55,
347 | "metadata": {},
348 | "outputs": [
349 | {
350 | "name": "stdout",
351 | "output_type": "stream",
352 | "text": [
353 | "\n",
354 | "\n",
355 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n"
356 | ]
357 | },
358 | {
359 | "name": "stderr",
360 | "output_type": "stream",
361 | "text": [
362 | "Python REPL can execute arbitrary code. Use with caution.\n"
363 | ]
364 | },
365 | {
366 | "name": "stdout",
367 | "output_type": "stream",
368 | "text": [
369 | "\u001b[32;1m\u001b[1;3m\n",
370 | "Invoking: `Python_REPL` with `from datetime import datetime\n",
371 | "\n",
372 | "def calculate_contract_details(contract):\n",
373 | " try:\n",
374 | " term_start = datetime.strptime(contract['Term_start_date'], '%m/%d/%Y')\n",
375 | " term_end = datetime.strptime(contract['Term_end_date'], '%m/%d/%Y')\n",
376 | " contract_amount = float(contract['Contract_amount'].replace('$', '').replace(',', ''))\n",
377 | "\n",
378 | " # Calculate total number of months\n",
379 | " total_months = (term_end.year - term_start.year) * 12 + term_end.month - term_start.month + 1\n",
380 | "\n",
381 | " # Calculate total number of years\n",
382 | " total_years = term_end.year - term_start.year + 1\n",
383 | "\n",
384 | " # Calculate number of months in each year\n",
385 | " months_in_years = {}\n",
386 | " for year in range(term_start.year, term_end.year + 1):\n",
387 | " if year == term_start.year:\n",
388 | " months_in_years[year] = 12 - term_start.month + 1\n",
389 | " elif year == term_end.year:\n",
390 | " months_in_years[year] = term_end.month\n",
391 | " else:\n",
392 | " months_in_years[year] = 12\n",
393 | "\n",
394 | " # Calculate the amount corresponds to each month\n",
395 | " monthly_amount = contract_amount / total_months\n",
396 | "\n",
397 | " # Calculate the amount corresponds to each year\n",
398 | " yearly_amounts = {year: months * monthly_amount for year, months in months_in_years.items()}\n",
399 | "\n",
400 | " return yearly_amounts\n",
401 | " except ValueError as e:\n",
402 | " return {'error': str(e)}\n",
403 | "\n",
404 | "contract_data = {'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/202323', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'}\n",
405 | "print(calculate_contract_details(contract_data))`\n",
406 | "\n",
407 | "\n",
408 | "\u001b[0m\u001b[36;1m\u001b[1;3m{'error': 'unconverted data remains: 23'}\n",
409 | "\u001b[0m\u001b[32;1m\u001b[1;3m\n",
410 | "Invoking: `Python_REPL` with `from datetime import datetime\n",
411 | "\n",
412 | "def calculate_contract_details(contract):\n",
413 | " try:\n",
414 | " # Correct the term start date format\n",
415 | " term_start_str = contract['Term_start_date']\n",
416 | " term_start_str = term_start_str[:-2] + term_start_str[-4:]\n",
417 | " term_start = datetime.strptime(term_start_str, '%m/%d/%Y')\n",
418 | " term_end = datetime.strptime(contract['Term_end_date'], '%m/%d/%Y')\n",
419 | " contract_amount = float(contract['Contract_amount'].replace('$', '').replace(',', ''))\n",
420 | "\n",
421 | " # Calculate total number of months\n",
422 | " total_months = (term_end.year - term_start.year) * 12 + term_end.month - term_start.month + 1\n",
423 | "\n",
424 | " # Calculate total number of years\n",
425 | " total_years = term_end.year - term_start.year + 1\n",
426 | "\n",
427 | " # Calculate number of months in each year\n",
428 | " months_in_years = {}\n",
429 | " for year in range(term_start.year, term_end.year + 1):\n",
430 | " if year == term_start.year:\n",
431 | " months_in_years[year] = 12 - term_start.month + 1\n",
432 | " elif year == term_end.year:\n",
433 | " months_in_years[year] = term_end.month\n",
434 | " else:\n",
435 | " months_in_years[year] = 12\n",
436 | "\n",
437 | " # Calculate the amount corresponds to each month\n",
438 | " monthly_amount = contract_amount / total_months\n",
439 | "\n",
440 | " # Calculate the amount corresponds to each year\n",
441 | " yearly_amounts = {year: months * monthly_amount for year, months in months_in_years.items()}\n",
442 | "\n",
443 | " return yearly_amounts\n",
444 | " except ValueError as e:\n",
445 | " return {'error': str(e)}\n",
446 | "\n",
447 | "contract_data = {'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/202323', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'}\n",
448 | "print(calculate_contract_details(contract_data))`\n",
449 | "\n",
450 | "\n",
451 | "\u001b[0m\u001b[36;1m\u001b[1;3m{'error': 'unconverted data remains: 2323'}\n",
452 | "\u001b[0m\u001b[32;1m\u001b[1;3m\n",
453 | "Invoking: `Python_REPL` with `from datetime import datetime\n",
454 | "\n",
455 | "def calculate_contract_details(contract):\n",
456 | " try:\n",
457 | " # Correct the term start date format\n",
458 | " term_start_str = contract['Term_start_date'].replace('23', '', 1) # Assuming typo in year\n",
459 | " term_start = datetime.strptime(term_start_str, '%m/%d/%Y')\n",
460 | " term_end = datetime.strptime(contract['Term_end_date'], '%m/%d/%Y')\n",
461 | " contract_amount = float(contract['Contract_amount'].replace('$', '').replace(',', ''))\n",
462 | "\n",
463 | " # Calculate total number of months\n",
464 | " total_months = (term_end.year - term_start.year) * 12 + term_end.month - term_start.month + 1\n",
465 | "\n",
466 | " # Calculate total number of years\n",
467 | " total_years = term_end.year - term_start.year + 1\n",
468 | "\n",
469 | " # Calculate number of months in each year\n",
470 | " months_in_years = {}\n",
471 | " for year in range(term_start.year, term_end.year + 1):\n",
472 | " if year == term_start.year:\n",
473 | " months_in_years[year] = 12 - term_start.month + 1\n",
474 | " elif year == term_end.year:\n",
475 | " months_in_years[year] = term_end.month\n",
476 | " else:\n",
477 | " months_in_years[year] = 12\n",
478 | "\n",
479 | " # Calculate the amount corresponds to each month\n",
480 | " monthly_amount = contract_amount / total_months\n",
481 | "\n",
482 | " # Calculate the amount corresponds to each year\n",
483 | " yearly_amounts = {year: months * monthly_amount for year, months in months_in_years.items()}\n",
484 | "\n",
485 | " return yearly_amounts\n",
486 | " except ValueError as e:\n",
487 | " return {'error': str(e)}\n",
488 | "\n",
489 | "contract_data = {'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/202323', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'}\n",
490 | "print(calculate_contract_details(contract_data))`\n",
491 | "\n",
492 | "\n",
493 | "\u001b[0m\u001b[36;1m\u001b[1;3m{2023: 15000.0, 2024: 75000.0}\n",
494 | "\u001b[0m\u001b[32;1m\u001b[1;3m```json\n",
495 | "{\n",
496 | " \"2023\": 15000.0,\n",
497 | " \"2024\": 75000.0\n",
498 | "}\n",
499 | "```\u001b[0m\n",
500 | "\n",
501 | "\u001b[1m> Finished chain.\u001b[0m\n"
502 | ]
503 | },
504 | {
505 | "data": {
506 | "text/plain": [
507 | "'```json\\n{\\n \"2023\": 15000.0,\\n \"2024\": 75000.0\\n}\\n```'"
508 | ]
509 | },
510 | "execution_count": 55,
511 | "metadata": {},
512 | "output_type": "execute_result"
513 | }
514 | ],
515 | "source": [
516 | "\n",
517 | "result=agent_executor.invoke({\"input\": query})\n",
518 | "\n",
519 | "result['output']"
520 | ]
521 | },
522 | {
523 | "cell_type": "code",
524 | "execution_count": 57,
525 | "metadata": {},
526 | "outputs": [
527 | {
528 | "data": {
529 | "text/plain": [
530 | "'```json\\n{\\n \"2023\": 15000.0,\\n \"2024\": 75000.0\\n}\\n```'"
531 | ]
532 | },
533 | "execution_count": 57,
534 | "metadata": {},
535 | "output_type": "execute_result"
536 | }
537 | ],
538 | "source": [
539 | "result['output']"
540 | ]
541 | },
542 | {
543 | "cell_type": "markdown",
544 | "metadata": {},
545 | "source": [
546 | "##"
547 | ]
548 | }
549 | ],
550 | "metadata": {
551 | "kernelspec": {
552 | "display_name": "langchain",
553 | "language": "python",
554 | "name": "python3"
555 | },
556 | "language_info": {
557 | "codemirror_mode": {
558 | "name": "ipython",
559 | "version": 3
560 | },
561 | "file_extension": ".py",
562 | "mimetype": "text/x-python",
563 | "name": "python",
564 | "nbconvert_exporter": "python",
565 | "pygments_lexer": "ipython3",
566 | "version": "3.12.2"
567 | }
568 | },
569 | "nbformat": 4,
570 | "nbformat_minor": 2
571 | }
572 |
--------------------------------------------------------------------------------
/DemoRAG/newagen3.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 1,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "from langchain_openai import ChatOpenAI\n",
10 | "from typing import List\n",
11 | "from typing import TypedDict, Annotated, Sequence\n",
12 | "import os, operator, json\n",
13 | "from langchain_experimental.utilities import PythonREPL\n",
14 | "from langchain_core.tools import tool\n",
15 | "from langchain.agents import Tool, initialize_agent\n",
16 | "from langchain.memory import ConversationBufferMemory,ConversationBufferWindowMemory\n",
17 | "from langchain.chains import LLMMathChain, LLMChain\n",
18 | "from langchain.agents.agent_types import AgentType\n",
19 | "from langchain.agents import create_openai_functions_agent\n",
20 | "from langchain.agents import AgentExecutor\n",
21 | "import time\n",
22 | "\n",
23 | "\n",
24 | "OPENAI_API_KEY=\"sk-vppxxxLaft8GdCx4PxxxXT3BlxxFJWGVSIWWCtErf3tWZgz5x\"\n",
25 | "\n",
26 | "os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY"
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": 2,
32 | "metadata": {},
33 | "outputs": [],
34 | "source": [
35 | "contract = \"\"\"{\"Sno\": 1,\n",
36 | " \"Contract_Number\": \"C887/36\",\n",
37 | " \"Contract_Date\": \"11/1/2023\",\n",
38 | " \"Term_start_date\": \"12/1/2023\",\n",
39 | " \"Term_end_date\": \"05/31/2025\",\n",
40 | " \"Contract_amount\": \"$90,000.00\"}\"\"\""
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 3,
46 | "metadata": {},
47 | "outputs": [],
48 | "source": [
49 | "llm = ChatOpenAI(model=\"gpt-4-1106-preview\")"
50 | ]
51 | },
52 | {
53 | "cell_type": "markdown",
54 | "metadata": {},
55 | "source": [
56 | "# Create Agent Using Customized Function"
57 | ]
58 | },
59 | {
60 | "cell_type": "code",
61 | "execution_count": 10,
62 | "metadata": {},
63 | "outputs": [],
64 | "source": [
65 | "from datetime import datetime\n",
66 | "def getting_yearly_amount(contract):\n",
67 | "#def getting_yearly_amount(contract=f\"{contract}\"):\n",
68 | " try:\n",
69 | " contract = json.loads(contract)\n",
70 | " except json.JSONDecodeError as e:\n",
71 | " print('Failed to decode coefficients:', e)\n",
72 | " return None\n",
73 | " # Extracting required information from the contract\n",
74 | " term_start_date = datetime.strptime(contract['Term_start_date'], '%m/%d/%Y')\n",
75 | " term_end_date = datetime.strptime(contract['Term_end_date'], '%m/%d/%Y')\n",
76 | " contract_amount = float(contract['Contract_amount'].replace('$', '').replace(',', ''))\n",
77 | "\n",
78 | " # Calculating the total number of months for the contract period\n",
79 | " total_months = (term_end_date.year - term_start_date.year) * 12 + (term_end_date.month - term_start_date.month + 1)\n",
80 | "\n",
81 | " # Finding the total number of years\n",
82 | " total_years = term_end_date.year - term_start_date.year + 1\n",
83 | "\n",
84 | " # Getting the number of months in each year\n",
85 | " months_per_year = {}\n",
86 | " for year in range(term_start_date.year, term_end_date.year + 1):\n",
87 | " if year == term_start_date.year:\n",
88 | " months_per_year[year] = 12 - term_start_date.month + 1\n",
89 | " elif year == term_end_date.year:\n",
90 | " months_per_year[year] = term_end_date.month\n",
91 | " else:\n",
92 | " months_per_year[year] = 12\n",
93 | "\n",
94 | " # Calculating the amount corresponds to each month\n",
95 | " amount_per_month = contract_amount / total_months\n",
96 | "\n",
97 | " # Calculating the amount corresponds to each year\n",
98 | " amount_per_year = {year: months * amount_per_month for year, months in months_per_year.items()}\n",
99 | "\n",
100 | " return amount_per_year\n",
101 | "\n",
102 | "equation_tool = Tool(name='Yearly Amount Estimation', func=getting_yearly_amount, description=\"Useful for data provided in the json format and estimating amount assciated for each year.\")\n",
103 | "\n",
104 | "tools = [equation_tool]\n",
105 | "\n",
106 | "memory = ConversationBufferWindowMemory(memory_key=\"chat_history\", k=3, input_key=\"input\", output_key=\"output\",return_messages=True) \n",
107 | "\n",
108 | "agent_parameters = {\n",
109 | " 'agent':'chat-conversational-react-description',\n",
110 | " 'tools':tools,\n",
111 | " 'llm':llm,\n",
112 | " 'verbose':True,\n",
113 | " 'max_iterations':4,\n",
114 | " 'return_intermediate_steps':True,\n",
115 | " 'early_stopping_method':'generate',\n",
116 | " \n",
117 | " 'memory':memory\n",
118 | "}\n",
119 | "\n",
120 | "agent = initialize_agent(**agent_parameters)\n"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": 11,
126 | "metadata": {},
127 | "outputs": [],
128 | "source": [
129 | "contract = \"\"\"{\"Sno\": 1,\n",
130 | " \"Contract_Number\": \"C887/36\",\n",
131 | " \"Contract_Date\": \"11/1/2023\",\n",
132 | " \"Term_start_date\": \"12/1/2023\",\n",
133 | " \"Term_end_date\": \"05/31/2025\",\n",
134 | " \"Contract_amount\": \"$90,000.00\"}\"\"\""
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "execution_count": 12,
140 | "metadata": {},
141 | "outputs": [
142 | {
143 | "name": "stdout",
144 | "output_type": "stream",
145 | "text": [
146 | "CPU times: user 2 µs, sys: 1e+03 ns, total: 3 µs\n",
147 | "Wall time: 17.9 µs\n",
148 | "\n",
149 | "\n",
150 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
151 | "\u001b[32;1m\u001b[1;3m```json\n",
152 | "{\n",
153 | " \"action\": \"Yearly Amount Estimation\",\n",
154 | " \"action_input\": \"{\\\"Sno\\\": 1, \\\"Contract_Number\\\": \\\"C887/36\\\", \\\"Contract_Date\\\": \\\"11/1/2023\\\", \\\"Term_start_date\\\": \\\"12/1/2023\\\", \\\"Term_end_date\\\": \\\"05/31/2025\\\", \\\"Contract_amount\\\": \\\"$90,000.00\\\"}\"\n",
155 | "}\n",
156 | "```\u001b[0m\n",
157 | "Observation: \u001b[36;1m\u001b[1;3m{2023: 5000.0, 2024: 60000.0, 2025: 25000.0}\u001b[0m\n",
158 | "Thought:\u001b[32;1m\u001b[1;3m```json\n",
159 | "{\n",
160 | " \"action\": \"Final Answer\",\n",
161 | " \"action_input\": \"The estimated contract amount allocated for each year is as follows: For the year 2023, the amount is $5,000.00; for the year 2024, it's $60,000.00; and for the year 2025, the amount is $25,000.00.\"\n",
162 | "}\n",
163 | "```\u001b[0m\n",
164 | "\n",
165 | "\u001b[1m> Finished chain.\u001b[0m\n"
166 | ]
167 | }
168 | ],
169 | "source": [
170 | "%time\n",
171 | "output= agent.invoke({\"input\":f\"get each year amount from the given contract {contract} \"})\n"
172 | ]
173 | },
174 | {
175 | "cell_type": "code",
176 | "execution_count": 13,
177 | "metadata": {},
178 | "outputs": [
179 | {
180 | "data": {
181 | "text/plain": [
182 | "{2023: 5000.0, 2024: 60000.0, 2025: 25000.0}"
183 | ]
184 | },
185 | "execution_count": 13,
186 | "metadata": {},
187 | "output_type": "execute_result"
188 | }
189 | ],
190 | "source": [
191 | "result=output['intermediate_steps'][-1][-1]\n",
192 | "result"
193 | ]
194 | },
195 | {
196 | "cell_type": "markdown",
197 | "metadata": {},
198 | "source": [
199 | "# Creating an Agent Using Standard Tool and Prompt"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 14,
205 | "metadata": {},
206 | "outputs": [],
207 | "source": [
208 | "problem_chain = LLMMathChain.from_llm(llm=llm)\n",
209 | "\n",
210 | "math_tool = Tool.from_function(name=\"Calculator\",func=problem_chain.run,description=\"Useful for when you need to answer questions \\\n",
211 | "about math. This tool is only for math questions and nothing else. Only input\\\n",
212 | "math expressions.\")\n",
213 | "\n",
214 | "agent = initialize_agent(\n",
215 | " tools=[math_tool],\n",
216 | " llm=llm,\n",
217 | " agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n",
218 | " verbose=False,\n",
219 | " handle_parsing_errors=True\n",
220 | ")"
221 | ]
222 | },
223 | {
224 | "cell_type": "code",
225 | "execution_count": 15,
226 | "metadata": {},
227 | "outputs": [],
228 | "source": [
229 | "\n",
230 | "contract={'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/2023', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'},\n",
231 | "\n",
232 | "instruction=f\"\"\"\n",
233 | "From this dictionay {contract} extract the value of each key and perform the following steps\n",
234 | "1. Get the total number of months for the given contract period. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final months in calculating the total number of months.\n",
235 | "2. Find the total number of years in this contract. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final years in calculating the total number of years.\n",
236 | "3. Get the number of months in each year. For example, if the Term_start_date is 11/1/2023 and Term_end_date is 8/1/2025, then there will be 2, 12 and 8 months in 2023, 2024 and 2025, respectively\n",
237 | "4. Get the amount corresponds to each month. This will be Contract_amount divided by total number of months for the given contract period.\n",
238 | "5. Get the amount corresponds to each year. This will be the multiplication of the amount corresponds to each month and the number of months in each year.\n",
239 | "Provide the final result in the json format where year will be key and the amount corresponds to each year will be value. Don't put addional text in the final output.\n",
240 | "\"\"\""
241 | ]
242 | },
243 | {
244 | "cell_type": "code",
245 | "execution_count": 16,
246 | "metadata": {},
247 | "outputs": [
248 | {
249 | "data": {
250 | "text/plain": [
251 | "'{\\n \"2023\": 15000,\\n \"2024\": 75000\\n}'"
252 | ]
253 | },
254 | "execution_count": 16,
255 | "metadata": {},
256 | "output_type": "execute_result"
257 | }
258 | ],
259 | "source": [
260 | "output=agent.invoke({'input':instruction})\n",
261 | "output['output']"
262 | ]
263 | },
264 | {
265 | "cell_type": "markdown",
266 | "metadata": {},
267 | "source": [
268 | "# Create an agent using python repl"
269 | ]
270 | },
271 | {
272 | "cell_type": "code",
273 | "execution_count": 20,
274 | "metadata": {},
275 | "outputs": [],
276 | "source": [
277 | "from langchain import hub\n",
278 | "from langchain_experimental.tools import PythonREPLTool\n",
279 | "tools = [PythonREPLTool()]\n"
280 | ]
281 | },
282 | {
283 | "cell_type": "code",
284 | "execution_count": 21,
285 | "metadata": {},
286 | "outputs": [],
287 | "source": [
288 | "instructions = \"\"\"You are an agent designed to write and execute python code to answer questions.\n",
289 | "You have access to a python REPL, which you can use to execute python code.\n",
290 | "If you get an error, debug your code and try again.\n",
291 | "Only use the output of your code to answer the question. \n",
292 | "You might know the answer without running any code, but you should still run the code to get the answer.\n",
293 | "User are encouraged to provide query with json data in this format.\n",
294 | "{'Sno': 1,\n",
295 | " 'Contract_Number': 'C887/36',\n",
296 | " 'Contract_Date': '11/1/2023',\n",
297 | " 'Term_start_date': '12/1/202323',\n",
298 | " 'Term_end_date': '05/31/2024',\n",
299 | " 'Contract_amount': '$90,000.00'}\n",
300 | "If the user provide the json fomated input in the query, follow the following steps for to generate the final result.\n",
301 | "1. Get the total number of months for the given contract period. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final months in calculating the total number of months.\n",
302 | "2. Find the total number of years in this contract. The beginning of the contract is Term_start_date and the end of the contract is Term_end_date. Include both the initial and final years in calculating the total number of years.\n",
303 | "3. Get the number of months in each year. For example, if the Term_start_date is 11/1/2023 and Term_end_date is 8/1/2025, then there will be 2, 12 and 8 months in 2023, 2024 and 2025, respectively\n",
304 | "4. Get the amount corresponds to each month. This will be Contract_amount divided by total number of months for the given contract period.\n",
305 | "5. Get the amount corresponds to each year. This will be the multiplication of the amount corresponds to each month and the number of months in each year.\n",
306 | "Provide the final result in the json format where year will be a key and the amount corresponds to each year will be the value. Don't put addional text in the final output.\n",
307 | "\"\"\"\n"
308 | ]
309 | },
310 | {
311 | "cell_type": "code",
312 | "execution_count": 22,
313 | "metadata": {},
314 | "outputs": [],
315 | "source": [
316 | "base_prompt = hub.pull(\"langchain-ai/openai-functions-template\")\n",
317 | "prompt = base_prompt.partial(instructions=instructions)"
318 | ]
319 | },
320 | {
321 | "cell_type": "code",
322 | "execution_count": 23,
323 | "metadata": {},
324 | "outputs": [],
325 | "source": [
326 | "agent = create_openai_functions_agent(llm, tools, prompt)\n",
327 | "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n"
328 | ]
329 | },
330 | {
331 | "cell_type": "code",
332 | "execution_count": 24,
333 | "metadata": {},
334 | "outputs": [],
335 | "source": [
336 | "query={'Sno': 1,\n",
337 | " 'Contract_Number': 'C887/36',\n",
338 | " 'Contract_Date': '11/1/2023',\n",
339 | " 'Term_start_date': '12/1/202323',\n",
340 | " 'Term_end_date': '05/31/2024',\n",
341 | " 'Contract_amount': '$90,000.00'}\n"
342 | ]
343 | },
344 | {
345 | "cell_type": "code",
346 | "execution_count": 25,
347 | "metadata": {},
348 | "outputs": [
349 | {
350 | "name": "stdout",
351 | "output_type": "stream",
352 | "text": [
353 | "\n",
354 | "\n",
355 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n"
356 | ]
357 | },
358 | {
359 | "name": "stderr",
360 | "output_type": "stream",
361 | "text": [
362 | "Python REPL can execute arbitrary code. Use with caution.\n"
363 | ]
364 | },
365 | {
366 | "name": "stdout",
367 | "output_type": "stream",
368 | "text": [
369 | "\u001b[32;1m\u001b[1;3m\n",
370 | "Invoking: `Python_REPL` with `from datetime import datetime\n",
371 | "\n",
372 | "# Input data\n",
373 | "contract_data = {'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/202323', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'}\n",
374 | "\n",
375 | "# Correct the Term_start_date\n",
376 | "contract_data['Term_start_date'] = '12/1/2023'\n",
377 | "\n",
378 | "# Convert dates to datetime objects\n",
379 | "start_date = datetime.strptime(contract_data['Term_start_date'], '%m/%d/%Y')\n",
380 | "end_date = datetime.strptime(contract_data['Term_end_date'], '%m/%d/%Y')\n",
381 | "\n",
382 | "# Calculate the total number of months\n",
383 | "total_months = (end_date.year - start_date.year) * 12 + end_date.month - start_date.month + 1\n",
384 | "print(total_months)`\n",
385 | "\n",
386 | "\n",
387 | "\u001b[0m\u001b[36;1m\u001b[1;3m6\n",
388 | "\u001b[0m\u001b[32;1m\u001b[1;3m\n",
389 | "Invoking: `Python_REPL` with `# Calculate the total number of years\n",
390 | "start_year = start_date.year\n",
391 | "end_year = end_date.year\n",
392 | "total_years = end_year - start_year + 1\n",
393 | "print(total_years)`\n",
394 | "\n",
395 | "\n",
396 | "\u001b[0m\u001b[36;1m\u001b[1;3m2\n",
397 | "\u001b[0m\u001b[32;1m\u001b[1;3m\n",
398 | "Invoking: `Python_REPL` with `# Calculate the number of months in each year\n",
399 | "months_in_years = {}\n",
400 | "for year in range(start_year, end_year + 1):\n",
401 | " if year == start_year:\n",
402 | " months_in_years[year] = 12 - start_date.month + 1\n",
403 | " elif year == end_year:\n",
404 | " months_in_years[year] = end_date.month\n",
405 | " else:\n",
406 | " months_in_years[year] = 12\n",
407 | "print(months_in_years)`\n",
408 | "\n",
409 | "\n",
410 | "\u001b[0m\u001b[36;1m\u001b[1;3m{2023: 1, 2024: 5}\n",
411 | "\u001b[0m\u001b[32;1m\u001b[1;3m\n",
412 | "Invoking: `Python_REPL` with `# Get the amount corresponds to each month\n",
413 | "contract_amount = float(contract_data['Contract_amount'].replace('$', '').replace(',', ''))\n",
414 | "amount_per_month = contract_amount / total_months\n",
415 | "print(amount_per_month)`\n",
416 | "\n",
417 | "\n",
418 | "\u001b[0m\u001b[36;1m\u001b[1;3m15000.0\n",
419 | "\u001b[0m\u001b[32;1m\u001b[1;3m\n",
420 | "Invoking: `Python_REPL` with `# Get the amount corresponds to each year\n",
421 | "amount_per_year = {}\n",
422 | "for year, months in months_in_years.items():\n",
423 | " amount_per_year[year] = months * amount_per_month\n",
424 | "print(amount_per_year)`\n",
425 | "\n",
426 | "\n",
427 | "\u001b[0m\u001b[36;1m\u001b[1;3m{2023: 15000.0, 2024: 75000.0}\n",
428 | "\u001b[0m\u001b[32;1m\u001b[1;3m```json\n",
429 | "{\n",
430 | " \"2023\": 15000.0,\n",
431 | " \"2024\": 75000.0\n",
432 | "}\n",
433 | "```\u001b[0m\n",
434 | "\n",
435 | "\u001b[1m> Finished chain.\u001b[0m\n"
436 | ]
437 | },
438 | {
439 | "data": {
440 | "text/plain": [
441 | "'```json\\n{\\n \"2023\": 15000.0,\\n \"2024\": 75000.0\\n}\\n```'"
442 | ]
443 | },
444 | "execution_count": 25,
445 | "metadata": {},
446 | "output_type": "execute_result"
447 | }
448 | ],
449 | "source": [
450 | "\n",
451 | "result=agent_executor.invoke({\"input\": query})\n",
452 | "\n",
453 | "result['output']"
454 | ]
455 | },
456 | {
457 | "cell_type": "code",
458 | "execution_count": 26,
459 | "metadata": {},
460 | "outputs": [
461 | {
462 | "data": {
463 | "text/plain": [
464 | "'```json\\n{\\n \"2023\": 15000.0,\\n \"2024\": 75000.0\\n}\\n```'"
465 | ]
466 | },
467 | "execution_count": 26,
468 | "metadata": {},
469 | "output_type": "execute_result"
470 | }
471 | ],
472 | "source": [
473 | "result['output']"
474 | ]
475 | },
476 | {
477 | "cell_type": "code",
478 | "execution_count": 30,
479 | "metadata": {},
480 | "outputs": [],
481 | "source": [
482 | "# check this out: https://pub.towardsai.net/use-langchain-to-extract-a-dictionary-from-text-3fca094d85d\n",
483 | "# from langchain.output_parsers import ResponseSchema\n",
484 | "# from langchain.output_parsers import StructuredOutputParser\n",
485 | "\n",
486 | "# year_schema = ResponseSchema(name=\"year\",\n",
487 | "# description=\"year covered in contract\")\n",
488 | "\n",
489 | "# amount_schema = ResponseSchema(name=\"amount\",\n",
490 | "# description=\"amount covered in each year\")\n",
491 | "\n",
492 | "# response_schemas = [year_schema, amount_schema]\n",
493 | " \n",
494 | "\n",
495 | "# output_parser = StructuredOutputParser.from_response_schemas(response_schemas)\n",
496 | "\n",
497 | "# output_dict = output_parser.parse(result['output'])"
498 | ]
499 | },
500 | {
501 | "cell_type": "markdown",
502 | "metadata": {},
503 | "source": [
504 | "## Using Standard Tool"
505 | ]
506 | },
507 | {
508 | "cell_type": "code",
509 | "execution_count": 61,
510 | "metadata": {},
511 | "outputs": [],
512 | "source": [
513 | "from langchain.agents import tool\n",
514 | "from datetime import datetime\n",
515 | "\n",
516 | "from langchain_openai import ChatOpenAI\n",
517 | "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
518 | "\n",
519 | "\n",
520 | "OPENAI_API_KEY=\"sk-xxxEQr0Lxxx8GdCx4PrXT3BxxkFJWGVSIWWCtErf3tWZgz5x\"\n",
521 | "\n",
522 | "os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY\n",
523 | "\n",
524 | "llm = ChatOpenAI(model=\"gpt-4-1106-preview\", temperature=0)\n"
525 | ]
526 | },
527 | {
528 | "cell_type": "code",
529 | "execution_count": 62,
530 | "metadata": {},
531 | "outputs": [],
532 | "source": [
533 | "@tool\n",
534 | "def getting_yearly_amount(contract) -> dict:\n",
535 | " \"\"\" Useful for doing mathematical calculation\"\"\"\n",
536 | " # try:\n",
537 | " # contract = json.loads(contract)\n",
538 | " # except json.JSONDecodeError as e:\n",
539 | " # print('Failed to decode coefficients:', e)\n",
540 | " # return None\n",
541 | " # Extracting required information from the contract\n",
542 | " term_start_date = datetime.strptime(contract['Term_start_date'], '%m/%d/%Y')\n",
543 | " term_end_date = datetime.strptime(contract['Term_end_date'], '%m/%d/%Y')\n",
544 | " contract_amount = float(contract['Contract_amount'].replace('$', '').replace(',', ''))\n",
545 | "\n",
546 | " # Calculating the total number of months for the contract period\n",
547 | " total_months = (term_end_date.year - term_start_date.year) * 12 + (term_end_date.month - term_start_date.month + 1)\n",
548 | "\n",
549 | " # Finding the total number of years\n",
550 | " total_years = term_end_date.year - term_start_date.year + 1\n",
551 | "\n",
552 | " # Getting the number of months in each year\n",
553 | " months_per_year = {}\n",
554 | " for year in range(term_start_date.year, term_end_date.year + 1):\n",
555 | " if year == term_start_date.year:\n",
556 | " months_per_year[year] = 12 - term_start_date.month + 1\n",
557 | " elif year == term_end_date.year:\n",
558 | " months_per_year[year] = term_end_date.month\n",
559 | " else:\n",
560 | " months_per_year[year] = 12\n",
561 | "\n",
562 | " # Calculating the amount corresponds to each month\n",
563 | " amount_per_month = contract_amount / total_months\n",
564 | "\n",
565 | " # Calculating the amount corresponds to each year\n",
566 | " amount_per_year = {year: months * amount_per_month for year, months in months_per_year.items()}\n",
567 | "\n",
568 | " return amount_per_year\n"
569 | ]
570 | },
571 | {
572 | "cell_type": "code",
573 | "execution_count": 63,
574 | "metadata": {},
575 | "outputs": [],
576 | "source": [
577 | "tools = [getting_yearly_amount]\n",
578 | "\n",
579 | "extract_messages = lambda x: x[\"messages\"]\n",
580 | "\n",
581 | "prompt = ChatPromptTemplate.from_messages(\n",
582 | " [\n",
583 | " (\n",
584 | " \"system\",\n",
585 | " \"You are very powerful assistant, but don't know current events\",\n",
586 | " ),\n",
587 | " (\"user\", \"{input}\"),\n",
588 | " MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n",
589 | " ]\n",
590 | ")\n",
591 | "\n",
592 | "llm_with_tools = llm.bind_tools(tools)\n",
593 | "\n",
594 | "\n",
595 | "from langchain.agents.format_scratchpad.openai_tools import (\n",
596 | " format_to_openai_tool_messages,\n",
597 | ")\n",
598 | "from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser\n",
599 | "\n",
600 | "agent = (\n",
601 | " {\n",
602 | " \"input\": lambda x: x[\"input\"],\n",
603 | " \"agent_scratchpad\": lambda x: format_to_openai_tool_messages(\n",
604 | " x[\"intermediate_steps\"]\n",
605 | " ),\n",
606 | " \"messages\": extract_messages, \n",
607 | " }\n",
608 | " | prompt\n",
609 | " | llm_with_tools\n",
610 | " | OpenAIToolsAgentOutputParser()\n",
611 | ")\n",
612 | "from langchain.agents import AgentExecutor\n",
613 | "\n",
614 | "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n"
615 | ]
616 | },
617 | {
618 | "cell_type": "code",
619 | "execution_count": 64,
620 | "metadata": {},
621 | "outputs": [],
622 | "source": [
623 | "contract={'Sno': 1,\n",
624 | " 'Contract_Number': 'C887/36',\n",
625 | " 'Contract_Date': '11/1/2023',\n",
626 | " 'Term_start_date': '12/1/2023',\n",
627 | " 'Term_end_date': '05/31/2024',\n",
628 | " 'Contract_amount': '$90,000.00'}\n"
629 | ]
630 | },
631 | {
632 | "cell_type": "code",
633 | "execution_count": 65,
634 | "metadata": {},
635 | "outputs": [
636 | {
637 | "name": "stdout",
638 | "output_type": "stream",
639 | "text": [
640 | "\n",
641 | "\n",
642 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
643 | "\u001b[32;1m\u001b[1;3m\n",
644 | "Invoking: `getting_yearly_amount` with `{'contract': {'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/2023', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'}}`\n",
645 | "\n",
646 | "\n",
647 | "\u001b[0m\u001b[36;1m\u001b[1;3m{2023: 15000.0, 2024: 75000.0}\u001b[0m\u001b[32;1m\u001b[1;3mThe contract with the number C887/36, which has a total contract amount of $90,000.00, is allocated as follows:\n",
648 | "\n",
649 | "- For the year 2023, the amount is $15,000.00.\n",
650 | "- For the year 2024, the amount is $75,000.00.\u001b[0m\n",
651 | "\n",
652 | "\u001b[1m> Finished chain.\u001b[0m\n"
653 | ]
654 | }
655 | ],
656 | "source": [
657 | "result=agent_executor.invoke({'input':contract, 'messages':[], 'agent_scratchpad':[]})"
658 | ]
659 | },
660 | {
661 | "cell_type": "code",
662 | "execution_count": 66,
663 | "metadata": {},
664 | "outputs": [
665 | {
666 | "data": {
667 | "text/plain": [
668 | "{'input': {'Sno': 1,\n",
669 | " 'Contract_Number': 'C887/36',\n",
670 | " 'Contract_Date': '11/1/2023',\n",
671 | " 'Term_start_date': '12/1/2023',\n",
672 | " 'Term_end_date': '05/31/2024',\n",
673 | " 'Contract_amount': '$90,000.00'},\n",
674 | " 'messages': [],\n",
675 | " 'agent_scratchpad': [],\n",
676 | " 'output': 'The contract with the number C887/36, which has a total contract amount of $90,000.00, is allocated as follows:\\n\\n- For the year 2023, the amount is $15,000.00.\\n- For the year 2024, the amount is $75,000.00.'}"
677 | ]
678 | },
679 | "execution_count": 66,
680 | "metadata": {},
681 | "output_type": "execute_result"
682 | }
683 | ],
684 | "source": [
685 | "result"
686 | ]
687 | },
688 | {
689 | "cell_type": "code",
690 | "execution_count": 67,
691 | "metadata": {},
692 | "outputs": [
693 | {
694 | "name": "stdout",
695 | "output_type": "stream",
696 | "text": [
697 | "The contract with the number C887/36, which has a total contract amount of $90,000.00, is allocated as follows:\n",
698 | "\n",
699 | "- For the year 2023, the amount is $15,000.00.\n",
700 | "- For the year 2024, the amount is $75,000.00.\n"
701 | ]
702 | }
703 | ],
704 | "source": [
705 | "print(result['output'])"
706 | ]
707 | }
708 | ],
709 | "metadata": {
710 | "kernelspec": {
711 | "display_name": "langchain",
712 | "language": "python",
713 | "name": "python3"
714 | },
715 | "language_info": {
716 | "codemirror_mode": {
717 | "name": "ipython",
718 | "version": 3
719 | },
720 | "file_extension": ".py",
721 | "mimetype": "text/x-python",
722 | "name": "python",
723 | "nbconvert_exporter": "python",
724 | "pygments_lexer": "ipython3",
725 | "version": "3.12.2"
726 | }
727 | },
728 | "nbformat": 4,
729 | "nbformat_minor": 2
730 | }
731 |
--------------------------------------------------------------------------------
/DemoRAG/newagen_onlyfunction.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 7,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "from langchain_openai import ChatOpenAI\n",
10 | "from typing import List\n",
11 | "from typing import TypedDict, Annotated, Sequence\n",
12 | "import os, operator, json\n",
13 | "from langchain_experimental.utilities import PythonREPL\n",
14 | "from langchain_core.tools import tool\n",
15 | "from langchain.agents import Tool, initialize_agent\n",
16 | "from langchain.memory import ConversationBufferMemory,ConversationBufferWindowMemory\n",
17 | "from langchain.chains import LLMMathChain, LLMChain\n",
18 | "from langchain.agents.agent_types import AgentType\n",
19 | "from langchain.agents import create_openai_functions_agent\n",
20 | "from langchain.agents import AgentExecutor\n",
21 | "import time\n",
22 | "from dateutil import parser\n",
23 | "from datetime import datetime\n",
24 | "\n",
25 | "\n",
26 | "OPENAI_API_KEY=\"sk-...\"\n",
27 | "\n",
28 | "os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY"
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": 8,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "llm = ChatOpenAI(model=\"gpt-4-1106-preview\")"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": 9,
43 | "metadata": {},
44 | "outputs": [],
45 | "source": [
46 | "# Redefining the contract data as a JSON string\n",
47 | "contract1 = \"\"\"{\"Sno\": 1,\n",
48 | " \"Contract_Number\": \"C887/36\",\n",
49 | " \"Contract_Date\": \"11/1/2023\",\n",
50 | " \"Term_start_date\": \"12/1/2023\",\n",
51 | " \"Term_end_date\": \"05/31/2025\",\n",
52 | " \"Contract_amount\": \"$90,000.00\"}\"\"\"\n",
53 | "\n",
54 | "\n",
55 | "contract2 = \"\"\"{\"Sno\": 1,\n",
56 | " \"Contract_Number\": \"C887/36\",\n",
57 | " \"Contract_Date\": \"11/1/2023\",\n",
58 | " \"Term_start_date\": \"12/1/2023\",\n",
59 | " \"Term_end_date\": \"18\",\n",
60 | " \"Contract_amount\": \"$90,000.00\"}\"\"\"\n",
61 | "\n",
62 | "\n",
63 | "contract3 = \"\"\"{\"Sno\": 1,\n",
64 | " \"Contract_Number\": \"C887/36\",\n",
65 | " \"Contract_Date\": \"11/1/2023\",\n",
66 | " \"Term_start_date\": \"12/1/2023\",\n",
67 | " \"Term_end_date\": \"18\",\n",
68 | " \"Contract_amount\": [{\"item 1\" : \"SD Card\", \"Quantity\" : \"5\", \"Amount\" : \"45000$\"}, {\"item 2\": \"Tea Bag\", \"Quantity\": \"10\", \"Amount\": \"45000$\"} ]}\"\"\"\n"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "execution_count": 10,
74 | "metadata": {},
75 | "outputs": [],
76 | "source": [
77 | "def parse_date(date_str, dayfirst=False):\n",
78 | " return parser.parse(date_str, dayfirst=dayfirst)\n",
79 | "\n",
80 | "def getting_yearly_amount(contract):\n",
81 | " \"\"\" Function use to calculate the yearly amount to be paid for a contract\"\"\"\n",
82 | " try:\n",
83 | " contract = json.loads(contract)\n",
84 | " except json.JSONDecodeError as e:\n",
85 | " print('Failed to decode coefficients:', e)\n",
86 | " return None\n",
87 | " # Extracting required information from the contract\n",
88 | " term_contract_date = parse_date(contract['Contract_Date'])\n",
89 | " term_start_date = parse_date(contract['Term_start_date'])\n",
90 | " if len(contract['Term_end_date']) > 5:\n",
91 | " term_end_date = parse_date(contract['Term_end_date'])\n",
92 | " total_months = (term_end_date.year - term_contract_date.year) * 12 + (term_end_date.month - term_contract_date.month)\n",
93 | " else:\n",
94 | " total_months = int(contract['Term_end_date'])\n",
95 | "\n",
96 | " if type(contract['Contract_amount']) == list:\n",
97 | " contract_amount = sum([float(item['Amount'].replace('$', '').replace(',', '')) for item in contract['Contract_amount']])\n",
98 | " else: \n",
99 | " contract_amount = float(contract['Contract_amount'].replace('$', '').replace(',', ''))\n",
100 | " # Calculate monthly amount to be paid\n",
101 | " monthly_payment = contract_amount / total_months\n",
102 | "\n",
103 | " # Calculate the utilized period in months\n",
104 | " utilized_months = (term_start_date.year - term_contract_date.year) * 12 + (term_start_date.month - term_contract_date.month)\n",
105 | "\n",
106 | " # Calculate the utilized amount so far\n",
107 | " utilized_amount = utilized_months * monthly_payment\n",
108 | "\n",
109 | " # remaing amount\n",
110 | " remaining_amount = contract_amount - utilized_amount\n",
111 | "\n",
112 | " return {'utilized_amount': utilized_amount, 'remaining_amount': remaining_amount}\n",
113 | "\n"
114 | ]
115 | },
116 | {
117 | "cell_type": "code",
118 | "execution_count": 11,
119 | "metadata": {},
120 | "outputs": [],
121 | "source": [
122 | "equation_tool = Tool(name='Yearly Amount Estimation', func=getting_yearly_amount, description=\"Useful for data provided in the json format and estimating amount assciated for each year.\")\n",
123 | "\n",
124 | "tools = [equation_tool]\n",
125 | "\n",
126 | "memory = ConversationBufferWindowMemory(memory_key=\"chat_history\", k=3, input_key=\"input\", output_key=\"output\",return_messages=True) \n",
127 | "\n",
128 | "agent_parameters = {\n",
129 | " 'agent':'chat-conversational-react-description',\n",
130 | " #'agent':AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n",
131 | " 'tools':tools,\n",
132 | " 'llm':llm,\n",
133 | " 'verbose':True,\n",
134 | " 'max_iterations':4,\n",
135 | " 'return_intermediate_steps':True,\n",
136 | " 'early_stopping_method':'generate',\n",
137 | " \n",
138 | " 'memory':memory\n",
139 | "}\n",
140 | "\n",
141 | "agent = initialize_agent(**agent_parameters)\n"
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "execution_count": 12,
147 | "metadata": {},
148 | "outputs": [
149 | {
150 | "name": "stdout",
151 | "output_type": "stream",
152 | "text": [
153 | "CPU times: user 2 µs, sys: 0 ns, total: 2 µs\n",
154 | "Wall time: 4.77 µs\n",
155 | "\n",
156 | "\n",
157 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
158 | "\u001b[32;1m\u001b[1;3m```json\n",
159 | "{\n",
160 | " \"action\": \"Yearly Amount Estimation\",\n",
161 | " \"action_input\": \"{\\\"Sno\\\": 1, \\\"Contract_Number\\\": \\\"C887/36\\\", \\\"Contract_Date\\\": \\\"11/1/2023\\\", \\\"Term_start_date\\\": \\\"12/1/2023\\\", \\\"Term_end_date\\\": \\\"18\\\", \\\"Contract_amount\\\": [{\\\"item 1\\\" : \\\"SD Card\\\", \\\"Quantity\\\" : \\\"5\\\", \\\"Amount\\\" : \\\"45000$\\\"}, {\\\"item 2\\\": \\\"Tea Bag\\\", \\\"Quantity\\\": \\\"10\\\", \\\"Amount\\\": \\\"45000$\\\"}]}\"\n",
162 | "}\n",
163 | "```\u001b[0m\n",
164 | "Observation: \u001b[36;1m\u001b[1;3m{'utilized_amount': 5000.0, 'remaining_amount': 85000.0}\u001b[0m\n",
165 | "Thought:\u001b[32;1m\u001b[1;3m```json\n",
166 | "{\n",
167 | " \"action\": \"Final Answer\",\n",
168 | " \"action_input\": \"Based on the provided information, the utilized amount from the contract is $5,000, and the remaining amount is $85,000.\"\n",
169 | "}\n",
170 | "```\u001b[0m\n",
171 | "\n",
172 | "\u001b[1m> Finished chain.\u001b[0m\n"
173 | ]
174 | }
175 | ],
176 | "source": [
177 | "%time\n",
178 | "output= agent.invoke({\"input\":f\"get each year amount from the given contract {contract3} \"})\n"
179 | ]
180 | },
181 | {
182 | "cell_type": "code",
183 | "execution_count": 13,
184 | "metadata": {},
185 | "outputs": [
186 | {
187 | "data": {
188 | "text/plain": [
189 | "{'utilized_amount': 5000.0, 'remaining_amount': 85000.0}"
190 | ]
191 | },
192 | "execution_count": 13,
193 | "metadata": {},
194 | "output_type": "execute_result"
195 | }
196 | ],
197 | "source": [
198 | "result=output['intermediate_steps'][-1][-1]\n",
199 | "result"
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 14,
205 | "metadata": {},
206 | "outputs": [
207 | {
208 | "name": "stdout",
209 | "output_type": "stream",
210 | "text": [
211 | "\n",
212 | "\n",
213 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
214 | "\u001b[32;1m\u001b[1;3m```json\n",
215 | "{\n",
216 | " \"action\": \"Yearly Amount Estimation\",\n",
217 | " \"action_input\": \"{\\\"Sno\\\": 1, \\\"Contract_Number\\\": \\\"C887/36\\\", \\\"Contract_Date\\\": \\\"11/1/2023\\\", \\\"Term_start_date\\\": \\\"12/1/2023\\\", \\\"Term_end_date\\\": \\\"18\\\", \\\"Contract_amount\\\": \\\"$90,000.00\\\"}\"\n",
218 | "}\n",
219 | "```\u001b[0m\n",
220 | "Observation: \u001b[36;1m\u001b[1;3m{'utilized_amount': 5000.0, 'remaining_amount': 85000.0}\u001b[0m\n",
221 | "Thought:\u001b[32;1m\u001b[1;3m```json\n",
222 | "{\n",
223 | " \"action\": \"Final Answer\",\n",
224 | " \"action_input\": \"The contract has a utilized amount of $5,000 and a remaining amount of $85,000.\"\n",
225 | "}\n",
226 | "```\u001b[0m\n",
227 | "\n",
228 | "\u001b[1m> Finished chain.\u001b[0m\n"
229 | ]
230 | },
231 | {
232 | "data": {
233 | "text/plain": [
234 | "{'utilized_amount': 5000.0, 'remaining_amount': 85000.0}"
235 | ]
236 | },
237 | "execution_count": 14,
238 | "metadata": {},
239 | "output_type": "execute_result"
240 | }
241 | ],
242 | "source": [
243 | "output= agent.invoke({\"input\":f\"get each year amount from the given contract {contract2} \"})\n",
244 | "\n",
245 | "result=output['intermediate_steps'][-1][-1]\n",
246 | "result"
247 | ]
248 | },
249 | {
250 | "cell_type": "code",
251 | "execution_count": 15,
252 | "metadata": {},
253 | "outputs": [
254 | {
255 | "name": "stdout",
256 | "output_type": "stream",
257 | "text": [
258 | "\n",
259 | "\n",
260 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
261 | "\u001b[32;1m\u001b[1;3m```json\n",
262 | "{\n",
263 | " \"action\": \"Yearly Amount Estimation\",\n",
264 | " \"action_input\": \"{\\\"Sno\\\": 1, \\\"Contract_Number\\\": \\\"C887/36\\\", \\\"Contract_Date\\\": \\\"11/1/2023\\\", \\\"Term_start_date\\\": \\\"12/1/2023\\\", \\\"Term_end_date\\\": \\\"05/31/2025\\\", \\\"Contract_amount\\\": \\\"$90,000.00\\\"}\"\n",
265 | "}\n",
266 | "```\u001b[0m\n",
267 | "Observation: \u001b[36;1m\u001b[1;3m{'utilized_amount': 5000.0, 'remaining_amount': 85000.0}\u001b[0m\n",
268 | "Thought:\u001b[32;1m\u001b[1;3m```json\n",
269 | "{\n",
270 | " \"action\": \"Final Answer\",\n",
271 | " \"action_input\": \"The utilized amount from the contract is $5,000, and the remaining amount is $85,000.\"\n",
272 | "}\n",
273 | "```\u001b[0m\n",
274 | "\n",
275 | "\u001b[1m> Finished chain.\u001b[0m\n"
276 | ]
277 | },
278 | {
279 | "data": {
280 | "text/plain": [
281 | "{'utilized_amount': 5000.0, 'remaining_amount': 85000.0}"
282 | ]
283 | },
284 | "execution_count": 15,
285 | "metadata": {},
286 | "output_type": "execute_result"
287 | }
288 | ],
289 | "source": [
290 | "output= agent.invoke({\"input\":f\"get each year amount from the given contract {contract1} \"})\n",
291 | "\n",
292 | "result=output['intermediate_steps'][-1][-1]\n",
293 | "result"
294 | ]
295 | },
296 | {
297 | "cell_type": "markdown",
298 | "metadata": {},
299 | "source": [
300 | "### Using LLM Math Tool"
301 | ]
302 | },
303 | {
304 | "cell_type": "code",
305 | "execution_count": 17,
306 | "metadata": {},
307 | "outputs": [],
308 | "source": [
309 | "problem_chain = LLMMathChain.from_llm(llm=llm)\n",
310 | "\n",
311 | "math_tool = Tool.from_function(name=\"Calculator\",func=problem_chain.run,description=\"Useful for when you need to answer questions \\\n",
312 | "about math. This tool is only for math questions and nothing else. Only input\\\n",
313 | "math expressions.\")\n",
314 | "\n",
315 | "agent = initialize_agent(\n",
316 | " tools=[math_tool],\n",
317 | " llm=llm,\n",
318 | " agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n",
319 | " verbose=False,\n",
320 | " handle_parsing_errors=True\n",
321 | ")\n",
322 | "\n",
323 | "contract1 = {'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/2023', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'}\n",
324 | "\n",
325 | "\n",
326 | "input_prompt = f\"\"\" You are an AI assistant that help us to make mathematical calculation. From the given contract details, calculate the amount to be paid based on the time spend by the auditor.\n",
327 | "Here are the details about the contract {contract1}:\n",
328 | "Contract_Date - Begining date of the contract and it is in the date format.\n",
329 | "Term_start_date - Auditor already worked until this data. This also in the date format.\n",
330 | "Term_end_date - The date when the contract will end. It could be either in the date fromat or simply the total number of months taken by contract to complete from the Contract_Date.\n",
331 | "Contract_amount - The total amount of the contract. It could be a single amount or an array of items with the amount associated with each item. If it is in the list, calulate the total amount by summing the amount of each item.\n",
332 | "\n",
333 | "Using following steps to calculate the amount to be paid and the remaing amount. also provide the final result in the json format.\n",
334 | "\n",
335 | "1. Total momnth covered by contract = Month between Contract_Date and Term_end_date. Include only month, not the days from the given dates. If the Term_end_date is a number, this number will simply be the total month covered by the contract.\n",
336 | "2. Total month spent by auditor = Month between Term_start_date and Contract_Date.\n",
337 | "3. Amount associated per month = Contract Amount / Total month covered by contract.\n",
338 | "4. Amount utilized by auditor = Amount utilized per month * Total month spent by auditor.\n",
339 | "5. Amount remaining = Contract Amount - Amount utilized by auditor.\n",
340 | "\n",
341 | "provide the final result (Amount utilized by auditor and Amount remaining) in the json format.\n",
342 | "\n",
343 | "\"\"\""
344 | ]
345 | },
346 | {
347 | "cell_type": "code",
348 | "execution_count": 18,
349 | "metadata": {},
350 | "outputs": [],
351 | "source": [
352 | "output=agent.invoke({'input':input_prompt})\n"
353 | ]
354 | },
355 | {
356 | "cell_type": "code",
357 | "execution_count": 19,
358 | "metadata": {},
359 | "outputs": [
360 | {
361 | "data": {
362 | "text/plain": [
363 | "{'input': \" You are an AI assistant that help us to make mathematical calculation. From the given contract details, calculate the amount to be paid based on the time spend by the auditor.\\nHere are the details about the contract {'Sno': 1, 'Contract_Number': 'C887/36', 'Contract_Date': '11/1/2023', 'Term_start_date': '12/1/2023', 'Term_end_date': '05/31/2024', 'Contract_amount': '$90,000.00'}:\\nContract_Date - Begining date of the contract and it is in the date format.\\nTerm_start_date - Auditor already worked until this data. This also in the date format.\\nTerm_end_date - The date when the contract will end. It could be either in the date fromat or simply the total number of months taken by contract to complete from the Contract_Date.\\nContract_amount - The total amount of the contract. It could be a single amount or an array of items with the amount associated with each item. If it is in the list, calulate the total amount by summing the amount of each item.\\n\\nUsing following steps to calculate the amount to be paid and the remaing amount. also provide the final result in the json format.\\n\\n1. Total momnth covered by contract = Month between Contract_Date and Term_end_date. Include only month, not the days from the given dates. If the Term_end_date is a number, this number will simply be the total month covered by the contract.\\n2. Total month spent by auditor = Month between Term_start_date and Contract_Date.\\n3. Amount associated per month = Contract Amount / Total month covered by contract.\\n4. Amount utilized by auditor = Amount utilized per month * Total month spent by auditor.\\n5. Amount remaining = Contract Amount - Amount utilized by auditor.\\n\\nprovide the final result (Amount utilized by auditor and Amount remaining) in the json format.\\n\\n\",\n",
364 | " 'output': '{\"Amount_utilized_by_auditor\": \"$12,857.14\", \"Amount_remaining\": \"$77,142.86\"}'}"
365 | ]
366 | },
367 | "execution_count": 19,
368 | "metadata": {},
369 | "output_type": "execute_result"
370 | }
371 | ],
372 | "source": [
373 | "output"
374 | ]
375 | },
376 | {
377 | "cell_type": "code",
378 | "execution_count": null,
379 | "metadata": {},
380 | "outputs": [],
381 | "source": []
382 | }
383 | ],
384 | "metadata": {
385 | "kernelspec": {
386 | "display_name": "langchain",
387 | "language": "python",
388 | "name": "python3"
389 | },
390 | "language_info": {
391 | "codemirror_mode": {
392 | "name": "ipython",
393 | "version": 3
394 | },
395 | "file_extension": ".py",
396 | "mimetype": "text/x-python",
397 | "name": "python",
398 | "nbconvert_exporter": "python",
399 | "pygments_lexer": "ipython3",
400 | "version": "3.12.2"
401 | }
402 | },
403 | "nbformat": 4,
404 | "nbformat_minor": 2
405 | }
406 |
--------------------------------------------------------------------------------
/LangGraph/README:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LangGraph/langGraph_breakpoints_turorial_04.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 2,
6 | "metadata": {},
7 | "outputs": [
8 | {
9 | "name": "stdout",
10 | "output_type": "stream",
11 | "text": [
12 | "{'user_input': 'hello world'}\n",
13 | "---Step 1---\n",
14 | "{'user_input': 'hello world', 'response': 'Hello! How can I assist you today?', 'user_approval': None}\n",
15 | "---Step 2---\n",
16 | "{'user_input': 'hello world', 'response': 'Hello! How can I assist you today?', 'user_approval': None}\n",
17 | "Breakpoint reached. Execution paused.\n",
18 | "----------------------------------------------------------------\n",
19 | "---Step 3---\n",
20 | "{'user_input': 'hello world', 'response': 'No response to show.', 'user_approval': 'no'}\n"
21 | ]
22 | }
23 | ],
24 | "source": [
25 | "from typing import TypedDict\n",
26 | "from langgraph.graph import StateGraph, START, END\n",
27 | "from langgraph.checkpoint.memory import MemorySaver\n",
28 | "from IPython.display import Image, display\n",
29 | "\n",
30 | "class State(TypedDict):\n",
31 | " user_input: str\n",
32 | " response: str\n",
33 | " user_approval: str\n",
34 | "\n",
35 | "def step_1(state):\n",
36 | " print(\"---Step 1---\")\n",
37 | " if \"hello\" in state[\"user_input\"].lower():\n",
38 | " state[\"response\"] = \"Hello! How can I assist you today?\"\n",
39 | " else:\n",
40 | " state[\"response\"] = \"I'm not sure how to respond to that.\"\n",
41 | " return state\n",
42 | "\n",
43 | "def step_2(state):\n",
44 | " print(\"---Step 2---\")\n",
45 | " print(state)\n",
46 | " pass\n",
47 | "\n",
48 | "def step_3(state):\n",
49 | " print(\"---Step 3---\")\n",
50 | " if state[\"user_approval\"] == \"yes\":\n",
51 | " print(\"Since you approved, I will show the response.\")\n",
52 | " return state\n",
53 | " else:\n",
54 | " return {\"response\":\"No response to show.\"}\n",
55 | " \n",
56 | "builder = StateGraph(State)\n",
57 | "builder.add_node(\"step_1\", step_1)\n",
58 | "builder.add_node(\"step_2\", step_2)\n",
59 | "builder.add_node(\"step_3\", step_3)\n",
60 | "builder.add_edge(START, \"step_1\")\n",
61 | "builder.add_edge(\"step_1\", \"step_2\")\n",
62 | "builder.add_edge(\"step_2\", \"step_3\")\n",
63 | "builder.add_edge(\"step_3\", END)\n",
64 | "# Set up memory\n",
65 | "memory = MemorySaver()\n",
66 | "# Add\n",
67 | "graph = builder.compile(checkpointer=memory, interrupt_before=[\"step_3\"])\n",
68 | "\n",
69 | "# Input\n",
70 | "initial_input = {\"user_input\": \"hello world\"}\n",
71 | "\n",
72 | "# Thread\n",
73 | "thread = {\"configurable\": {\"thread_id\": \"1\"}}\n",
74 | "\n",
75 | "# Run the graph until the first interruption\n",
76 | "for event in graph.stream(initial_input, thread, stream_mode=\"values\"):\n",
77 | " print(event)\n",
78 | "\n",
79 | "print(\"Breakpoint reached. Execution paused.\")\n",
80 | "print('----------------------------------------------------------------')\n",
81 | "#print('\\n')\n",
82 | "user_approval = input(\"Do you want to execute step 3? (yes/no): \")\n",
83 | "\n",
84 | "snapshot=graph.get_state(thread)\n",
85 | "snapshot.values['user_approval']=user_approval\n",
86 | "graph.update_state(thread, snapshot.values, as_node=\"step_2\")\n",
87 | "\n",
88 | "#print(snapshot.values)\n",
89 | "\n",
90 | "for event in graph.stream(None, thread, stream_mode=\"values\"):\n",
91 | " print(event)\n",
92 | "\n",
93 | "# if user_approval.lower() == \"yes\":\n",
94 | "# # If approved, continue the graph execution\n",
95 | "# for event in graph.stream(None, thread, stream_mode=\"values\"):\n",
96 | "# print(event)\n",
97 | "# else:\n",
98 | "# print(\"Operation cancelled by user.\")"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "execution_count": 57,
104 | "metadata": {},
105 | "outputs": [
106 | {
107 | "data": {
108 | "image/jpeg": "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",
109 | "text/plain": [
110 | ""
111 | ]
112 | },
113 | "metadata": {},
114 | "output_type": "display_data"
115 | }
116 | ],
117 | "source": [
118 | "display(Image(graph.get_graph().draw_mermaid_png()))"
119 | ]
120 | }
121 | ],
122 | "metadata": {
123 | "kernelspec": {
124 | "display_name": "langchain",
125 | "language": "python",
126 | "name": "python3"
127 | },
128 | "language_info": {
129 | "codemirror_mode": {
130 | "name": "ipython",
131 | "version": 3
132 | },
133 | "file_extension": ".py",
134 | "mimetype": "text/x-python",
135 | "name": "python",
136 | "nbconvert_exporter": "python",
137 | "pygments_lexer": "ipython3",
138 | "version": "3.12.2"
139 | }
140 | },
141 | "nbformat": 4,
142 | "nbformat_minor": 2
143 | }
144 |
--------------------------------------------------------------------------------
/LangGraph/langGraph_router_turorial_02.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Example - No Branching. Try with StateGraph and MessageGraph. StateGraph is more powerful"
8 | ]
9 | },
10 | {
11 | "cell_type": "code",
12 | "execution_count": 1,
13 | "metadata": {},
14 | "outputs": [
15 | {
16 | "name": "stdout",
17 | "output_type": "stream",
18 | "text": [
19 | "[HumanMessage(content='who are you?', id='591093d0-27c2-46cb-b939-dbb787732b9a'), AIMessage(content='I am an artificial intelligence developed by OpenAI, designed to assist with answering questions, providing information, and engaging in various text-based tasks. How can I help you today?', response_metadata={'token_usage': {'completion_tokens': 35, 'prompt_tokens': 11, 'total_tokens': 46}, 'model_name': 'gpt-4o', 'system_fingerprint': 'fp_4e2b2da518', 'finish_reason': 'stop', 'logprobs': None}, id='run-1cf8068b-144a-4d8c-bd12-55b8ca351c60-0')]\n"
20 | ]
21 | },
22 | {
23 | "data": {
24 | "image/jpeg": "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",
25 | "text/plain": [
26 | ""
27 | ]
28 | },
29 | "metadata": {},
30 | "output_type": "display_data"
31 | }
32 | ],
33 | "source": [
34 | "import os\n",
35 | "from langchain_openai import ChatOpenAI\n",
36 | "from langchain_core.messages import HumanMessage,BaseMessage\n",
37 | "from langchain_openai import ChatOpenAI\n",
38 | "import operator\n",
39 | "from typing import Annotated, TypedDict, List\n",
40 | "from langgraph.graph import StateGraph, END, MessageGraph, START\n",
41 | "from IPython.display import Image, display\n",
42 | "\n",
43 | "OPENAI_API_KEY=\"sk-xxxx\" # https://platform.openai.com/account/api-keys\n",
44 | "os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY\n",
45 | "\n",
46 | "llm = ChatOpenAI(model='gpt-4o')\n",
47 | "\n",
48 | "class State(TypedDict):\n",
49 | " messages: Annotated[List[str], operator.add]\n",
50 | "\n",
51 | "#builder = StateGraph(State)\n",
52 | "builder = MessageGraph()\n",
53 | "\n",
54 | "# def call_llm(state):\n",
55 | "# msg = state['messages']\n",
56 | "# res = llm.invoke(msg)\n",
57 | "# return {'messages':[res]}\n",
58 | "\n",
59 | "#builder.add_node(\"model\", call_llm)\n",
60 | "builder.add_node(\"model\", llm)\n",
61 | "\n",
62 | "builder.add_edge(\"model\", END)\n",
63 | "\n",
64 | "builder.add_edge(START, \"model\")\n",
65 | "\n",
66 | "graph = builder.compile()\n",
67 | "\n",
68 | "#result = graph.invoke({'messages':input_messages})\n",
69 | "result = graph.invoke([HumanMessage(content='who are you?')])\n",
70 | "print(result)\n",
71 | "#graph.invoke({'messages':['who are you?']})\n",
72 | "\n",
73 | "display(Image(graph.get_graph(xray=True).draw_mermaid_png()))\n"
74 | ]
75 | },
76 | {
77 | "cell_type": "markdown",
78 | "metadata": {},
79 | "source": [
80 | "## Example - Branching and Customized tools Implementation"
81 | ]
82 | },
83 | {
84 | "cell_type": "code",
85 | "execution_count": 2,
86 | "metadata": {},
87 | "outputs": [
88 | {
89 | "data": {
90 | "image/jpeg": "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",
91 | "text/plain": [
92 | ""
93 | ]
94 | },
95 | "metadata": {},
96 | "output_type": "display_data"
97 | }
98 | ],
99 | "source": [
100 | "import os\n",
101 | "import operator\n",
102 | "from langchain_core.tools import tool\n",
103 | "from langgraph.graph import END, START\n",
104 | "from langgraph.prebuilt import ToolNode\n",
105 | "from langchain_openai import ChatOpenAI\n",
106 | "from langchain_core.messages import HumanMessage,BaseMessage\n",
107 | "from langchain_openai import ChatOpenAI\n",
108 | "from typing import Annotated, TypedDict, List\n",
109 | "from langgraph.graph import StateGraph, END, MessageGraph, START\n",
110 | "from IPython.display import Image, display\n",
111 | "\n",
112 | "#OPENAI_API_KEY=\"xxxxxx\"\n",
113 | "os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY\n",
114 | "\n",
115 | "@tool\n",
116 | "def multiply(first_number: int, second_number: int):\n",
117 | " \"\"\"Multiplies two numbers together.\"\"\"\n",
118 | " return first_number * second_number\n",
119 | "\n",
120 | "@tool\n",
121 | "def add(first_number: int, second_number: int) -> int:\n",
122 | " \"\"\"Adds two numbers together.\"\"\"\n",
123 | " return first_number + second_number\n",
124 | "\n",
125 | "tools = [multiply, add]\n",
126 | "\n",
127 | "model = ChatOpenAI(model='gpt-4o')\n",
128 | "\n",
129 | "model_with_tools = model.bind_tools(tools=tools)\n",
130 | "\n",
131 | "builder = MessageGraph()\n",
132 | "builder.add_node('model', model_with_tools)\n",
133 | "tool_node = ToolNode(tools)\n",
134 | "builder.add_node(\"action\", tool_node)\n",
135 | "builder.add_edge(START, \"model\")\n",
136 | "builder.add_edge(\"action\", END)\n",
137 | "\n",
138 | "def router(state: list[BaseMessage]):\n",
139 | " tool_calls = state[-1].additional_kwargs.get(\"tool_calls\", [])\n",
140 | " if len(tool_calls):\n",
141 | " return \"action\"\n",
142 | " else:\n",
143 | " return END\n",
144 | "\n",
145 | "builder.add_conditional_edges(\"model\", router)\n",
146 | "\n",
147 | "graph = builder.compile()\n",
148 | "display(Image(graph.get_graph(xray=True).draw_mermaid_png()))"
149 | ]
150 | },
151 | {
152 | "cell_type": "markdown",
153 | "metadata": {},
154 | "source": [
155 | "#### question is related to multiplication, so the multiply tool was called during graph execution"
156 | ]
157 | },
158 | {
159 | "cell_type": "code",
160 | "execution_count": 4,
161 | "metadata": {},
162 | "outputs": [
163 | {
164 | "name": "stdout",
165 | "output_type": "stream",
166 | "text": [
167 | "[HumanMessage(content='What is 123 * 456?', id='c602c9bc-b602-4aa5-93df-61dcab581bac'), AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_CHuS4ResEuHKjEoHIaM4gOZ5', 'function': {'arguments': '{\"first_number\":123,\"second_number\":456}', 'name': 'multiply'}, 'type': 'function'}]}, response_metadata={'token_usage': {'completion_tokens': 19, 'prompt_tokens': 81, 'total_tokens': 100}, 'model_name': 'gpt-4o', 'system_fingerprint': 'fp_bc2a86f5f5', 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-c891ddce-43b9-49da-a743-bc49a9a57eec-0', tool_calls=[{'name': 'multiply', 'args': {'first_number': 123, 'second_number': 456}, 'id': 'call_CHuS4ResEuHKjEoHIaM4gOZ5', 'type': 'tool_call'}]), ToolMessage(content='56088', name='multiply', id='63a6da07-725a-4550-b148-f39a916d4fba', tool_call_id='call_CHuS4ResEuHKjEoHIaM4gOZ5')]\n"
168 | ]
169 | }
170 | ],
171 | "source": [
172 | "result=graph.invoke(HumanMessage(\"What is 123 * 456?\"))\n",
173 | "print(result)\n"
174 | ]
175 | },
176 | {
177 | "cell_type": "markdown",
178 | "metadata": {},
179 | "source": [
180 | "#### question not related to tools: so no tool is invoked during graph execution"
181 | ]
182 | },
183 | {
184 | "cell_type": "code",
185 | "execution_count": 5,
186 | "metadata": {},
187 | "outputs": [
188 | {
189 | "data": {
190 | "text/plain": [
191 | "[HumanMessage(content='when did last olympics happen?', id='9d410f5f-b2d7-422a-b784-05356469c659'),\n",
192 | " AIMessage(content='The most recent Olympic Games were the Summer Olympics, which took place in Tokyo, Japan from July 23 to August 8, 2021.', response_metadata={'token_usage': {'completion_tokens': 31, 'prompt_tokens': 80, 'total_tokens': 111}, 'model_name': 'gpt-4o', 'system_fingerprint': 'fp_4e2b2da518', 'finish_reason': 'stop', 'logprobs': None}, id='run-b8fb45fc-caf7-47b7-be6c-5938bc8bc74e-0')]"
193 | ]
194 | },
195 | "execution_count": 5,
196 | "metadata": {},
197 | "output_type": "execute_result"
198 | }
199 | ],
200 | "source": [
201 | "result=graph.invoke(HumanMessage(\"when did last olympics happen?\"))\n",
202 | "result\n"
203 | ]
204 | },
205 | {
206 | "cell_type": "code",
207 | "execution_count": null,
208 | "metadata": {},
209 | "outputs": [],
210 | "source": []
211 | }
212 | ],
213 | "metadata": {
214 | "kernelspec": {
215 | "display_name": "langchain",
216 | "language": "python",
217 | "name": "python3"
218 | },
219 | "language_info": {
220 | "codemirror_mode": {
221 | "name": "ipython",
222 | "version": 3
223 | },
224 | "file_extension": ".py",
225 | "mimetype": "text/x-python",
226 | "name": "python",
227 | "nbconvert_exporter": "python",
228 | "pygments_lexer": "ipython3",
229 | "version": "3.12.2"
230 | }
231 | },
232 | "nbformat": 4,
233 | "nbformat_minor": 2
234 | }
235 |
--------------------------------------------------------------------------------
/LangGraphStudio/.env:
--------------------------------------------------------------------------------
1 | OPENAI_API_KEY="sk-vppEQrLLaft8GdCM4PrXT3BxxxxtErfxxxWZgz5x"
2 | LANGCHAIN_API_KEY="lsv2_pt_6e9exxxx28459xxx94a214_cfc2M01db0"
3 | OPENWEATHERMAP_API_KEY="d3440b2b0xxxxx2bfM0xxx745c5"
4 | TAVILY_API_KEY="tvly-5EMhv4TbDDcxxxJemxx1NbxxPUPH"
5 |
--------------------------------------------------------------------------------
/LangGraphStudio/README:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/LangGraphStudio/agent.py:
--------------------------------------------------------------------------------
1 | from pydantic import BaseModel, Field
2 | from langchain.tools import StructuredTool
3 | import requests
4 | import os
5 | from langchain_openai import ChatOpenAI
6 | from langgraph.prebuilt import create_react_agent
7 | from langchain_community.tools.tavily_search import TavilySearchResults
8 |
9 | # define llm
10 | model = ChatOpenAI(model="gpt-4o")
11 |
12 | OPENWEATHERMAP_API_KEY = os.getenv("OPENWEATHERMAP_API_KEY")
13 |
14 | # define tools
15 | class City(BaseModel):
16 | city: str = Field(description="City")
17 | country: str = Field(description="Country code")
18 |
19 | def get_current_weather(city: str, country: str) -> int:
20 | response = requests.get(
21 | f"http://api.openweathermap.org/data/2.5/weather?q={city},{country}&appid={OPENWEATHERMAP_API_KEY}"
22 | )
23 | data = response.json()
24 | temp_kelvin = data["main"]["temp"]
25 | temp_fahrenheit = (temp_kelvin - 273.15) * 9 / 5 + 32
26 | return int(temp_fahrenheit)
27 |
28 |
29 | weather = StructuredTool.from_function(
30 | func=get_current_weather,
31 | name="Get_Weather",
32 | description="Get the current temperature from a city, in Fahrenheit",
33 | args_schema=City,
34 | return_direct=False,
35 | )
36 |
37 | tools = [weather, TavilySearchResults(max_results=2)]
38 | graph = create_react_agent(model, tools=tools)
39 |
--------------------------------------------------------------------------------
/LangGraphStudio/langgraph.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": ["."],
3 | "graphs": {
4 | "agent": "./agent.py:graph"
5 | },
6 | "env": ".env"
7 | }
--------------------------------------------------------------------------------
/LangGraphStudio/requirements.txt:
--------------------------------------------------------------------------------
1 | langgraph
2 | tavily-python
3 | langchain_openai
4 | langchain_community
5 | langchain
6 | pydantic
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # OpenAI-Chat
--------------------------------------------------------------------------------
/agentapp.py:
--------------------------------------------------------------------------------
1 | # General imports
2 | import streamlit as st
3 | from streamlit_chat import message
4 | import os
5 | import operator
6 | from typing import Annotated, Any, Dict, List, Optional, Sequence, TypedDict
7 | import functools
8 | import openai
9 |
10 | # Langchain imports
11 | from langchain_community.tools.tavily_search import TavilySearchResults
12 | from langchain_core.tools import tool, Tool
13 | from langchain_experimental.tools import PythonREPLTool
14 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
15 | from langchain_community.utilities import OpenWeatherMapAPIWrapper
16 | from langchain.agents import AgentExecutor, create_openai_tools_agent,load_tools
17 | from langchain_openai import ChatOpenAI
18 | from langchain.chains import LLMMathChain
19 | from langchain.output_parsers.openai_functions import JsonOutputFunctionsParser
20 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
21 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
22 | from langgraph.graph import StateGraph, END
23 | from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage
24 |
25 | ## Additional Library -
26 | from langchain_community.tools import YouTubeSearchTool
27 | from langchain_community.tools.google_finance import GoogleFinanceQueryRun
28 | from langchain_community.utilities.google_finance import GoogleFinanceAPIWrapper
29 | from langchain_community.tools.google_jobs import GoogleJobsQueryRun
30 | from langchain_community.utilities.google_jobs import GoogleJobsAPIWrapper
31 | from langchain_community.utilities.dalle_image_generator import DallEAPIWrapper
32 | from langchain.tools import WikipediaQueryRun
33 | from langchain_community.utilities import WikipediaAPIWrapper
34 | from langchain_community.document_loaders import WebBaseLoader
35 | from langchain_community.document_loaders import YoutubeLoader
36 |
37 | headers = {
38 | "authorization":st.secrets['OPENAI_API_KEY'],
39 | "content-type":"application/json",
40 | "talivy_api_key":st.secrets['TAVILY_API_KEY'],
41 | "langchain_api_key":st.secrets['LANGCHAIN_API_KEY'],
42 | "openweathermap_api_key":st.secrets['OPENWEATHERMAP_API_KEY'],
43 | "e2b_api_key":st.secrets['E2B_API_KEY'],
44 | "serpapi_api_key":st.secrets['SERPAPI_API_KEY']
45 | }
46 |
47 | openai.api_key = st.secrets["OPENAI_API_KEY"]
48 | OPENWEATHERMAP_API_KEY = st.secrets['OPENWEATHERMAP_API_KEY']
49 |
50 | os.environ['OPENAI_API_KEY'] = st.secrets['OPENAI_API_KEY']
51 | os.environ['TAVILY_API_KEY'] = st.secrets['TAVILY_API_KEY']
52 | os.environ['LANGCHAIN_API_KEY'] = st.secrets['LANGCHAIN_API_KEY']
53 | os.environ['OPENWEATHERMAP_API_KEY'] = st.secrets['OPENWEATHERMAP_API_KEY']
54 | os.environ['E2B_API_KEY'] = st.secrets['E2B_API_KEY']
55 | os.environ['SERPAPI_API_KEY'] = st.secrets['SERPAPI_API_KEY']
56 |
57 | st.title('Multi-Agent Framework - Supervisor')
58 | st.write(""":blue[Following agents are used in this framwork: Researcher, Coder, Weather, Calculator, Youtuber,
59 | GoogleFinace, JobSearch, Wikipedia, WebScarp, WebSummerizer]""")
60 | # system_p")
61 | # For visualization of the graph, Optional
62 | ## Creating LLM
63 | ## Tools and llm setup
64 | llm = ChatOpenAI(model="gpt-4-1106-preview")
65 |
66 | # Weather tools
67 | weather_tool = load_tools(["openweathermap-api"], llm, openweathermap_api_key=OPENWEATHERMAP_API_KEY)
68 |
69 | # Tavily tools - Search tools
70 | tavily_tool = TavilySearchResults(max_results=5)
71 |
72 | ### Math tools
73 | problem_chain = LLMMathChain.from_llm(llm=llm)
74 | math_tool = Tool.from_function(name="Calculator",func=problem_chain.run,description=\
75 | "Useful for when you need to answer questions \
76 | about math. This tool is only for math questions and nothing else. Only input\
77 | math expressions.")
78 |
79 | # Python REPL tool
80 | python_repl_tool = PythonREPLTool()
81 |
82 | ## Youtube tool
83 | youtube_tool = YouTubeSearchTool()
84 |
85 | ## Google Finace
86 | google_finance_tool = GoogleFinanceQueryRun(api_wrapper=GoogleFinanceAPIWrapper())
87 |
88 |
89 | ## Google Job Search
90 | jobsearch_tool = GoogleJobsQueryRun(api_wrapper=GoogleJobsAPIWrapper())
91 |
92 |
93 | # Dall.E image
94 | dalle_tool = DallEAPIWrapper()
95 |
96 | ## Wikipedia
97 | wiki_tool = WikipediaQueryRun(api_wrapper=WikipediaAPIWrapper())
98 | # response=wikipedia.run("Barak Obama")
99 | # response
100 |
101 | # Web Scrape
102 |
103 | @tool()
104 | def webScarpe(urls: List[str]) -> str:
105 | """Use requests and bs4 to scrape the provided web pages for detailed
106 | information."""
107 | loader = WebBaseLoader(urls)
108 | docs = loader.load()
109 | return "\n\n".join(
110 | [
111 | f'\n{doc.page_content}\n'
112 | for doc in docs
113 | ]
114 | )
115 |
116 | @tool()
117 | def summarize(content: str) -> str:
118 | """Summarize the content"""
119 | messages = [
120 | SystemMessage(
121 | content="You are an AI agent having very borad knowledge about the recent events around the glob. Your task is to summarize the given content very accurately."
122 | ),
123 | HumanMessage(
124 | content=content
125 | ),
126 | ]
127 | response = llm(messages)
128 | return response.content
129 |
130 | #cnt=webScarpe.invoke({'urls':['https://blog.langchain.dev/reflection-agents/']})
131 |
132 | @tool()
133 | def YoutubeTranslate(url: str) -> str:
134 | """Use to tranlate youtube video to plain text"""
135 | loader = YoutubeLoader.from_youtube_url(url,
136 | add_video_info=True,
137 | language=["en", "id"],
138 | translation="en")
139 |
140 | txt=loader.load()
141 |
142 | return txt[0].page_content
143 |
144 |
145 | def create_agent(llm: ChatOpenAI, tools: list, system_prompt: str):
146 | # Each worker node will be given a name and some tools.
147 | prompt = ChatPromptTemplate.from_messages(
148 | [
149 | (
150 | "system",
151 | system_prompt,
152 | ),
153 | MessagesPlaceholder(variable_name="messages"),
154 | MessagesPlaceholder(variable_name="agent_scratchpad"),
155 | ]
156 | )
157 | agent = create_openai_tools_agent(llm, tools, prompt)
158 | executor = AgentExecutor(agent=agent, tools=tools)
159 | return executor
160 |
161 | def agent_node(state, agent, name):
162 | result = agent.invoke(state)
163 | return {"messages": [HumanMessage(content=result["output"], name=name)]}
164 |
165 | members = ["Researcher", "Coder", "Weather", "Calculator", "Youtuber", "GoogleFinace", "JobSearch", "Wikipedia", "WebScarp", "WebSummerizer"]# "YouTubeText"]
166 | # system_prompt = (
167 | # "You are a supervisor tasked with managing a conversation between the"
168 | # " following workers: {members}. Given the following user request,"
169 | # " respond with the worker to act next. Each worker will perform a"
170 | # " task and respond with their results and status. When finished,"
171 | # " respond with FINISH."
172 | # )
173 | system_prompt = (
174 | "You are the supervisor over the following agents: {members}."
175 | "You are responsible for assigning tasks to each agent as requested by the user."
176 | "Each agent executes tasks according to their roles and responds with their results and status."
177 | "Please review the information and answer with the name of the agent to which the task should be assigned next."
178 | "Answer 'FINISH' if you are satisfied that you have fulfilled the user's request."
179 | )
180 |
181 | # Our team supervisor is an LLM node. It just picks the next agent to process
182 | # and decides when the work is completed
183 | options = ["FINISH"] + members
184 | # Using openai function calling can make output parsing easier for us
185 | function_def = {
186 | "name": "route",
187 | "description": "Select the next role.",
188 | "parameters": {
189 | "title": "routeSchema",
190 | "type": "object",
191 | "properties": {
192 | "next": {
193 | "title": "Next",
194 | "anyOf": [
195 | {"enum": options},
196 | ],
197 | }
198 | },
199 | "required": ["next"],
200 | },
201 | }
202 | prompt = ChatPromptTemplate.from_messages(
203 | [
204 | ("system", system_prompt),
205 | MessagesPlaceholder(variable_name="messages"),
206 | (
207 | "system",
208 | "Given the conversation above, who should act next?"
209 | " Or should we FINISH? Select one of: {options}",
210 | ),
211 | ]
212 | ).partial(options=str(options), members=", ".join(members))
213 |
214 | ### Supervisor Chain
215 | supervisor_chain = (
216 | prompt
217 | | llm.bind_functions(functions=[function_def], function_call="route")
218 | | JsonOutputFunctionsParser()
219 | )
220 |
221 |
222 | # The agent state is the input to each node in the graph
223 | class AgentState(TypedDict):
224 | messages: Annotated[Sequence[BaseMessage], operator.add]
225 | next: str
226 | recursion_count: int = 0
227 |
228 |
229 | research_agent = create_agent(llm, [tavily_tool], "You are a Web searcher.")
230 | research_node = functools.partial(agent_node, agent=research_agent, name="Researcher")
231 |
232 | # NOTE: THIS PERFORMS ARBITRARY CODE EXECUTION. PROCEED WITH CAUTION
233 | code_agent = create_agent(
234 | llm,
235 | [python_repl_tool],
236 | "You may generate safe python code to analyze data and generate charts using matplotlib.",
237 | )
238 | code_node = functools.partial(agent_node, agent=code_agent, name="Coder")
239 |
240 | #Weather nodes
241 | weather_agent = create_agent(
242 | llm,
243 | weather_tool,
244 | "You are a weather finder. You can provide weather information for a given location.",
245 | )
246 | weather_node = functools.partial(agent_node, agent=weather_agent, name="Weather")
247 |
248 | # Math node
249 |
250 | math_agent = create_agent(
251 | llm,
252 | [math_tool],
253 | "Useful for when you need to answer questions about math",
254 | )
255 | math_node = functools.partial(agent_node, agent=math_agent, name="Calculator")
256 |
257 | youtube_agent = create_agent(
258 | llm,
259 | [youtube_tool],
260 | "You are helpful for finding videos from Youtube"
261 | )
262 | youtube_node = functools.partial(agent_node, agent=youtube_agent, name="Youtuber")
263 |
264 | google_finance_agent = create_agent(
265 | llm,
266 | [google_finance_tool],
267 | "You are helpful for finding videos from Youtube"
268 | )
269 | google_finance_node = functools.partial(agent_node, agent=google_finance_agent, name="GoogleFinace")
270 |
271 |
272 | jobsearch_agent = create_agent(
273 | llm,
274 | [jobsearch_tool],
275 | "You are helpful for finding job related information"
276 | )
277 | jobsearch_node = functools.partial(agent_node, agent=jobsearch_agent, name="JobSearch")
278 |
279 |
280 | wiki_search_agent = create_agent(
281 | llm,
282 | [wiki_tool],
283 | "You are helpful for finding information from Wikipedia"
284 | )
285 | wiki_search_node = functools.partial(agent_node, agent=jobsearch_agent, name="Wikipedia")
286 |
287 |
288 | # image_generator_agent = create_agent(
289 | # llm,
290 | # [dalle_tool],
291 | # "You are helpful for generating images"
292 | # )
293 | # image_generator_node = functools.partial(agent_node, agent=image_generator_agent, name="ImageGenerator")
294 |
295 |
296 | WebScarp_agent = create_agent(
297 | llm,
298 | [webScarpe],
299 | "You are helpful for scarping the web page"
300 | )
301 | WebScarp_node = functools.partial(agent_node, agent=WebScarp_agent, name="WebScarp")
302 |
303 | WebSummerizer_agent = create_agent(
304 | llm,
305 | [summarize],
306 | "You are helpful for summarizing the content"
307 | )
308 | WebSummerizer_node = functools.partial(agent_node, agent=WebScarp_agent, name="WebSummerizer")
309 |
310 | YoutubeTranslate_agent = create_agent(
311 | llm,
312 | [YoutubeTranslate],
313 | "You are helpful for translating audio/video to text"
314 | )
315 | YoutubeTranslate_node = functools.partial(agent_node, agent=WebScarp_agent, name="YouTubeText")
316 |
317 | #### Create a Graph
318 | workflow = StateGraph(AgentState)
319 | workflow.add_node("Researcher", research_node)
320 | workflow.add_node("Coder", code_node)
321 | workflow.add_node("Weather", weather_node)
322 | workflow.add_node("Calculator", math_node)
323 | workflow.add_node("Youtuber", youtube_node)
324 | workflow.add_node("GoogleFinace", google_finance_node)
325 | workflow.add_node("JobSearch", jobsearch_node)
326 | workflow.add_node("Wikipedia", wiki_search_node)
327 | workflow.add_node("WebScarp", WebScarp_node)
328 | workflow.add_node("WebSummerizer", WebSummerizer_node)
329 | #workflow.add_node("YouTubeText", YoutubeTranslate_node)
330 | workflow.add_node("supervisor", supervisor_chain)
331 |
332 | for member in members:
333 | # We want our workers to ALWAYS "report back" to the supervisor when done
334 | workflow.add_edge(member, "supervisor")
335 | # The supervisor populates the "next" field in the graph state
336 | # which routes to a node or finishes
337 | conditional_map = {k: k for k in members}
338 | conditional_map["FINISH"] = END
339 | workflow.add_conditional_edges("supervisor", lambda x: x["next"], conditional_map)
340 | # Finally, add entrypoint
341 | workflow.set_entry_point("supervisor")
342 | graph = workflow.compile()
343 |
344 | # Graph Visualization
345 | # os.environ["PATH"] += os.pathsep + '/opt/homebrew/bin'
346 | # Image(graph.get_graph().draw_png())
347 |
348 | user_query = "find the weather in New York City today"
349 | user_query = "weather in ST. Louis MO and find one job related to data science in St. Louis?"
350 | user_query = "what is the google's stock today?"
351 | # user_query = "Why students are protesting in Columbia Univeristy this year?"
352 |
353 | user_query="1. First extract content from this url=https://python.langchain.com/docs/modules/agents/quick_start/, and 2. Summarize the content with one sentence only"
354 |
355 | # user_query="get the content from this url=https://www.youtube.com/watch?v=BZP1rYjoBgI" # this first goes to web and then go to youtube
356 |
357 | #user_query="write a python function help me generate Fibonacci sequence "
358 |
359 |
360 | question = st.text_input("User Query", key="input")
361 | #question = "find the weather in New York City today"
362 |
363 | if st.button('Submit'):
364 | if question:
365 | state=[]
366 | try:
367 | for s in graph.stream(
368 | {
369 | "messages": [
370 | HumanMessage(content=f"{question}")
371 | ]
372 | }
373 | ):
374 | state.append(s)
375 | if "__end__" not in s:
376 | #st.write(s)
377 | print("----")
378 | if len(state) > 3:
379 | break
380 | print(len(state))
381 | except:
382 | print("There is an issue")
383 |
384 | if len(state) > 1:
385 |
386 | #key_name=list(state[-1].keys())[0]
387 |
388 | #content=state[-1][key_name]['messages'][0].content
389 |
390 | #final_agent=state[-1][key_name]['messages'][0].name
391 |
392 | #st.write(f":blue[{content}]")
393 | # st.write(f"Final Agent: {final_agent}")
394 | st.write(":red[Let's check the entire state]")
395 | st.write(state)
396 | # st.write("Thank you for using this demo")
397 | else:
398 | st.write("service is not available currenlty")
399 |
--------------------------------------------------------------------------------
/chatbot_deployment_intent.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openai
3 | import streamlit as st
4 |
5 | # pip install streamlit-chat
6 | from streamlit_chat import message
7 |
8 | # from dotenv import load_dotenv, find_dotenv
9 | # load_dotenv(find_dotenv(), override=True)
10 |
11 | headers = {
12 | "authorization":st.secrets['OPENAI_API_KEY'],
13 | "content-type":"application/json",
14 | "pinecone-api-key":st.secrets['PINECONE_API_KEY'],
15 | "pinecone-env-name":st.secrets['PINECONE_ENV_NAME']
16 | }
17 | openai.api_key = st.secrets["OPENAI_API_KEY"]
18 |
19 | def insert_or_fetch_embeddings(index_name):
20 | import pinecone
21 | from langchain.vectorstores import Pinecone
22 | from langchain.embeddings.openai import OpenAIEmbeddings
23 |
24 | embeddings = OpenAIEmbeddings()
25 |
26 | #pinecone.init(api_key=os.environ.get('PINECONE_API_KEY'), environment=os.environ.get('PINECONE_ENV_NAME'))
27 | pinecone.init(api_key=st.secrets["PINECONE_API_KEY"], environment=st.secrets["PINECONE_ENV_NAME"])
28 |
29 | if index_name in pinecone.list_indexes():
30 | print(f'Index {index_name} already exists. Loading embeddings ... ', end='')
31 | vector_store = Pinecone.from_existing_index(index_name, embeddings)
32 | print('Ok')
33 | else:
34 | print(f'Creating index {index_name} and embeddings ...', end='')
35 | # pinecone.create_index(index_name, dimension=1536, metric='cosine')
36 | # vector_store = Pinecone.from_documents(chunks, embeddings, index_name=index_name)
37 | vector_store=None
38 | print('Ok')
39 | return vector_store
40 |
41 | index_name='intentdocument-index'
42 | vector_store = insert_or_fetch_embeddings(index_name)
43 |
44 | def ask_with_memory(vector_store, question, chat_history=[]):
45 | from langchain.chains import ConversationalRetrievalChain
46 | from langchain.chat_models import ChatOpenAI
47 |
48 | llm = ChatOpenAI(temperature=1)
49 | retriever = vector_store.as_retriever(search_type='similarity', search_kwargs={'k': 3})
50 |
51 | crc = ConversationalRetrievalChain.from_llm(llm, retriever)
52 | result = crc({'question': question, 'chat_history': chat_history})
53 | chat_history.append((question, result['answer']))
54 |
55 | return result, chat_history
56 |
57 | st.title("ChatBot : INTENT")
58 |
59 | chat_history=[]
60 | #question = st.text_input('Enter your question')
61 |
62 | if 'generated' not in st.session_state:
63 | st.session_state['generated'] = []
64 |
65 | if 'past' not in st.session_state:
66 | st.session_state['past'] = []
67 |
68 | query = st.text_input("Query: ", key="input")
69 |
70 |
71 | if query:
72 | result, chat_history = ask_with_memory(vector_store, question=query, chat_history=chat_history)
73 | answer = result['answer']
74 | st.session_state.past.append(query)
75 | st.session_state.generated.append(answer)
76 | #print(answer)
77 | #st.write(answer)
78 | if st.session_state['generated']:
79 |
80 | for i in range(len(st.session_state['generated'])-1, -1, -1):
81 | message(st.session_state["generated"][i], key=str(i))
82 | message(st.session_state['past'][i], is_user=True, key=str(i) + '_user')
83 |
84 |
--------------------------------------------------------------------------------
/chatbot_deployment_intent_withmemory.py:
--------------------------------------------------------------------------------
1 | import streamlit as st
2 | from pymongo import MongoClient
3 | from streamlit_chat import message
4 | from langchain.memory import MongoDBChatMessageHistory
5 | import pinecone
6 | from langchain.vectorstores import Pinecone
7 | from langchain.embeddings.openai import OpenAIEmbeddings
8 | import openai
9 |
10 | headers = {
11 | "authorization":st.secrets['OPENAI_API_KEY'],
12 | "content-type":"application/json",
13 | "connection_string":st.secrets['CONNECTION_STRING'],
14 | "pinecone-api-key":st.secrets['PINECONE_API_KEY'],
15 | "pinecone-env-name":st.secrets['PINECONE_ENV_NAME'],
16 | "mongodb_username":st.secrets['USERNAME'],
17 | "mongodb_pw":st.secrets['PW']
18 | }
19 | openai.api_key = st.secrets["OPENAI_API_KEY"]
20 |
21 | CONNECTION_STRING = st.secrets["CONNECTION_STRING"]
22 | USERNAME = st.secrets["USERNAME"]
23 | PW = st.secrets["PW"]
24 |
25 | # st.write(CONNECTION_STRING)
26 | # st.write(USERNAME)
27 | # st.write(PW)
28 |
29 | # CONNECTION_STRING =f"mongodb+srv://{USERNAME}:{PW}@cluster0.wjj4auk.mongodb.net/?retryWrites=true&w=majority"
30 | # st.write(CONNECTION_STRING)
31 |
32 | st.title('Simple question answer chatbot')
33 |
34 | embeddings = OpenAIEmbeddings()
35 | pinecone.init(api_key=st.secrets["PINECONE_API_KEY"], environment=st.secrets["PINECONE_ENV_NAME"])
36 |
37 | index_name='intentdocument-index'
38 | #index_name='pilotsurvey'
39 | vector_store = Pinecone.from_existing_index(index_name, embeddings)
40 |
41 | def get_mongodb_client():
42 | client = MongoClient(CONNECTION_STRING)
43 | return client
44 |
45 | # client = get_mongodb_client()
46 | # st.write(client)
47 | # db = client['chatbot_db']
48 | # conversation_collection = db['conversations']
49 | # # st.write(db)
50 | # # st.write(conversation_collection)
51 |
52 | # conversation_collection.insert_one({
53 | # 'question': 'who is Emry',
54 | # 'answer': 'She is from LA'
55 | # })
56 |
57 |
58 | def ask_with_memory(vector_store, question, chat_history=[]):
59 | from langchain.chains import ConversationalRetrievalChain
60 | from langchain.chat_models import ChatOpenAI
61 |
62 | llm = ChatOpenAI(temperature=1)
63 | retriever = vector_store.as_retriever(search_type='similarity', search_kwargs={'k': 3})
64 |
65 | crc = ConversationalRetrievalChain.from_llm(llm, retriever)
66 | result = crc({'question': question, 'chat_history': chat_history})
67 | chat_history.append((question, result['answer']))
68 |
69 | client = get_mongodb_client()
70 | db = client['chatbot_db']
71 | conversation_collection = db['conversations']
72 | conversation_collection.insert_one({
73 | 'question': question,
74 | 'answer': result['answer']
75 | })
76 | return result, chat_history
77 |
78 | chat_history=[]
79 | if 'generated' not in st.session_state:
80 | st.session_state['generated'] = []
81 | if 'past' not in st.session_state:
82 | st.session_state['past'] = []
83 |
84 | query = st.text_input("Query: ", key="input")
85 |
86 | if query:
87 | result, chat_history = ask_with_memory(vector_store, question=query, chat_history=chat_history)
88 | answer = result['answer']
89 | st.session_state.past.append(query)
90 | st.session_state.generated.append(answer)
91 | st.write(answer)
92 | if st.session_state['generated']:
93 | for i in range(len(st.session_state['generated'])-1, -1, -1):
94 | message(st.session_state["generated"][i], key=str(i))
95 | message(st.session_state['past'][i], is_user=True, key=str(i) + '_user')
96 |
--------------------------------------------------------------------------------
/clientsurvey.py:
--------------------------------------------------------------------------------
1 | import streamlit as st
2 | from pymongo import MongoClient
3 | from streamlit_chat import message
4 | import pinecone
5 | from langchain.vectorstores import Pinecone
6 | from langchain.embeddings.openai import OpenAIEmbeddings
7 | import openai
8 |
9 | import yagmail
10 | from email.message import EmailMessage
11 | import smtplib
12 |
13 | ## This is online version, the local copy is older version
14 | headers = {
15 | "authorization":st.secrets['OPENAI_API_KEY'],
16 | "content-type":"application/json",
17 | "connection_string":st.secrets['CONNECTION_STRING'],
18 | "pinecone-api-key":st.secrets['PINECONE_API_KEY'],
19 | "pinecone-env-name":st.secrets['PINECONE_ENV_NAME']
20 | }
21 | openai.api_key = st.secrets["OPENAI_API_KEY"]
22 |
23 | st.title('INTENT Survey Chatbot')
24 | st.write('(This pilot program is about sustainable douple-crop soybean production. Any questions about this program? Please reach out to guilherme.lobato@intent.ag)')
25 | CONNECTION_STRING = st.secrets["CONNECTION_STRING"]
26 |
27 | embeddings = OpenAIEmbeddings()
28 | pinecone.init(api_key=st.secrets["PINECONE_API_KEY"], environment=st.secrets["PINECONE_ENV_NAME"])
29 |
30 | #index_name='intentdocument-index'
31 | index_name='pilotsurvey'
32 | vector_store = Pinecone.from_existing_index(index_name, embeddings)
33 |
34 | def get_mongodb_client():
35 | client = MongoClient(CONNECTION_STRING)
36 | return client
37 |
38 | client = get_mongodb_client()
39 | db = client['chatbot_db']
40 | conversation_collection = db['conversations']
41 |
42 | def ask_with_memory(vector_store, user_name, user_email, question, conversation_collection, chat_history=[]):
43 | from langchain.chains import ConversationalRetrievalChain
44 | from langchain.chat_models import ChatOpenAI
45 |
46 | llm = ChatOpenAI(temperature=1)
47 | retriever = vector_store.as_retriever(search_type='similarity', search_kwargs={'k': 3})
48 |
49 | crc = ConversationalRetrievalChain.from_llm(llm, retriever)
50 | result = crc({'question': question, 'chat_history': chat_history})
51 | chat_history.append((question, result['answer']))
52 |
53 | conversation_collection.insert_one({
54 | 'user_name':user_name,
55 | 'user_email':user_email,
56 | 'question':question,
57 | 'answer':result['answer']
58 | })
59 | return result, chat_history
60 |
61 | chat_history=[]
62 |
63 | st.write("**Please provide your name and email address to activate the chabot.**")
64 | user_name = st.text_input("Your Name:")
65 | user_email = st.text_input("Your Email:")
66 |
67 | if user_name and user_email:
68 | question = st.text_input("**If you have any question about this program, please write your question.**", key="input")
69 |
70 | if question:
71 | result, chat_history = ask_with_memory(vector_store, user_name, user_email, question, conversation_collection, chat_history=chat_history)
72 |
73 | # message_history.add_user_message(result["question"])
74 | # message_history.add_ai_message(result["answer"])
75 | st.write(result['answer'])
76 |
77 | with st.form(key='myform', clear_on_submit=True):
78 | message = st.text_area("**Will you be interested in participing in this program? Please answer yes or no.**", height=10)
79 | submit_button = st.form_submit_button("Submit")
80 | if submit_button:
81 | conversation_collection.insert_one({
82 | 'user_name':user_name,
83 | 'user_email':user_email,
84 | 'question':'are you interested in this program?',
85 | 'answer':message})
86 | # if 'yes' in message.lower():
87 | # msg = EmailMessage()
88 | # contacts = [user_email]
89 | # msg['Subject'] = 'Invitation From INTENT'
90 | # msg['From'] = 'dhunganain23@gmail.com'
91 | # msg['To'] = ', '.join(contacts)
92 |
93 | # msg.set_content(f'''\n Dear {user_name},\n\n Hope this email find you well. We would like to invite you to participate in the sustaibale agricuture pilot program. Thank you for showing you interest. Please find the link below to proceed a head: https://intent.ag/ .
94 | # \n
95 | # Thanks\n
96 | # INTENT
97 | # \n''')
98 |
99 | # with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
100 | # smtp.login('dhunganain23@gmail.com', 'dlszoxlqycoidmyi')
101 | # smtp.send_message(msg)
102 | # st.write(f"We have sent you an email with additional information at {user_email}, Please kindly check your email and let us know if you have any other questions")
103 | st.write('Thank you for participating this survey')
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/document_summarize.py:
--------------------------------------------------------------------------------
1 | import os
2 | # from dotenv import load_dotenv, find_dotenv
3 | # load_dotenv(find_dotenv(), override=True)
4 |
5 | import os
6 | import openai
7 | import streamlit as st
8 |
9 | from langchain.chat_models import ChatOpenAI
10 | from langchain import PromptTemplate
11 | from langchain.chains.summarize import load_summarize_chain
12 | from langchain.text_splitter import RecursiveCharacterTextSplitter
13 | from langchain.document_loaders import UnstructuredPDFLoader
14 | import streamlit as st
15 | from tempfile import NamedTemporaryFile
16 | from PyPDF2 import PdfFileReader
17 |
18 | headers = {
19 | "authorization":st.secrets['OPENAI_API_KEY'],
20 | "content-type":"application/json"
21 | }
22 | openai.api_key = st.secrets["OPENAI_API_KEY"]
23 |
24 | st.title('Text Summarization')
25 | #st.write('upload pdf file for summarization')
26 | original_text = 'upload pdf file to extract summary
'
27 | st.markdown(original_text, unsafe_allow_html=True)
28 |
29 | ## Reading input mp4 file and converting it into .mp3 file
30 | uploaded_file = st.sidebar.file_uploader("Upload your pdf file", type="pdf")
31 |
32 | def processing(data):
33 | text_splitter = RecursiveCharacterTextSplitter(chunk_size=10000, chunk_overlap=100)
34 | chunks = text_splitter.split_documents(data)
35 | return chunks
36 |
37 | def get_summary(chunks):
38 | llm = ChatOpenAI(temperature=0, model_name='gpt-3.5-turbo-16k')
39 | prompt_template = """Write a concise summary of the following extracting the key information:
40 | Text: `{text}`
41 | CONCISE SUMMARY:"""
42 | initial_prompt = PromptTemplate(template=prompt_template, input_variables=['text'])
43 | refine_template = '''
44 | Your job is to produce a final summary.
45 | I have provided an existing summary up to a certain point: {existing_answer}.
46 | Please refine the existing summary with some more context below.
47 | ------------
48 | {text}
49 | ------------
50 | Start the final summary with an INTRODUCTION PARAGRAPH that gives an overview of the topic FOLLOWED
51 | by BULLET POINTS AND end the summary with a CONCLUSION PHRASE.
52 |
53 | '''
54 | refine_prompt = PromptTemplate(
55 | template=refine_template,
56 | input_variables=['existing_answer', 'text']
57 | )
58 | chain = load_summarize_chain(
59 | llm=llm,
60 | chain_type='refine',
61 | question_prompt=initial_prompt,
62 | refine_prompt=refine_prompt,
63 | return_intermediate_steps=False,
64 | )
65 | output_summary = chain.run(chunks)
66 | return output_summary
67 |
68 |
69 | if uploaded_file is not None:
70 | st.write('Waiting time depends upon the size of the pdf file.')
71 | temp_file = NamedTemporaryFile(delete=False)
72 | temp_path = temp_file.name
73 | temp_file.close()
74 |
75 | with open(temp_path, "wb") as f:
76 | f.write(uploaded_file.read())
77 |
78 | # Use the saved file path with UnstructuredPDFLoader
79 | loader = UnstructuredPDFLoader(temp_path)
80 | data = loader.load()
81 |
82 | # Delete the temporary file
83 | os.remove(temp_path)
84 |
85 | # my_list = []
86 | # mm = 0
87 | with st.spinner('Model working ...'):
88 | chunks = processing(data)
89 | output=get_summary(chunks)
90 | st.subheader('Summary Report')
91 | st.write(output)
92 |
93 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | openai
2 | streamlit
3 | langchain
4 | pinecone-client
5 | tiktoken
6 | streamlit_chat
7 | pymongo
8 | yagmail
9 | langchain_community
10 | langchain_core
11 | langchain_openai
12 | langchain_experimental
13 | langgraph
14 | pyowm
15 | numexpr
16 | google-search-results
17 | wikipedia
18 |
19 |
20 |
--------------------------------------------------------------------------------