├── .env
├── .gitignore
├── CODE_OF_CONDUCT.md
├── Clippy2.ipynb
├── ClippywithUI.py
├── LICENSE
├── README.md
├── SECURITY.md
├── SUPPORT.md
├── azureAI.ipynb
├── finalRAG.ipynb
├── firstAgent.ipynb
└── requirements.txt
/.env:
--------------------------------------------------------------------------------
1 | OPENAI_API_KEY=dasfadsfsa-dafdafdsfas-sfadsfasdfsd
2 | TAVILY_API_KEY=
3 | LANGCHAIN_API_KEY=
4 | CLIENT_ID=
5 | CLIENT_SECRET=
6 | TENANT_ID=
7 | USERNAME=
8 | AZURE_OPENAI_API_KEY=
9 | AZURE_OPENAI_ENDPOINT=
10 | GRAPH_ACCESS_TOKEN=
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | # but not Directory.Build.rsp, as it configures directory-level build defaults
86 | !Directory.Build.rsp
87 | *.sbr
88 | *.tlb
89 | *.tli
90 | *.tlh
91 | *.tmp
92 | *.tmp_proj
93 | *_wpftmp.csproj
94 | *.log
95 | *.tlog
96 | *.vspscc
97 | *.vssscc
98 | .builds
99 | *.pidb
100 | *.svclog
101 | *.scc
102 |
103 | # Chutzpah Test files
104 | _Chutzpah*
105 |
106 | # Visual C++ cache files
107 | ipch/
108 | *.aps
109 | *.ncb
110 | *.opendb
111 | *.opensdf
112 | *.sdf
113 | *.cachefile
114 | *.VC.db
115 | *.VC.VC.opendb
116 |
117 | # Visual Studio profiler
118 | *.psess
119 | *.vsp
120 | *.vspx
121 | *.sap
122 |
123 | # Visual Studio Trace Files
124 | *.e2e
125 |
126 | # TFS 2012 Local Workspace
127 | $tf/
128 |
129 | # Guidance Automation Toolkit
130 | *.gpState
131 |
132 | # ReSharper is a .NET coding add-in
133 | _ReSharper*/
134 | *.[Rr]e[Ss]harper
135 | *.DotSettings.user
136 |
137 | # TeamCity is a build add-in
138 | _TeamCity*
139 |
140 | # DotCover is a Code Coverage Tool
141 | *.dotCover
142 |
143 | # AxoCover is a Code Coverage Tool
144 | .axoCover/*
145 | !.axoCover/settings.json
146 |
147 | # Coverlet is a free, cross platform Code Coverage Tool
148 | coverage*.json
149 | coverage*.xml
150 | coverage*.info
151 |
152 | # Visual Studio code coverage results
153 | *.coverage
154 | *.coveragexml
155 |
156 | # NCrunch
157 | _NCrunch_*
158 | .*crunch*.local.xml
159 | nCrunchTemp_*
160 |
161 | # MightyMoose
162 | *.mm.*
163 | AutoTest.Net/
164 |
165 | # Web workbench (sass)
166 | .sass-cache/
167 |
168 | # Installshield output folder
169 | [Ee]xpress/
170 |
171 | # DocProject is a documentation generator add-in
172 | DocProject/buildhelp/
173 | DocProject/Help/*.HxT
174 | DocProject/Help/*.HxC
175 | DocProject/Help/*.hhc
176 | DocProject/Help/*.hhk
177 | DocProject/Help/*.hhp
178 | DocProject/Help/Html2
179 | DocProject/Help/html
180 |
181 | # Click-Once directory
182 | publish/
183 |
184 | # Publish Web Output
185 | *.[Pp]ublish.xml
186 | *.azurePubxml
187 | # Note: Comment the next line if you want to checkin your web deploy settings,
188 | # but database connection strings (with potential passwords) will be unencrypted
189 | *.pubxml
190 | *.publishproj
191 |
192 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
193 | # checkin your Azure Web App publish settings, but sensitive information contained
194 | # in these scripts will be unencrypted
195 | PublishScripts/
196 |
197 | # NuGet Packages
198 | *.nupkg
199 | # NuGet Symbol Packages
200 | *.snupkg
201 | # The packages folder can be ignored because of Package Restore
202 | **/[Pp]ackages/*
203 | # except build/, which is used as an MSBuild target.
204 | !**/[Pp]ackages/build/
205 | # Uncomment if necessary however generally it will be regenerated when needed
206 | #!**/[Pp]ackages/repositories.config
207 | # NuGet v3's project.json files produces more ignorable files
208 | *.nuget.props
209 | *.nuget.targets
210 |
211 | # Microsoft Azure Build Output
212 | csx/
213 | *.build.csdef
214 |
215 | # Microsoft Azure Emulator
216 | ecf/
217 | rcf/
218 |
219 | # Windows Store app package directories and files
220 | AppPackages/
221 | BundleArtifacts/
222 | Package.StoreAssociation.xml
223 | _pkginfo.txt
224 | *.appx
225 | *.appxbundle
226 | *.appxupload
227 |
228 | # Visual Studio cache files
229 | # files ending in .cache can be ignored
230 | *.[Cc]ache
231 | # but keep track of directories ending in .cache
232 | !?*.[Cc]ache/
233 |
234 | # Others
235 | ClientBin/
236 | ~$*
237 | *~
238 | *.dbmdl
239 | *.dbproj.schemaview
240 | *.jfm
241 | *.pfx
242 | *.publishsettings
243 | orleans.codegen.cs
244 |
245 | # Including strong name files can present a security risk
246 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
247 | #*.snk
248 |
249 | # Since there are multiple workflows, uncomment next line to ignore bower_components
250 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
251 | #bower_components/
252 |
253 | # RIA/Silverlight projects
254 | Generated_Code/
255 |
256 | # Backup & report files from converting an old project file
257 | # to a newer Visual Studio version. Backup files are not needed,
258 | # because we have git ;-)
259 | _UpgradeReport_Files/
260 | Backup*/
261 | UpgradeLog*.XML
262 | UpgradeLog*.htm
263 | ServiceFabricBackup/
264 | *.rptproj.bak
265 |
266 | # SQL Server files
267 | *.mdf
268 | *.ldf
269 | *.ndf
270 |
271 | # Business Intelligence projects
272 | *.rdl.data
273 | *.bim.layout
274 | *.bim_*.settings
275 | *.rptproj.rsuser
276 | *- [Bb]ackup.rdl
277 | *- [Bb]ackup ([0-9]).rdl
278 | *- [Bb]ackup ([0-9][0-9]).rdl
279 |
280 | # Microsoft Fakes
281 | FakesAssemblies/
282 |
283 | # GhostDoc plugin setting file
284 | *.GhostDoc.xml
285 |
286 | # Node.js Tools for Visual Studio
287 | .ntvs_analysis.dat
288 | node_modules/
289 |
290 | # Visual Studio 6 build log
291 | *.plg
292 |
293 | # Visual Studio 6 workspace options file
294 | *.opt
295 |
296 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
297 | *.vbw
298 |
299 | # Visual Studio 6 auto-generated project file (contains which files were open etc.)
300 | *.vbp
301 |
302 | # Visual Studio 6 workspace and project file (working project files containing files to include in project)
303 | *.dsw
304 | *.dsp
305 |
306 | # Visual Studio 6 technical files
307 | *.ncb
308 | *.aps
309 |
310 | # Visual Studio LightSwitch build output
311 | **/*.HTMLClient/GeneratedArtifacts
312 | **/*.DesktopClient/GeneratedArtifacts
313 | **/*.DesktopClient/ModelManifest.xml
314 | **/*.Server/GeneratedArtifacts
315 | **/*.Server/ModelManifest.xml
316 | _Pvt_Extensions
317 |
318 | # Paket dependency manager
319 | .paket/paket.exe
320 | paket-files/
321 |
322 | # FAKE - F# Make
323 | .fake/
324 |
325 | # CodeRush personal settings
326 | .cr/personal
327 |
328 | # Python Tools for Visual Studio (PTVS)
329 | __pycache__/
330 | *.pyc
331 |
332 | # Cake - Uncomment if you are using it
333 | # tools/**
334 | # !tools/packages.config
335 |
336 | # Tabs Studio
337 | *.tss
338 |
339 | # Telerik's JustMock configuration file
340 | *.jmconfig
341 |
342 | # BizTalk build output
343 | *.btp.cs
344 | *.btm.cs
345 | *.odx.cs
346 | *.xsd.cs
347 |
348 | # OpenCover UI analysis results
349 | OpenCover/
350 |
351 | # Azure Stream Analytics local run output
352 | ASALocalRun/
353 |
354 | # MSBuild Binary and Structured Log
355 | *.binlog
356 |
357 | # NVidia Nsight GPU debugger configuration file
358 | *.nvuser
359 |
360 | # MFractors (Xamarin productivity tool) working folder
361 | .mfractor/
362 |
363 | # Local History for Visual Studio
364 | .localhistory/
365 |
366 | # Visual Studio History (VSHistory) files
367 | .vshistory/
368 |
369 | # BeatPulse healthcheck temp database
370 | healthchecksdb
371 |
372 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
373 | MigrationBackup/
374 |
375 | # Ionide (cross platform F# VS Code tools) working folder
376 | .ionide/
377 |
378 | # Fody - auto-generated XML schema
379 | FodyWeavers.xsd
380 |
381 | # VS Code files for those working on multiple tools
382 | .vscode/*
383 | !.vscode/settings.json
384 | !.vscode/tasks.json
385 | !.vscode/launch.json
386 | !.vscode/extensions.json
387 | *.code-workspace
388 |
389 | # Local History for Visual Studio Code
390 | .history/
391 |
392 | # Windows Installer files from build outputs
393 | *.cab
394 | *.msi
395 | *.msix
396 | *.msm
397 | *.msp
398 |
399 | # JetBrains Rider
400 | *.sln.iml
401 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Microsoft Open Source Code of Conduct
2 |
3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
4 |
5 | Resources:
6 |
7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
10 |
--------------------------------------------------------------------------------
/Clippy2.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 4,
6 | "id": "51139436-d2af-44ca-8d0d-4d3c9848cd96",
7 | "metadata": {},
8 | "outputs": [
9 | {
10 | "name": "stdout",
11 | "output_type": "stream",
12 | "text": [
13 | "Hello! I am your personal companion, Clippy!. Ask me about your meetings. Or the weather. I can answer most things about the world! \n",
14 | "\n",
15 | "---------------------------------------------------------------------------------------------------------\n",
16 | "User prompt: Hey Clippy! I am Sai. I need to go to Paris, France for a work trip. Can you help me plan that?\n",
17 | "\n",
18 | "\n",
19 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
20 | "\u001b[32;1m\u001b[1;3mOf course, Sai! I'd be happy to help you plan your work trip to Paris, France. Here are a few things we can start with:\n",
21 | "\n",
22 | "1. **Check the Weather**: Knowing the current weather in Paris can help you pack appropriately.\n",
23 | "2. **Travel Itinerary**: Do you have specific dates for your travel? I can help you with your flight and accommodation options.\n",
24 | "3. **Events & Meetings**: I can check your calendar for any scheduled events and help you manage your work commitments while you're away.\n",
25 | "4. **Contacts in Paris**: If you need to meet anyone in Paris, I can search for contacts in that location.\n",
26 | "5. **Travel Policies**: I can provide information on your company's travel policies and any necessary approvals.\n",
27 | "6. **Local Information**: If you're interested in any specific places or activities in Paris, I can look them up for you.\n",
28 | "\n",
29 | "Let me know which of these you'd like to start with, or if there's anything else you need!\u001b[0m\n",
30 | "\n",
31 | "\u001b[1m> Finished chain.\u001b[0m\n",
32 | "---------------------------------------------------------------------------------------------------------\n",
33 | "User prompt: Cool! I want to see if I have any important meetings on 11th and 12th of February?\n",
34 | "\n",
35 | "\n",
36 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
37 | "\u001b[32;1m\u001b[1;3m\n",
38 | "Invoking: `getevents` with `{}`\n",
39 | "\n",
40 | "\n",
41 | "\u001b[0m\u001b[33;1m\u001b[1;3m{'@odata.context': \"https://graph.microsoft.com/v1.0/$metadata#users('2be45935-77e0-45e6-a816-42e5966c0b1c')/events\", 'value': [{'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABIv3GKg==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjFAAA=', 'createdDateTime': '2025-01-14T20:14:18.2622852Z', 'lastModifiedDateTime': '2025-01-14T20:14:30.1639677Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABIv3GKg==', 'categories': [], 'transactionId': 'b64881fa-d1a8-1362-12c0-35fcdc2afbe7', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E00800000000846B02E4C066DB01000000000000000010000000B73CA37223FE144494F78B27C63B6AE2', 'uid': '040000008200E00074C5B7101A82E00800000000846B02E4C066DB01000000000000000010000000B73CA37223FE144494F78B27C63B6AE2', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'Dentist Appointment', 'bodyPreview': '', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjFAAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': False, 'onlineMeetingProvider': 'unknown', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': ''}, 'start': {'dateTime': '2025-01-14T18:30:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-14T21:00:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': '', 'locationType': 'default', 'uniqueIdType': 'unknown', 'address': {}, 'coordinates': {}}, 'locations': [], 'recurrence': None, 'attendees': [], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': None, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}, {'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABIv3EOw==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjEAAA=', 'createdDateTime': '2025-01-14T20:13:40.8446921Z', 'lastModifiedDateTime': '2025-01-14T20:13:54.1997294Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABIv3EOw==', 'categories': [], 'transactionId': '9e853702-a0e4-9d5f-1cbb-a544ace5d8bf', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E008000000005138B4CDC066DB01000000000000000010000000DAF763CAFC85D044907D88B292BCF954', 'uid': '040000008200E00074C5B7101A82E008000000005138B4CDC066DB01000000000000000010000000DAF763CAFC85D044907D88B292BCF954', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'Focus Hours', 'bodyPreview': '', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjEAAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': False, 'onlineMeetingProvider': 'unknown', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': ''}, 'start': {'dateTime': '2025-01-17T17:00:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-18T00:00:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': '', 'locationType': 'default', 'uniqueIdType': 'unknown', 'address': {}, 'coordinates': {}}, 'locations': [], 'recurrence': None, 'attendees': [], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': None, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}, {'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABIv2/WA==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjDAAA=', 'createdDateTime': '2025-01-14T17:49:18.040024Z', 'lastModifiedDateTime': '2025-01-14T17:49:50.3802554Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABIv2/WA==', 'categories': [], 'transactionId': '178630b1-38e4-3efa-d112-7cf1d9829ff3', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E00800000000D66744A2AC66DB01000000000000000010000000A5E94F3C1FD4B443BC73C26FE4F9672C', 'uid': '040000008200E00074C5B7101A82E00800000000D66744A2AC66DB01000000000000000010000000A5E94F3C1FD4B443BC73C26FE4F9672C', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'Focus Hours', 'bodyPreview': '', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjDAAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': False, 'onlineMeetingProvider': 'unknown', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': ''}, 'start': {'dateTime': '2025-01-15T18:00:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-15T20:00:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': '', 'locationType': 'default', 'uniqueIdType': 'unknown', 'address': {}, 'coordinates': {}}, 'locations': [], 'recurrence': None, 'attendees': [], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': None, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}, {'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABIv2/mA==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjCAAA=', 'createdDateTime': '2025-01-14T17:49:05.7752435Z', 'lastModifiedDateTime': '2025-01-14T17:51:08.4088329Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABIv2/mA==', 'categories': [], 'transactionId': '051acb34-2a31-12df-c3de-7443384b5c46', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E00800000000EDC5F49AAC66DB01000000000000000010000000BE50350F42D77147945D10B9C0A1B6D1', 'uid': '040000008200E00074C5B7101A82E00800000000EDC5F49AAC66DB01000000000000000010000000BE50350F42D77147945D10B9C0A1B6D1', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'LT Review', 'bodyPreview': '________________________________________________________________________________\\r\\nMicrosoft Teams Need help?\\r\\nJoin the meeting now\\r\\nMeeting ID: 214 526 079 36\\r\\nPasscode: KZ95Ty7e\\r\\n________________________________\\r\\nFor organizers: Meeting options\\r\\n______', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjCAAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': True, 'onlineMeetingProvider': 'teamsForBusiness', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': '\\r\\n
\\r\\n\\r\\n\\r\\n\\r\\n
\\r\\n\\r\\n
________________________________________________________________________________
\\r\\n
\\r\\n
\\r\\n
Meeting ID:\\r\\n214 526 079 36\\r\\n
\\r\\n
Passcode:\\r\\nKZ95Ty7e\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
________________________________________________________________________________
\\r\\n
\\r\\n\\r\\n\\r\\n'}, 'start': {'dateTime': '2025-01-15T21:30:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-15T22:00:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': 'Microsoft Teams Meeting', 'locationType': 'default', 'uniqueId': 'Microsoft Teams Meeting', 'uniqueIdType': 'private'}, 'locations': [{'displayName': 'Microsoft Teams Meeting', 'locationType': 'default', 'uniqueId': 'Microsoft Teams Meeting', 'uniqueIdType': 'private'}], 'recurrence': None, 'attendees': [{'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Nestor Wilke', 'address': 'NestorW@tfdgr.onmicrosoft.com'}}], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': {'joinUrl': 'https://teams.microsoft.com/l/meetup-join/19%3ameeting_OTM0MDVmMTEtNTZlNy00YTJiLWJlZDktNzY5ZDIwYWRkNDEz%40thread.v2/0?context=%7b%22Tid%22%3a%2295e4fdc7-aaab-48b7-a4a2-4b219b877a6d%22%2c%22Oid%22%3a%222be45935-77e0-45e6-a816-42e5966c0b1c%22%7d'}, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}, {'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABIv2/mw==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjBAAA=', 'createdDateTime': '2025-01-14T17:48:39.1592667Z', 'lastModifiedDateTime': '2025-01-14T17:51:49.6303078Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABIv2/mw==', 'categories': [], 'transactionId': '65416d37-9742-0822-e72a-5ddc5016c8b8', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E008000000006066188BAC66DB0100000000000000001000000041C866EE949158408C89869D321A51B4', 'uid': '040000008200E00074C5B7101A82E008000000006066188BAC66DB0100000000000000001000000041C866EE949158408C89869D321A51B4', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'Pitch Deck Review', 'bodyPreview': '________________________________________________________________________________\\r\\nMicrosoft Teams Need help?\\r\\nJoin the meeting now\\r\\nMeeting ID: 216 567 765 744\\r\\nPasscode: k7Z82L5w\\r\\n________________________________\\r\\nFor organizers: Meeting options\\r\\n_____', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEjLBjBAAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': True, 'onlineMeetingProvider': 'teamsForBusiness', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': '\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n
\\r\\n\\r\\n
________________________________________________________________________________
\\r\\n
\\r\\n
\\r\\n
Meeting ID:\\r\\n216 567 765 744\\r\\n
\\r\\n
Passcode:\\r\\nk7Z82L5w\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
________________________________________________________________________________
\\r\\n
\\r\\n\\r\\n\\r\\n'}, 'start': {'dateTime': '2025-01-15T16:30:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-15T18:00:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': 'Microsoft Teams Meeting', 'locationType': 'default', 'uniqueId': 'Microsoft Teams Meeting', 'uniqueIdType': 'private'}, 'locations': [{'displayName': 'Microsoft Teams Meeting', 'locationType': 'default', 'uniqueId': 'Microsoft Teams Meeting', 'uniqueIdType': 'private'}], 'recurrence': None, 'attendees': [{'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Adam Grotesque', 'address': 'adamg@montoso.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Terry Gordo', 'address': 'terryg@montoso.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Lynne Robbins', 'address': 'LynneR@tfdgr.onmicrosoft.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Lee Gu', 'address': 'LeeG@tfdgr.onmicrosoft.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Patti Fernandez', 'address': 'PattiF@tfdgr.onmicrosoft.com'}}], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': {'joinUrl': 'https://teams.microsoft.com/l/meetup-join/19%3ameeting_YTA4ZjFhZGMtODg3Ny00YmUwLWJlNWQtMjFjMTI4NDM4MTI5%40thread.v2/0?context=%7b%22Tid%22%3a%2295e4fdc7-aaab-48b7-a4a2-4b219b877a6d%22%2c%22Oid%22%3a%222be45935-77e0-45e6-a816-42e5966c0b1c%22%7d'}, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}, {'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABHi8AoA==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEeW9V0AAA=', 'createdDateTime': '2025-01-10T17:57:16.6247634Z', 'lastModifiedDateTime': '2025-01-10T17:59:56.6214156Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABHi8AoA==', 'categories': [], 'transactionId': '6ced3088-0dcf-fb21-2da6-43a6398378bf', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E008000000004B8DDF158963DB010000000000000000100000008D19D744D4AFD84BA42C28458C1CB5A7', 'uid': '040000008200E00074C5B7101A82E008000000004B8DDF158963DB010000000000000000100000008D19D744D4AFD84BA42C28458C1CB5A7', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'Pitch Deck Review', 'bodyPreview': '________________________________________________________________________________\\r\\nMicrosoft Teams Need help?\\r\\nJoin the meeting now\\r\\nMeeting ID: 263 681 324 69\\r\\nPasscode: Xo9XY798\\r\\n________________________________\\r\\nFor organizers: Meeting options\\r\\n______', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEeW9V0AAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': True, 'onlineMeetingProvider': 'teamsForBusiness', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': '\\r\\n\\r\\n\\r\\n\\r\\n\\r\\n
\\r\\n\\r\\n
________________________________________________________________________________
\\r\\n
\\r\\n
\\r\\n
Meeting ID:\\r\\n263 681 324 69\\r\\n
\\r\\n
Passcode:\\r\\nXo9XY798\\r\\n
\\r\\n
\\r\\n
\\r\\n\\r\\n
\\r\\n
\\r\\n
\\r\\n
________________________________________________________________________________
\\r\\n
\\r\\n\\r\\n\\r\\n'}, 'start': {'dateTime': '2025-01-10T19:00:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-10T20:00:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': 'Microsoft Teams Meeting', 'locationType': 'default', 'uniqueId': 'Microsoft Teams Meeting', 'uniqueIdType': 'private'}, 'locations': [{'displayName': 'Microsoft Teams Meeting', 'locationType': 'default', 'uniqueId': 'Microsoft Teams Meeting', 'uniqueIdType': 'private'}], 'recurrence': None, 'attendees': [{'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Grady Archie', 'address': 'GradyA@tfdgr.onmicrosoft.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Adam Grotesque', 'address': 'adamg@montoso.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Adele Vance', 'address': 'AdeleV@tfdgr.onmicrosoft.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Lidia Holloway', 'address': 'LidiaH@tfdgr.onmicrosoft.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Johanna Lorenz', 'address': 'JohannaL@tfdgr.onmicrosoft.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Miriam Graham', 'address': 'MiriamG@tfdgr.onmicrosoft.com'}}, {'type': 'required', 'status': {'response': 'none', 'time': '0001-01-01T00:00:00Z'}, 'emailAddress': {'name': 'Isaiah Langer', 'address': 'IsaiahL@tfdgr.onmicrosoft.com'}}], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': {'joinUrl': 'https://teams.microsoft.com/l/meetup-join/19%3ameeting_MDgxNDBhZDgtMThhMy00ZGIxLTk1MjktYjU1YTJiYjZhYmZj%40thread.v2/0?context=%7b%22Tid%22%3a%2295e4fdc7-aaab-48b7-a4a2-4b219b877a6d%22%2c%22Oid%22%3a%222be45935-77e0-45e6-a816-42e5966c0b1c%22%7d'}, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}, {'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABHi8ANA==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEeW9VzAAA=', 'createdDateTime': '2025-01-10T17:56:54.3563722Z', 'lastModifiedDateTime': '2025-01-10T17:56:55.3454895Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABHi8ANA==', 'categories': [], 'transactionId': '09e632e5-ef7b-ebf4-5cf3-368ff8a53bc9', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E0080000000000029A088963DB01000000000000000010000000448D2C88D82F9048A4416E5D5AD6796D', 'uid': '040000008200E00074C5B7101A82E0080000000000029A088963DB01000000000000000010000000448D2C88D82F9048A4416E5D5AD6796D', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'Focus Time', 'bodyPreview': '', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEeW9VzAAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': False, 'onlineMeetingProvider': 'unknown', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': ''}, 'start': {'dateTime': '2025-01-07T17:30:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-07T18:00:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': '', 'locationType': 'default', 'uniqueIdType': 'unknown', 'address': {}, 'coordinates': {}}, 'locations': [], 'recurrence': None, 'attendees': [], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': None, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}, {'@odata.etag': 'W/\"84g3LUa6KEK5yANLVuHCtQABHi8ALQ==\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEeW9VyAAA=', 'createdDateTime': '2025-01-10T17:56:41.3443286Z', 'lastModifiedDateTime': '2025-01-10T17:56:42.7242356Z', 'changeKey': '84g3LUa6KEK5yANLVuHCtQABHi8ALQ==', 'categories': [], 'transactionId': 'd9e89c8c-c04d-5ed6-6812-7872b0d3778a', 'originalStartTimeZone': 'Pacific Standard Time', 'originalEndTimeZone': 'Pacific Standard Time', 'iCalUId': '040000008200E00074C5B7101A82E0080000000019EFD7008963DB010000000000000000100000007384F48105644F43BBAF1DA7D314C553', 'uid': '040000008200E00074C5B7101A82E0080000000019EFD7008963DB010000000000000000100000007384F48105644F43BBAF1DA7D314C553', 'reminderMinutesBeforeStart': 15, 'isReminderOn': True, 'hasAttachments': False, 'subject': 'Pitch Deck Review', 'bodyPreview': '', 'importance': 'normal', 'sensitivity': 'normal', 'isAllDay': False, 'isCancelled': False, 'isOrganizer': True, 'responseRequested': True, 'seriesMasterId': None, 'showAs': 'busy', 'type': 'singleInstance', 'webLink': 'https://outlook.office365.com/owa/?itemid=AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAENAADziDctRrooQrnIA0tW4cK1AAEeW9VyAAA%3D&exvsurl=1&path=/calendar/item', 'onlineMeetingUrl': None, 'isOnlineMeeting': False, 'onlineMeetingProvider': 'unknown', 'allowNewTimeProposals': True, 'occurrenceId': None, 'isDraft': False, 'hideAttendees': False, 'responseStatus': {'response': 'organizer', 'time': '0001-01-01T00:00:00Z'}, 'body': {'contentType': 'html', 'content': ''}, 'start': {'dateTime': '2025-01-08T19:30:00.0000000', 'timeZone': 'UTC'}, 'end': {'dateTime': '2025-01-08T20:30:00.0000000', 'timeZone': 'UTC'}, 'location': {'displayName': '', 'locationType': 'default', 'uniqueIdType': 'unknown', 'address': {}, 'coordinates': {}}, 'locations': [], 'recurrence': None, 'attendees': [], 'organizer': {'emailAddress': {'name': 'Sai Deepthi Kovvuru', 'address': 'iamadmin8390@tfdgr.onmicrosoft.com'}}, 'onlineMeeting': None, 'calendar@odata.associationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')/$ref\", 'calendar@odata.navigationLink': \"https://graph.microsoft.com/v1.0/users('2be45935-77e0-45e6-a816-42e5966c0b1c')/calendars('AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEGAADziDctRrooQrnIA0tW4cK1AAADAVO9AAA=')\"}]}\u001b[0m\u001b[32;1m\u001b[1;3mIt looks like you don't have any meetings scheduled on the 11th and 12th of February, 2025. You're free on those dates! If you need any further assistance, feel free to let me know.\u001b[0m\n",
42 | "\n",
43 | "\u001b[1m> Finished chain.\u001b[0m\n",
44 | "---------------------------------------------------------------------------------------------- \n",
45 | "\n",
46 | "User prompt: Okay. Is there anyone in my contacts in the France office location of Montoso, that I can meet?\n",
47 | "\n",
48 | "\n",
49 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
50 | "\u001b[32;1m\u001b[1;3m\n",
51 | "Invoking: `getcontacts` with `{}`\n",
52 | "\n",
53 | "\n",
54 | "\u001b[0m\u001b[36;1m\u001b[1;3m{'@odata.context': \"https://graph.microsoft.com/v1.0/$metadata#users('2be45935-77e0-45e6-a816-42e5966c0b1c')/contacts\", 'value': [{'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEvcFZW\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEvopeCAAA=', 'createdDateTime': '2025-02-07T21:08:46Z', 'lastModifiedDateTime': '2025-02-07T21:08:47Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEvcFZW', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Chin Bansky', 'givenName': 'Chin', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Bansky', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Sales', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'France', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 732 555 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Chin Bansky', 'address': 'chinb@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq21\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sUAAA=', 'createdDateTime': '2025-01-09T05:10:32Z', 'lastModifiedDateTime': '2025-01-09T05:10:34Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq21', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Lipta Swell', 'givenName': 'Lipta', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Swell', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Accounts', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'USA', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Lipta Swell', 'address': 'liptas@contoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2s\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sTAAA=', 'createdDateTime': '2025-01-09T05:10:00Z', 'lastModifiedDateTime': '2025-01-09T05:10:01Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2s', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Banos Angler', 'givenName': 'Banos', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Angler', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Accounts', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'USA', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Banos Angler', 'address': 'banosa@contoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2g\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sSAAA=', 'createdDateTime': '2025-01-09T05:02:17Z', 'lastModifiedDateTime': '2025-01-09T05:02:19Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2g', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Keira Noko', 'givenName': 'Keira', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Noko', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Accounts', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Keira Noko', 'address': 'keiran@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2X\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sRAAA=', 'createdDateTime': '2025-01-09T05:01:46Z', 'lastModifiedDateTime': '2025-01-09T05:01:47Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2X', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Terry Gordo', 'givenName': 'Terry', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Gordo', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'VP of Sales', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Terry Gordo', 'address': 'terryg@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2O\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sQAAA=', 'createdDateTime': '2025-01-09T05:01:13Z', 'lastModifiedDateTime': '2025-01-09T05:01:14Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2O', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Molly Moon', 'givenName': 'Molly', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Moon', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'HR', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Molly Moon', 'address': 'mollym@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2F\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sPAAA=', 'createdDateTime': '2025-01-09T05:00:28Z', 'lastModifiedDateTime': '2025-01-09T05:00:30Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2F', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Bina Bella', 'givenName': 'Bina', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Bella', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Product Head', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Bina Bella', 'address': 'binab@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmu\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sOAAA=', 'createdDateTime': '2025-01-09T04:59:44Z', 'lastModifiedDateTime': '2025-01-09T04:59:46Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmu', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Adam Grotesque', 'givenName': 'Adam', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Grotesque', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Sales Head', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 732 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Adam Grotesque', 'address': 'adamg@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmc\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sNAAA=', 'createdDateTime': '2025-01-09T04:52:26Z', 'lastModifiedDateTime': '2025-01-09T04:52:28Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmc', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Pavel Bansky', 'givenName': 'Pavel', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Bansky', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': '', 'generation': None, 'imAddresses': [], 'jobTitle': '', 'companyName': None, 'department': '', 'officeLocation': '', 'profession': None, 'businessHomePage': '', 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 732 555 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Pavel Bansky', 'address': 'pavelb@contoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}]}\u001b[0m\u001b[32;1m\u001b[1;3mYou have one contact in the France office location of Montoso:\n",
55 | "\n",
56 | "- **Name:** Chin Bansky\n",
57 | "- **Job Title:** Sales\n",
58 | "- **Company:** Montoso\n",
59 | "- **Office Location:** France\n",
60 | "- **Email:** chinb@montoso.com\n",
61 | "- **Phone:** +1 732 555 0102\n",
62 | "\n",
63 | "You can reach out to Chin Bansky for a meeting.\u001b[0m\n",
64 | "\n",
65 | "\u001b[1m> Finished chain.\u001b[0m\n",
66 | "---------------------------------------------------------------------------------------------- \n",
67 | "\n",
68 | "User prompt: Okay. Can you send Chin a mail with the subject: Can we meet for Lunch? and with body: I am in Paris on 11th and 12th of Feb and can meet you for lunch. Let me know.\n",
69 | "\n",
70 | "\n",
71 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
72 | "\u001b[32;1m\u001b[1;3m\n",
73 | "Invoking: `getcontacts` with `{}`\n",
74 | "\n",
75 | "\n",
76 | "\u001b[0m\u001b[36;1m\u001b[1;3m{'@odata.context': \"https://graph.microsoft.com/v1.0/$metadata#users('2be45935-77e0-45e6-a816-42e5966c0b1c')/contacts\", 'value': [{'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEvcFZW\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEvopeCAAA=', 'createdDateTime': '2025-02-07T21:08:46Z', 'lastModifiedDateTime': '2025-02-07T21:08:47Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEvcFZW', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Chin Bansky', 'givenName': 'Chin', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Bansky', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Sales', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'France', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 732 555 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Chin Bansky', 'address': 'chinb@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq21\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sUAAA=', 'createdDateTime': '2025-01-09T05:10:32Z', 'lastModifiedDateTime': '2025-01-09T05:10:34Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq21', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Lipta Swell', 'givenName': 'Lipta', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Swell', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Accounts', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'USA', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Lipta Swell', 'address': 'liptas@contoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2s\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sTAAA=', 'createdDateTime': '2025-01-09T05:10:00Z', 'lastModifiedDateTime': '2025-01-09T05:10:01Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2s', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Banos Angler', 'givenName': 'Banos', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Angler', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Accounts', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'USA', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Banos Angler', 'address': 'banosa@contoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2g\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sSAAA=', 'createdDateTime': '2025-01-09T05:02:17Z', 'lastModifiedDateTime': '2025-01-09T05:02:19Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2g', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Keira Noko', 'givenName': 'Keira', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Noko', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Accounts', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Keira Noko', 'address': 'keiran@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2X\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sRAAA=', 'createdDateTime': '2025-01-09T05:01:46Z', 'lastModifiedDateTime': '2025-01-09T05:01:47Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2X', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Terry Gordo', 'givenName': 'Terry', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Gordo', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'VP of Sales', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Terry Gordo', 'address': 'terryg@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2O\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sQAAA=', 'createdDateTime': '2025-01-09T05:01:13Z', 'lastModifiedDateTime': '2025-01-09T05:01:14Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2O', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Molly Moon', 'givenName': 'Molly', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Moon', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'HR', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Molly Moon', 'address': 'mollym@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2F\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sPAAA=', 'createdDateTime': '2025-01-09T05:00:28Z', 'lastModifiedDateTime': '2025-01-09T05:00:30Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLq2F', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Bina Bella', 'givenName': 'Bina', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Bella', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Product Head', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 731 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Bina Bella', 'address': 'binab@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmu\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sOAAA=', 'createdDateTime': '2025-01-09T04:59:44Z', 'lastModifiedDateTime': '2025-01-09T04:59:46Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmu', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Adam Grotesque', 'givenName': 'Adam', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Grotesque', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': None, 'generation': None, 'imAddresses': [], 'jobTitle': 'Sales Head', 'companyName': 'Montoso', 'department': None, 'officeLocation': 'Canada', 'profession': None, 'businessHomePage': None, 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 732 575 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Adam Grotesque', 'address': 'adamg@montoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}, {'@odata.etag': 'W/\"EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmc\"', 'id': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQBGAAAAAADKTYktQPcOQahMFVLnvXJEBwDziDctRrooQrnIA0tW4cK1AAAAAAEOAADziDctRrooQrnIA0tW4cK1AAEeW3sNAAA=', 'createdDateTime': '2025-01-09T04:52:26Z', 'lastModifiedDateTime': '2025-01-09T04:52:28Z', 'changeKey': 'EQAAABYAAADziDctRrooQrnIA0tW4cK1AAEeLqmc', 'categories': [], 'parentFolderId': 'AAMkADVlMDNkMDMzLTQ0NWMtNGFjMi1hODVkLWE0YjM0OGE1ZTc0OQAuAAAAAADKTYktQPcOQahMFVLnvXJEAQDziDctRrooQrnIA0tW4cK1AAAAAAEOAAA=', 'birthday': None, 'fileAs': '', 'displayName': 'Pavel Bansky', 'givenName': 'Pavel', 'initials': None, 'middleName': None, 'nickName': None, 'surname': 'Bansky', 'title': None, 'yomiGivenName': None, 'yomiSurname': None, 'yomiCompanyName': '', 'generation': None, 'imAddresses': [], 'jobTitle': '', 'companyName': None, 'department': '', 'officeLocation': '', 'profession': None, 'businessHomePage': '', 'assistantName': '', 'manager': '', 'homePhones': [], 'mobilePhone': '', 'businessPhones': ['+1 732 555 0102'], 'spouseName': '', 'personalNotes': '', 'children': [], 'emailAddresses': [{'name': 'Pavel Bansky', 'address': 'pavelb@contoso.com'}], 'homeAddress': {}, 'businessAddress': {}, 'otherAddress': {}}]}\u001b[0m\u001b[32;1m\u001b[1;3m\n",
77 | "Invoking: `sendmail` with `{'subject': 'Can we meet for Lunch?', 'body': 'I am in Paris on 11th and 12th of Feb and can meet you for lunch. Let me know.', 'email': 'chinb@montoso.com'}`\n",
78 | "\n",
79 | "\n",
80 | "\u001b[0mStatus Code 202\n",
81 | "\u001b[31;1m\u001b[1;3m\u001b[0m\u001b[32;1m\u001b[1;3mI've successfully sent the email to Chin with the subject \"Can we meet for Lunch?\" and the message body you provided. Let me know if there's anything else you need!\u001b[0m\n",
82 | "\n",
83 | "\u001b[1m> Finished chain.\u001b[0m\n"
84 | ]
85 | },
86 | {
87 | "data": {
88 | "text/plain": [
89 | "{'input': 'Okay. Can you send Chin a mail with the subject: Can we meet for Lunch? and with body: I am in Paris on 11th and 12th of Feb and can meet you for lunch. Let me know.',\n",
90 | " 'chat_history': [HumanMessage(content='Hey Clippy! I am Sai. I need to go to Paris, France for a work trip. Can you help me plan that?', additional_kwargs={}, response_metadata={}),\n",
91 | " AIMessage(content=\"Of course, Sai! I'd be happy to help you plan your work trip to Paris, France. Here are a few things we can start with:\\n\\n1. **Check the Weather**: Knowing the current weather in Paris can help you pack appropriately.\\n2. **Travel Itinerary**: Do you have specific dates for your travel? I can help you with your flight and accommodation options.\\n3. **Events & Meetings**: I can check your calendar for any scheduled events and help you manage your work commitments while you're away.\\n4. **Contacts in Paris**: If you need to meet anyone in Paris, I can search for contacts in that location.\\n5. **Travel Policies**: I can provide information on your company's travel policies and any necessary approvals.\\n6. **Local Information**: If you're interested in any specific places or activities in Paris, I can look them up for you.\\n\\nLet me know which of these you'd like to start with, or if there's anything else you need!\", additional_kwargs={}, response_metadata={}),\n",
92 | " HumanMessage(content='Cool! I want to see if I have any important meetings on 11th and 12th of February?', additional_kwargs={}, response_metadata={}),\n",
93 | " AIMessage(content=\"It looks like you don't have any meetings scheduled on the 11th and 12th of February, 2025. You're free on those dates! If you need any further assistance, feel free to let me know.\", additional_kwargs={}, response_metadata={}),\n",
94 | " HumanMessage(content='Okay. Is there anyone in my contacts in the France office location of Montoso, that I can meet?', additional_kwargs={}, response_metadata={}),\n",
95 | " AIMessage(content='You have one contact in the France office location of Montoso:\\n\\n- **Name:** Chin Bansky\\n- **Job Title:** Sales\\n- **Company:** Montoso\\n- **Office Location:** France\\n- **Email:** chinb@montoso.com\\n- **Phone:** +1 732 555 0102\\n\\nYou can reach out to Chin Bansky for a meeting.', additional_kwargs={}, response_metadata={})],\n",
96 | " 'output': 'I\\'ve successfully sent the email to Chin with the subject \"Can we meet for Lunch?\" and the message body you provided. Let me know if there\\'s anything else you need!'}"
97 | ]
98 | },
99 | "execution_count": 4,
100 | "metadata": {},
101 | "output_type": "execute_result"
102 | }
103 | ],
104 | "source": [
105 | "# Import relevant functionality\n",
106 | "import os\n",
107 | "import asyncio\n",
108 | "import requests\n",
109 | "import urllib.parse\n",
110 | "import json\n",
111 | "import configparser\n",
112 | "from datetime import date\n",
113 | "from dotenv import load_dotenv\n",
114 | "from langchain_community.tools.tavily_search import TavilySearchResults\n",
115 | "from msgraph.generated.models.o_data_errors.o_data_error import ODataError\n",
116 | "from configparser import SectionProxy\n",
117 | "from langchain_core.messages import HumanMessage\n",
118 | "from langgraph.checkpoint.memory import MemorySaver\n",
119 | "from langgraph.prebuilt import create_react_agent\n",
120 | "from langchain_openai import ChatOpenAI\n",
121 | "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
122 | "from langgraph.graph import START, MessagesState, StateGraph\n",
123 | "from langchain.agents import AgentType, initialize_agent, load_tools\n",
124 | "from langchain.tools import BaseTool, StructuredTool, tool\n",
125 | "from langchain_openai import OpenAI\n",
126 | "from langchain_core.runnables import ConfigurableField\n",
127 | "from langchain.agents import create_tool_calling_agent, AgentExecutor\n",
128 | "from langchain_core.runnables.history import RunnableWithMessageHistory\n",
129 | "from langchain.agents import AgentExecutor, create_react_agent\n",
130 | "from langchain.memory import ChatMessageHistory\n",
131 | "from dotenv import load_dotenv, find_dotenv\n",
132 | "from configparser import SectionProxy\n",
133 | "from azure.identity import DeviceCodeCredential\n",
134 | "from msgraph import GraphServiceClient\n",
135 | "from langgraph.types import interrupt\n",
136 | "from msgraph.generated.users.users_request_builder import UsersRequestBuilder\n",
137 | "from kiota_abstractions.base_request_configuration import RequestConfiguration\n",
138 | "#MSAL Auth\n",
139 | "import msal\n",
140 | "import jwt\n",
141 | "import json\n",
142 | "import sys\n",
143 | "import requests\n",
144 | "from datetime import datetime as dt\n",
145 | "from msal_extensions import *\n",
146 | "\n",
147 | "# Graph permissions scopes\n",
148 | "# For multiple scopes, separate with a space\n",
149 | "scopes = 'user.read Calendars.Read Calendars.ReadBasic Calendars.Read Calendars.ReadWrite Contacts.Read Mail.Send'\n",
150 | "\n",
151 | "#load the environment\n",
152 | "load_dotenv(override=True)\n",
153 | "\n",
154 | "os.environ[\"OPENAI_API_KEY\"] = os.getenv(\"OPENAI_API_KEY\")\n",
155 | "os.environ[\"TAVILY_API_KEY\"] = os.getenv(\"TAVILY_API_KEY\")\n",
156 | "OPENWEATHERMAP_API_KEY = os.getenv(\"OPENWEATHERMAP_API_KEY\")\n",
157 | "TENANT_GRAPH_ACCESS_TOKEN = os.getenv(\"TENANT_GRAPH_ACCESS_TOKEN\")\n",
158 | "GRAPH_ACCESS_TOKEN = os.getenv(\"GRAPH_ACCESS_TOKEN\")\n",
159 | "TENANT_GRAPH_ACCESS_TOKEN = GRAPH_ACCESS_TOKEN\n",
160 | "CLIENT_ID = os.getenv(\"CLIENT_ID\")\n",
161 | "TENANT_ID = os.getenv(\"TENANT_ID\")\n",
162 | "USERNAME = os.getenv(\"USERNAME\")\n",
163 | "\n",
164 | "#MSAL Auth\n",
165 | "graphURI = 'https://graph.microsoft.com'\n",
166 | "tenantID = TENANT_ID\n",
167 | "authority = 'https://login.microsoftonline.com/' + tenantID\n",
168 | "clientID = CLIENT_ID\n",
169 | "scope = [\"User.Read\",\"Calendars.Read\",\"Calendars.ReadBasic\", \"Calendars.Read\", \"Calendars.ReadWrite\"]\n",
170 | "username = USERNAME\n",
171 | "result = None\n",
172 | "tokenExpiry = None\n",
173 | "\n",
174 | "\n",
175 | "def msal_persistence(location, fallback_to_plaintext=False):\n",
176 | " \"\"\"Build a suitable persistence instance based your current OS\"\"\"\n",
177 | " if sys.platform.startswith('win'):\n",
178 | " return FilePersistenceWithDataProtection(location)\n",
179 | " if sys.platform.startswith('darwin'):\n",
180 | " return KeychainPersistence(location, \"my_service_name\", \"my_account_name\")\n",
181 | " return FilePersistence(location)\n",
182 | "\n",
183 | "def msal_cache_accounts(clientID, authority):\n",
184 | " # Accounts\n",
185 | " persistence = msal_persistence(\"token_cache.bin\")\n",
186 | " #print(\"Is this MSAL persistence cache encrypted?\", persistence.is_encrypted)\n",
187 | " cache = PersistedTokenCache(persistence)\n",
188 | " \n",
189 | " app = msal.PublicClientApplication(\n",
190 | " client_id=clientID, authority=authority, token_cache=cache)\n",
191 | " accounts = app.get_accounts()\n",
192 | " #print(accounts)\n",
193 | " return accounts\n",
194 | "\n",
195 | "def msal_delegated_refresh(clientID, scope, authority, account):\n",
196 | " persistence = msal_persistence(\"token_cache.bin\")\n",
197 | " cache = PersistedTokenCache(persistence)\n",
198 | " \n",
199 | " app = msal.PublicClientApplication(\n",
200 | " client_id=clientID, authority=authority, token_cache=cache)\n",
201 | " result = app.acquire_token_silent_with_error(\n",
202 | " scopes=scope, account=account)\n",
203 | " return result\n",
204 | "\n",
205 | "def msal_delegated_refresh_force(clientID, scope, authority, account):\n",
206 | " persistence = msal_persistence(\"token_cache.bin\")\n",
207 | " cache = PersistedTokenCache(persistence)\n",
208 | " \n",
209 | " app = msal.PublicClientApplication(\n",
210 | " client_id=clientID, authority=authority, token_cache=cache)\n",
211 | " result = app.acquire_token_silent_with_error(\n",
212 | " scopes=scope, account=account, force_refresh=True)\n",
213 | " return result\n",
214 | "\n",
215 | "def msal_delegated_device_flow(clientID, scope, authority):\n",
216 | " #print(\"Initiate Device Code Flow to get an AAD Access Token.\")\n",
217 | " #print(\"Open a browser window and paste in the URL below and then enter the Code. CTRL+C to cancel.\")\n",
218 | " persistence = msal_persistence(\"token_cache.bin\")\n",
219 | " cache = PersistedTokenCache(persistence)\n",
220 | " app = msal.PublicClientApplication(client_id=clientID, authority=authority, token_cache=cache)\n",
221 | " flow = app.initiate_device_flow(scopes=scope)\n",
222 | " if \"user_code\" not in flow:\n",
223 | " raise ValueError(\"Fail to create device flow. Err: %s\" % json.dumps(flow, indent=4))\n",
224 | " print(flow[\"message\"])\n",
225 | " sys.stdout.flush()\n",
226 | " result = app.acquire_token_by_device_flow(flow)\n",
227 | " return result\n",
228 | "\n",
229 | "def msal_jwt_expiry(accessToken):\n",
230 | " decodedAccessToken = jwt.decode(accessToken, verify=False)\n",
231 | " accessTokenFormatted = json.dumps(decodedAccessToken, indent=2)\n",
232 | " # Token Expiry\n",
233 | " tokenExpiry = dt.fromtimestamp(int(decodedAccessToken['exp']))\n",
234 | " #print(\"Token Expires at: \" + str(tokenExpiry))\n",
235 | " return tokenExpiry\n",
236 | "\n",
237 | "def msgraph_request(resource, requestHeaders):\n",
238 | " # Request\n",
239 | " results = requests.get(resource, headers=requestHeaders).json()\n",
240 | " return results\n",
241 | "\n",
242 | "accounts = msal_cache_accounts(clientID, authority)\n",
243 | "if accounts:\n",
244 | " for account in accounts:\n",
245 | " if account['username'] == username:\n",
246 | " myAccount = account\n",
247 | " #print(\"Found account in MSAL Cache: \" + account['username'])\n",
248 | " #print(\"Obtaining a new Access Token using the Refresh Token\")\n",
249 | " result = msal_delegated_refresh(clientID, scope, authority, myAccount)\n",
250 | "\n",
251 | " if result is None:\n",
252 | " # Get a new Access Token using the Device Code Flow\n",
253 | " result = msal_delegated_device_flow(clientID, scope, authority)\n",
254 | " else:\n",
255 | " if result[\"access_token\"]:\n",
256 | " msal_jwt_expiry(result[\"access_token\"]) \n",
257 | "else:\n",
258 | " # Get a new Access Token using the Device Code Flow\n",
259 | " result = msal_delegated_device_flow(clientID, scope, authority)\n",
260 | "\n",
261 | " if result[\"access_token\"]:\n",
262 | " msal_jwt_expiry(result[\"access_token\"])\n",
263 | "\n",
264 | "# End of authentication code\n",
265 | "\n",
266 | "@tool\n",
267 | "async def getevents():\n",
268 | " \"\"\"Get a list of my events from my calendar and display them with the meeting name, subject of the meeting, start dateTime, end dateTime, organizers, participants, date and time.\"\"\"\n",
269 | " # To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python\n",
270 | " requestHeaders = {'Authorization': 'Bearer ' + result[\"access_token\"],'Content-Type': 'application/json'}\n",
271 | " queryResults = msgraph_request(graphURI + \"/v1.0/me/events\",requestHeaders)\n",
272 | " #print(json.dumps(queryResults, indent=2))\n",
273 | " return queryResults\n",
274 | " \n",
275 | "\n",
276 | "@tool\n",
277 | "async def getcontacts():\n",
278 | " \"\"\"Get a list of user's contacts and display with their full name, office location, jobTitle, email id, company name\"\"\"\n",
279 | " requestHeaders = {'Authorization': 'Bearer ' + result[\"access_token\"],'Content-Type': 'application/json'}\n",
280 | " queryResults = msgraph_request(graphURI + \"/v1.0/me/contacts\",requestHeaders)\n",
281 | " #print(json.dumps(queryResults, indent=2))\n",
282 | " return queryResults\n",
283 | "\n",
284 | "\n",
285 | "GRAPH_ACCESS_TOKEN = result[\"access_token\"]\n",
286 | "\n",
287 | "@tool\n",
288 | "def sendmail(subject: str, body: str, email: str) -> str:\n",
289 | " \"\"\"Send a mail to the email address provided with the Subject provided in the subject and Body provided in the body as the user.\"\"\"\n",
290 | " url = \"https://graph.microsoft.com/v1.0/me/sendMail\"\n",
291 | " headers = {\n",
292 | " \"Authorization\": f\"Bearer {GRAPH_ACCESS_TOKEN}\"}\n",
293 | " data = {\n",
294 | " \"message\": {\n",
295 | " \"subject\": f\"{subject}\",\n",
296 | " \"body\": {\n",
297 | " \"contentType\": \"Text\",\n",
298 | " \"content\": f\"{body}\"\n",
299 | " },\n",
300 | " \"toRecipients\": [\n",
301 | " {\n",
302 | " \"emailAddress\": {\n",
303 | " \"address\": f\"{email}\"\n",
304 | " }\n",
305 | " }\n",
306 | " ]\n",
307 | " }\n",
308 | " }\n",
309 | " response = requests.post(url, headers=headers, json=data)\n",
310 | " #response = requests.post(url, json=data)\n",
311 | " print(\"Status Code\", response.status_code)\n",
312 | " #print(\"JSON Response \", response.json())\n",
313 | " return response\n",
314 | "\n",
315 | "\n",
316 | "prompt = ChatPromptTemplate.from_messages([\n",
317 | " (\"system\", \"you're a helpful admin assistant who can talk professionally. Your name is Clippy. Please answer all questions knowing that today's date is \"+ date.today().strftime('%m/%d/%Y') +\". You can send emails. Search the web. Whenever someone wants to see their events, use the tool getevents and identify the right start dateTime from the results you get from getEvents tool and answer the user prompt about their availability correctly. Please format the tool responses you get into much more readable format. You can fetch their contacts. You can search the web for anything else you don't understand. You can get their calendar events. You can also give information to users about the holidays in their regions. Their DTO policies. Their timeoff policies. Anything they want to know about their employee benefits. The access_tokens are available in the tools so don't ask the users again.\"), \n",
318 | " (\"human\", \"{input}\"), \n",
319 | " (\"placeholder\", \"{agent_scratchpad}\"),\n",
320 | "])\n",
321 | "\n",
322 | "search = TavilySearchResults(max_results=2)\n",
323 | "\n",
324 | "# all the tools I have access to\n",
325 | "tools = [getcontacts, getevents, search, sendmail]\n",
326 | "\n",
327 | "llm = ChatOpenAI(model=\"gpt-4o\")\n",
328 | "\n",
329 | "# Define a new graph\n",
330 | "workflow = StateGraph(state_schema=MessagesState)\n",
331 | "\n",
332 | "\n",
333 | "# Define the function that calls the model\n",
334 | "async def call_model(state: MessagesState):\n",
335 | " prompt = prompt.invoke(state)\n",
336 | " response = model.ainvoke(prompt)\n",
337 | " return {\"messages\": response}\n",
338 | "\n",
339 | "# Define the (single) node in the graph\n",
340 | "workflow.add_edge(START, \"model\")\n",
341 | "workflow.add_node(\"model\", call_model)\n",
342 | "\n",
343 | "# Add memory\n",
344 | "memory = ChatMessageHistory(session_id=\"test-session\")\n",
345 | "app = workflow.compile(checkpointer=memory)\n",
346 | "\n",
347 | "config = {\"configurable\": {\"thread_id\": \"def234\"}}\n",
348 | "#config = RunnableConfig(recursion_limit=10)\n",
349 | "agent = create_tool_calling_agent(llm, tools, prompt)\n",
350 | "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, trim_intermediate_steps=True)\n",
351 | "agent_with_chat_history = RunnableWithMessageHistory(\n",
352 | " agent_executor,\n",
353 | " lambda session_id: memory,\n",
354 | " input_messages_key=\"input\",\n",
355 | " history_messages_key=\"chat_history\",\n",
356 | ")\n",
357 | "\n",
358 | "print(\"Hello! I am your personal companion, Clippy!. Ask me about your meetings. Or the weather. I can answer most things about the world!\",\"\\n\")\n",
359 | "\n",
360 | "\n",
361 | "query=\"Hey Clippy! I am Sai. I need to go to Paris, France for a work trip. Can you help me plan that?\"\n",
362 | "print(\"---------------------------------------------------------------------------------------------------------\")\n",
363 | "print(\"User prompt: \",query)\n",
364 | "\n",
365 | "\n",
366 | "\n",
367 | "await agent_with_chat_history.ainvoke(\n",
368 | " {\"input\": query},\n",
369 | " config={\"configurable\": {\"session_id\": \"def234\"}},\n",
370 | ")\n",
371 | "\n",
372 | "\n",
373 | "query=\"Cool! I want to see if I have any important meetings on 11th and 12th of February?\"\n",
374 | "print(\"---------------------------------------------------------------------------------------------------------\")\n",
375 | "print(\"User prompt: \",query)\n",
376 | "\n",
377 | "\n",
378 | "\n",
379 | "await agent_with_chat_history.ainvoke(\n",
380 | " {\"input\": query},\n",
381 | " config={\"configurable\": {\"session_id\": \"def234\"}},\n",
382 | ")\n",
383 | "\n",
384 | "\n",
385 | "query=\"Okay. Is there anyone in my contacts in the France office location of Montoso, that I can meet?\"\n",
386 | "print(\"----------------------------------------------------------------------------------------------\",\"\\n\")\n",
387 | "print(\"User prompt: \",query)\n",
388 | " \n",
389 | "await agent_with_chat_history.ainvoke(\n",
390 | " {\"input\": query},\n",
391 | " config={\"configurable\": {\"session_id\": \"def234\"}},\n",
392 | ")\n",
393 | "\n",
394 | "query=\"Okay. Can you send Chin a mail with the subject: Can we meet for Lunch? and with body: I am in Paris on 11th and 12th of Feb and can meet you for lunch. Let me know.\"\n",
395 | "print(\"----------------------------------------------------------------------------------------------\",\"\\n\")\n",
396 | "print(\"User prompt: \",query)\n",
397 | " \n",
398 | "await agent_with_chat_history.ainvoke(\n",
399 | " {\"input\": query},\n",
400 | " config={\"configurable\": {\"session_id\": \"def234\"}},\n",
401 | ")\n"
402 | ]
403 | },
404 | {
405 | "cell_type": "code",
406 | "execution_count": null,
407 | "id": "b5a0bb48-9d27-49e8-9136-2868a2c6878f",
408 | "metadata": {},
409 | "outputs": [],
410 | "source": []
411 | },
412 | {
413 | "cell_type": "code",
414 | "execution_count": null,
415 | "id": "676e73d0-5b17-4eb6-9dcf-03c05419fbf4",
416 | "metadata": {},
417 | "outputs": [],
418 | "source": []
419 | }
420 | ],
421 | "metadata": {
422 | "kernelspec": {
423 | "display_name": "Python 3 (ipykernel)",
424 | "language": "python",
425 | "name": "python3"
426 | },
427 | "language_info": {
428 | "codemirror_mode": {
429 | "name": "ipython",
430 | "version": 3
431 | },
432 | "file_extension": ".py",
433 | "mimetype": "text/x-python",
434 | "name": "python",
435 | "nbconvert_exporter": "python",
436 | "pygments_lexer": "ipython3",
437 | "version": "3.12.9"
438 | }
439 | },
440 | "nbformat": 4,
441 | "nbformat_minor": 5
442 | }
443 |
--------------------------------------------------------------------------------
/ClippywithUI.py:
--------------------------------------------------------------------------------
1 | from langchain.prompts import ChatPromptTemplate
2 | from langchain.schema import StrOutputParser
3 | from langchain.schema.runnable import Runnable
4 | from langchain.schema.runnable.config import RunnableConfig
5 | import getpass
6 | import os
7 | from langchain_openai import ChatOpenAI
8 | from langchain_core.messages import HumanMessage, SystemMessage
9 | from dotenv import load_dotenv
10 | import chainlit as cl
11 | import asyncio
12 | import requests
13 | import urllib.parse
14 | import json
15 | import configparser
16 | from datetime import date
17 | from langchain_community.tools.tavily_search import TavilySearchResults
18 | from msgraph.generated.models.o_data_errors.o_data_error import ODataError
19 | from configparser import SectionProxy
20 | from langchain_core.messages import HumanMessage
21 | from langgraph.checkpoint.memory import MemorySaver
22 | from langgraph.prebuilt import create_react_agent
23 | from langchain_openai import ChatOpenAI
24 | from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
25 | from langgraph.graph import START, MessagesState, StateGraph
26 | from langchain.agents import AgentType, initialize_agent, load_tools
27 | from langchain.tools import BaseTool, StructuredTool, tool
28 | from langchain_openai import OpenAI
29 | from langchain_core.runnables import ConfigurableField
30 | from langchain.agents import create_tool_calling_agent, AgentExecutor
31 | from langchain_core.runnables.history import RunnableWithMessageHistory
32 | from langchain.agents import AgentExecutor, create_react_agent
33 | from langchain.memory import ChatMessageHistory
34 | from dotenv import load_dotenv, find_dotenv
35 | from configparser import SectionProxy
36 | from azure.identity import DeviceCodeCredential
37 | from msgraph import GraphServiceClient
38 | from langgraph.types import interrupt
39 | from msgraph.generated.users.users_request_builder import UsersRequestBuilder
40 | from kiota_abstractions.base_request_configuration import RequestConfiguration
41 | from typing import Literal
42 | from langgraph.prebuilt import ToolNode
43 | from langchain.schema.runnable.config import RunnableConfig
44 | from langgraph.errors import GraphRecursionError
45 | from langgraph.checkpoint.memory import MemorySaver
46 | #MSAL Auth
47 | import msal
48 | import jwt
49 | import json
50 | import sys
51 | import requests
52 | from datetime import datetime as dt
53 | from datetime import date
54 | from msal_extensions import *
55 |
56 |
57 | #load the environment
58 | load_dotenv(override=True)
59 |
60 |
61 | os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")
62 | os.environ["TAVILY_API_KEY"] = os.getenv("TAVILY_API_KEY")
63 | OPENWEATHERMAP_API_KEY = os.getenv("OPENWEATHERMAP_API_KEY")
64 | TENANT_GRAPH_ACCESS_TOKEN = os.getenv("TENANT_GRAPH_ACCESS_TOKEN")
65 | CLIENT_ID = os.getenv("CLIENT_ID")
66 | TENANT_ID = os.getenv("TENANT_ID")
67 | USERNAME = os.getenv("USERNAME")
68 | os.environ["LANGCHAIN_TRACING_V2"] = "true"
69 | os.environ["LANGCHAIN_API_KEY"] = os.getenv("LANGCHAIN_API_KEY")
70 |
71 |
72 |
73 | #MSAL Auth
74 | graphURI = 'https://graph.microsoft.com'
75 | tenantID = TENANT_ID
76 | authority = 'https://login.microsoftonline.com/' + tenantID
77 | clientID = CLIENT_ID
78 | scope = ["User.Read","Calendars.Read","Calendars.ReadBasic", "Calendars.Read", "Calendars.ReadWrite"]
79 | username = USERNAME
80 | result = None
81 | tokenExpiry = None
82 |
83 | def msal_persistence(location, fallback_to_plaintext=False):
84 | """Build a suitable persistence instance based your current OS"""
85 | if sys.platform.startswith('win'):
86 | return FilePersistenceWithDataProtection(location)
87 | if sys.platform.startswith('darwin'):
88 | return KeychainPersistence(location, "my_service_name", "my_account_name")
89 | return FilePersistence(location)
90 |
91 | def msal_cache_accounts(clientID, authority):
92 | # Accounts
93 | persistence = msal_persistence("token_cache.bin")
94 | #print("Is this MSAL persistence cache encrypted?", persistence.is_encrypted)
95 | cache = PersistedTokenCache(persistence)
96 |
97 | app = msal.PublicClientApplication(
98 | client_id=clientID, authority=authority, token_cache=cache)
99 | accounts = app.get_accounts()
100 | #print(accounts)
101 | return accounts
102 |
103 | def msal_delegated_refresh(clientID, scope, authority, account):
104 | persistence = msal_persistence("token_cache.bin")
105 | cache = PersistedTokenCache(persistence)
106 |
107 | app = msal.PublicClientApplication(
108 | client_id=clientID, authority=authority, token_cache=cache)
109 | result = app.acquire_token_silent_with_error(
110 | scopes=scope, account=account)
111 | return result
112 |
113 | def msal_delegated_refresh_force(clientID, scope, authority, account):
114 | persistence = msal_persistence("token_cache.bin")
115 | cache = PersistedTokenCache(persistence)
116 |
117 | app = msal.PublicClientApplication(
118 | client_id=clientID, authority=authority, token_cache=cache)
119 | result = app.acquire_token_silent_with_error(
120 | scopes=scope, account=account, force_refresh=True)
121 | return result
122 |
123 | def msal_delegated_device_flow(clientID, scope, authority):
124 | #print("Initiate Device Code Flow to get an AAD Access Token.")
125 | #print("Open a browser window and paste in the URL below and then enter the Code. CTRL+C to cancel.")
126 | persistence = msal_persistence("token_cache.bin")
127 | cache = PersistedTokenCache(persistence)
128 | app = msal.PublicClientApplication(client_id=clientID, authority=authority, token_cache=cache)
129 | flow = app.initiate_device_flow(scopes=scope)
130 | if "user_code" not in flow:
131 | raise ValueError("Fail to create device flow. Err: %s" % json.dumps(flow, indent=4))
132 | print(flow["message"])
133 | sys.stdout.flush()
134 | result = app.acquire_token_by_device_flow(flow)
135 | return result
136 |
137 | def msal_jwt_expiry(accessToken):
138 | decodedAccessToken = jwt.decode(accessToken, verify=False)
139 | accessTokenFormatted = json.dumps(decodedAccessToken, indent=2)
140 | # Token Expiry
141 | tokenExpiry = dt.fromtimestamp(int(decodedAccessToken['exp']))
142 | #print("Token Expires at: " + str(tokenExpiry))
143 | return tokenExpiry
144 |
145 |
146 | def msgraph_request(resource, requestHeaders):
147 | # Request
148 | results = requests.get(resource, headers=requestHeaders).json()
149 | return results
150 |
151 | accounts = msal_cache_accounts(clientID, authority)
152 | if accounts:
153 | for account in accounts:
154 | if account['username'] == username:
155 | myAccount = account
156 | #print("Found account in MSAL Cache: " + account['username'])
157 | #print("Obtaining a new Access Token using the Refresh Token")
158 | result = msal_delegated_refresh(clientID, scope, authority, myAccount)
159 |
160 | if result is None:
161 | # Get a new Access Token using the Device Code Flow
162 | result = msal_delegated_device_flow(clientID, scope, authority)
163 | else:
164 | if result["access_token"]:
165 | msal_jwt_expiry(result["access_token"])
166 | else:
167 | # Get a new Access Token using the Device Code Flow
168 | result = msal_delegated_device_flow(clientID, scope, authority)
169 |
170 | if result["access_token"]:
171 | msal_jwt_expiry(result["access_token"])
172 |
173 | GRAPH_ACCESS_TOKEN =result["access_token"]
174 | # End of authentication code
175 |
176 | @tool
177 | async def getevents():
178 | """Get a list of my events from my calendar and display them with the meeting name, subject of the meeting, start dateTime, end dateTime, organizers, participants, date and time."""
179 | # To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python
180 | print("using getevents tool")
181 | requestHeaders = {'Authorization': 'Bearer ' + result["access_token"],'Content-Type': 'application/json'}
182 | queryResults = msgraph_request(graphURI + "/v1.0/me/events",requestHeaders)
183 | #print(json.dumps(queryResults, indent=2))
184 | return queryResults
185 |
186 |
187 | @tool
188 | async def getcontacts():
189 | """Get a list of my contacts and display with their full name, office location, email id, company name"""
190 | print("using getevents tool")
191 | requestHeaders = {'Authorization': 'Bearer ' + result["access_token"],'Content-Type': 'application/json'}
192 | queryResults = msgraph_request(graphURI + "/v1.0/me/contacts",requestHeaders)
193 | #print(json.dumps(queryResults, indent=2))
194 | return queryResults
195 |
196 |
197 | @tool
198 | def sendmail(subject: str, body: str, email: str) -> str:
199 | """Send a mail to the email address provided with the Subject provided in the subject and Body provided in the body as the user.Send an empty body if there is no body in the user query. Do not sign the mail."""
200 | url = "https://graph.microsoft.com/v1.0/me/sendMail"
201 | headers = {
202 | "Authorization": f"Bearer {GRAPH_ACCESS_TOKEN}"}
203 | data = {
204 | "message": {
205 | "subject": f"{subject}",
206 | "body": {
207 | "contentType": "Text",
208 | "content": f"{body}"
209 | },
210 | "toRecipients": [
211 | {
212 | "emailAddress": {
213 | "address": f"{email}"
214 | }
215 | }
216 | ]
217 | }
218 | }
219 | response = requests.post(url, headers=headers, json=data)
220 | #response = requests.post(url, json=data)
221 | print("Status Code", response.status_code)
222 | #print("JSON Response ", response.json())
223 | return response
224 |
225 | llm = ChatOpenAI(model="gpt-4o")
226 |
227 | prompt = ChatPromptTemplate.from_messages([
228 | ("system", "you're a helpful admin assistant who can send emails on behalf of the user. Your name is Clippy. Please answer all questions knowing that today's date is"+ date.today().strftime('%m/%d/%Y') +"Whenever someone wants to see their events, use the tool getevents and identify the right start dateTime from the results you get from getEvents tool and answer the user prompt about their availability correctly. Please format the tool responses you get into much more readable format. You can fetch their contacts. You can search the web for anything else you don't understand. You can get their calendar events. You can also give information to users about the holidays in their regions. Their DTO policies. Their timeoff policies. Anything they want to know about their employee benefits. The access_tokens are available in the tools so don't ask the users again."),
229 | ("human", "{input}"),
230 | ("placeholder", "{agent_scratchpad}"),
231 | ])
232 |
233 | search = TavilySearchResults(max_results=2)
234 |
235 | # all the tools I have access to
236 | tools = [getcontacts, getevents, sendmail, search]
237 |
238 | model = ChatOpenAI(model="gpt-4o-mini", temperature=0, max_retries=2)
239 |
240 |
241 | llm = ChatOpenAI(model="gpt-4o")
242 |
243 | # Define a new graph
244 | workflow = StateGraph(state_schema=MessagesState)
245 |
246 |
247 | # Define the function that calls the model
248 | async def call_model(state: MessagesState):
249 | prompt = prompt.invoke(state)
250 | response = model.ainvoke(prompt)
251 | return {"messages": response}
252 |
253 | # Define the (single) node in the graph
254 | workflow.add_edge(START, "model")
255 | workflow.add_node("model", call_model)
256 |
257 | # Add memory
258 | memory = ChatMessageHistory(session_id="test-session")
259 | app = workflow.compile(checkpointer=memory)
260 |
261 | agent = create_tool_calling_agent(model, tools, prompt)
262 | langgraph_agent_executor = agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, trim_intermediate_steps=True)
263 | agent_with_chat_history = RunnableWithMessageHistory(
264 | langgraph_agent_executor,
265 | lambda session_id: memory,
266 | input_messages_key="input",
267 | history_messages_key="chat_history",
268 | )
269 |
270 | config = {"configurable": {"thread_id": "def234"}}
271 |
272 | @cl.on_chat_start
273 | async def on_chat_start():
274 | await cl.Message(content="Hello! I am your personal companion, Clippy! Ask me about your meetings. Or the weather. I can answer most things about the world!").send()
275 | cl.user_session.set("langgraph_agent_executor", langgraph_agent_executor)
276 |
277 | @cl.on_message
278 | async def handle_message(message: cl.Message):
279 | langgraph_agent_executor = cl.user_session.get("langgraph_agent_executor")
280 | prompt = ChatPromptTemplate.from_messages([
281 | ("system", "you're a helpful admin assistant who can send mails on behalf of users. You can answer simple questions like country capitals without using any tools. You can search the web. Your name is Clippy. Please answer all questions knowing that today's date is "+ date.today().strftime('%m/%d/%Y') +". Whenever someone wants to see their events, use the tool getevents and identify the right start dateTime from the results you get from getEvents tool and answer the user prompt about their availability correctly. Please format the tool responses you get into much more readable format. You can fetch their contacts. You can search the web for anything else you don't understand. You can get their calendar events. You can also give information to users about the holidays in their regions. Their DTO policies. Their timeoff policies. Anything they want to know about their employee benefits. The access_tokens are available in the tools so don't ask the users again."),
282 | ("human", message.content),
283 | ("placeholder", "{agent_scratchpad}"),
284 | ])
285 | agent = create_tool_calling_agent(model, tools, prompt)
286 | langgraph_agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, trim_intermediate_steps=True)
287 | agent_with_chat_history = RunnableWithMessageHistory(
288 | langgraph_agent_executor,
289 | lambda session_id: memory,
290 | input_messages_key="input",
291 | history_messages_key="chat_history",
292 | )
293 |
294 |
295 | # Invoke the LangGraph agent executor
296 | config = {"configurable": {"session_id": "def234"}}
297 |
298 | async for chunk in agent_with_chat_history.astream(
299 | {"messages": [HumanMessage(content=message.content)]}, config
300 | ):
301 | print(chunk)
302 | if 'output' in chunk:
303 | # Do something if the object has the 'my_field' attribute
304 | print("Object has the attribute")
305 | await cl.Message(chunk['output']).send()
306 | else:
307 | cl.Message("Processing step:","\n")
308 | await cl.Message(chunk).send()
309 | print("----")
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository contains sample agentic applications in python that can talk to Azure AI and OpenAI models and perform complex tasks based on user queries.
2 |
3 | ## Prerequisites
4 |
5 | 1. You need an OpenAI API Key, Tavily Search API Key, Open Weather Map API Key and M365 Developer Tenant
6 | 2. You will need to buy a license to use the OpenAI GPT models
7 | 3. Alternatively, you can use AzureAI models by deploying your models using your Azure subscription. Steps are here --> https://learn.microsoft.com/en-us/azure/ai-foundry/model-inference/concepts/endpoints?tabs=python
8 | 4. You will need to create an app registration in Azure portal. Use the following steps - https://learn.microsoft.com/en-us/graph/tutorials/python?tabs=aad&tutorial-step=1
9 | 5. Save the ClientID and the TenantID from this app you created.
10 | 6. You need to install Python, Jupyter notebook, PIP on your system. I am using Windows 11.
11 | 7. You need to install the following Python Packages - Jupyter, Python, LangChain, MSGraph, AzureIdentity
12 |
13 | ## Steps to get your first Agent running
14 |
15 | 1. Clone this repository
16 | 2. Go to the folder where you downloaded the repository.
17 | 3. Open the .env file and add your keys that you obtained from OpenAI, Tavily, Open Weather Map, etc.
18 | 4. Add ClientID and the TenantID
19 | 5. Save and Close the file.
20 | 6. Run the following command to ensure all the right libraries are installed --> pip install --requirement=.\requirements.txt
21 | 7. Open Command Prompt and go to the folder where the repository is.
22 | 8. Type the following command - jupyter notebook
23 | 9. This will open a web page that contains all your scripts.
24 | 10. Click on first Agent script and it will open in a separate page.
25 | 11. Click on the run icon.
26 | 12. You should see the output on the line below.
27 |
28 |
29 | ## Getting the Clippy2 Agent running
30 | 1. This is a more advanced Agent and to run it, you will need to access Microsoft Graph SDKs.
31 | 2. Follow this tutorial --> https://learn.microsoft.com/en-us/microsoft-365-copilot/extensibility/graph-api-tutorial
32 |
33 | ## Feedback
34 | If you have any feedback, please send a mail to sakov@microsoft.com and I will get back.
35 |
36 | ## Contributing
37 |
38 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
39 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
40 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
41 |
42 | When you submit a pull request, a CLA bot will automatically determine whether you need to provide
43 | a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
44 | provided by the bot. You will only need to do this once across all repos using our CLA.
45 |
46 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
47 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
48 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
49 |
50 | ## Trademarks
51 |
52 | This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
53 | trademarks or logos is subject to and must follow
54 | [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
55 | Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
56 | Any use of third-party trademarks or logos are subject to those third-party's policies.
57 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # TODO: The maintainer of this repo has not yet edited this file
2 |
3 | **REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project?
4 |
5 | - **No CSS support:** Fill out this template with information about how to file issues and get help.
6 | - **Yes CSS support:** Fill out an intake form at [aka.ms/onboardsupport](https://aka.ms/onboardsupport). CSS will work with/help you to determine next steps.
7 | - **Not sure?** Fill out an intake as though the answer were "Yes". CSS will help you decide.
8 |
9 | *Then remove this first heading from this SUPPORT.MD file before publishing your repo.*
10 |
11 | # Support
12 |
13 | ## How to file issues and get help
14 |
15 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing
16 | issues before filing new issues to avoid duplicates. For new issues, file your bug or
17 | feature request as a new Issue.
18 |
19 | For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE
20 | FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER
21 | CHANNEL. WHERE WILL YOU HELP PEOPLE?**.
22 |
23 | ## Microsoft Support Policy
24 |
25 | Support for this **PROJECT or PRODUCT** is limited to the resources listed above.
26 |
--------------------------------------------------------------------------------
/azureAI.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 4,
6 | "id": "afdec5df-fad2-48fe-a3f5-0bc92b70db98",
7 | "metadata": {},
8 | "outputs": [
9 | {
10 | "name": "stdout",
11 | "output_type": "stream",
12 | "text": [
13 | "Sure! Here's one for you:\n",
14 | "\n",
15 | "Why don’t skeletons fight each other?\n",
16 | "\n",
17 | "Because they don’t have the guts! 😄\n"
18 | ]
19 | }
20 | ],
21 | "source": [
22 | "from dotenv import load_dotenv\n",
23 | "import os\n",
24 | "from langchain_openai import AzureChatOpenAI\n",
25 | "\n",
26 | "#load the environment\n",
27 | "load_dotenv(override=True)\n",
28 | "\n",
29 | "os.environ[\"AZURE_OPENAI_API_KEY\"] = os.getenv(\"AZURE_OPENAI_API_KEY\")\n",
30 | "os.environ[\"AZURE_OPENAI_ENDPOINT\"] = os.getenv(\"AZURE_OPENAI_ENDPOINT\")\n",
31 | "\n",
32 | "llm = AzureChatOpenAI(\n",
33 | " azure_deployment=\"gpt-4o\", # or your deployment\n",
34 | " api_version=\"2024-08-01-preview\", # or your api version\n",
35 | " temperature=0,\n",
36 | " max_tokens=None,\n",
37 | " timeout=None,\n",
38 | " max_retries=2,\n",
39 | " # other params...\n",
40 | ")\n",
41 | "\n",
42 | "ai_msg = llm.invoke(\"Tell me a joke\")\n",
43 | "print(ai_msg.content)"
44 | ]
45 | },
46 | {
47 | "cell_type": "code",
48 | "execution_count": null,
49 | "id": "f8d35630-cb56-4491-8c4d-641708fee5f5",
50 | "metadata": {},
51 | "outputs": [],
52 | "source": []
53 | }
54 | ],
55 | "metadata": {
56 | "kernelspec": {
57 | "display_name": "Python 3 (ipykernel)",
58 | "language": "python",
59 | "name": "python3"
60 | },
61 | "language_info": {
62 | "codemirror_mode": {
63 | "name": "ipython",
64 | "version": 3
65 | },
66 | "file_extension": ".py",
67 | "mimetype": "text/x-python",
68 | "name": "python",
69 | "nbconvert_exporter": "python",
70 | "pygments_lexer": "ipython3",
71 | "version": "3.12.9"
72 | }
73 | },
74 | "nbformat": 4,
75 | "nbformat_minor": 5
76 | }
77 |
--------------------------------------------------------------------------------
/finalRAG.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "id": "cb8c1438-3bfb-4241-a522-b127d54ae19d",
7 | "metadata": {},
8 | "outputs": [
9 | {
10 | "name": "stdout",
11 | "output_type": "stream",
12 | "text": [
13 | "----------------------------------------------------------\n",
14 | "User prompt: Do I Need a Pizza Den Login to Sign into Pizza Den Wi-Fi?\n",
15 | "\n",
16 | "\n",
17 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
18 | "\u001b[32;1m\u001b[1;3m\n",
19 | "Invoking: `ragforPizzaDen` with `{'query': 'Do I Need a Pizza Den Login to Sign into Pizza Den Wi-Fi?'}`\n",
20 | "\n",
21 | "\n",
22 | "\u001b[0mStatus Code 401\n",
23 | "\u001b[38;5;200m\u001b[1;3m\u001b[0m\u001b[32;1m\u001b[1;3mI'm unable to retrieve the information about signing into Pizza Den Wi-Fi at the moment. You might want to check directly with Pizza Den's customer service or their official website for accurate details.\u001b[0m\n",
24 | "\n",
25 | "\u001b[1m> Finished chain.\u001b[0m\n",
26 | "---------------------------------------------------------------------------------------------------------\n",
27 | "User prompt: Which Internet Provider does Pizza Den use for its wifi?\n",
28 | "\n",
29 | "\n",
30 | "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
31 | "\u001b[32;1m\u001b[1;3m\n",
32 | "Invoking: `ragforPizzaDen` with `{'query': 'Internet Provider used by Pizza Den for Wifi'}`\n",
33 | "\n",
34 | "\n",
35 | "\u001b[0mStatus Code 401\n",
36 | "\u001b[38;5;200m\u001b[1;3m\u001b[0m\u001b[32;1m\u001b[1;3mI'm unable to retrieve the information about the Internet Provider used by Pizza Den for its WiFi at the moment. Is there anything else related to Pizza Den that I can assist you with?\u001b[0m\n",
37 | "\n",
38 | "\u001b[1m> Finished chain.\u001b[0m\n"
39 | ]
40 | },
41 | {
42 | "data": {
43 | "text/plain": [
44 | "{'input': 'Which Internet Provider does Pizza Den use for its wifi?',\n",
45 | " 'chat_history': [HumanMessage(content='Do I Need a Pizza Den Login to Sign into Pizza Den Wi-Fi?', additional_kwargs={}, response_metadata={}),\n",
46 | " AIMessage(content=\"I'm unable to retrieve the information about signing into Pizza Den Wi-Fi at the moment. You might want to check directly with Pizza Den's customer service or their official website for accurate details.\", additional_kwargs={}, response_metadata={})],\n",
47 | " 'output': \"I'm unable to retrieve the information about the Internet Provider used by Pizza Den for its WiFi at the moment. Is there anything else related to Pizza Den that I can assist you with?\"}"
48 | ]
49 | },
50 | "execution_count": 7,
51 | "metadata": {},
52 | "output_type": "execute_result"
53 | }
54 | ],
55 | "source": [
56 | "# Import relevant functionality\n",
57 | "import os\n",
58 | "import asyncio\n",
59 | "import requests\n",
60 | "import urllib.parse\n",
61 | "import json\n",
62 | "import configparser\n",
63 | "from datetime import date\n",
64 | "from msgraph.generated.models.o_data_errors.o_data_error import ODataError\n",
65 | "from configparser import SectionProxy\n",
66 | "from langchain_core.messages import HumanMessage\n",
67 | "from langgraph.checkpoint.memory import MemorySaver\n",
68 | "from langgraph.prebuilt import create_react_agent\n",
69 | "from langchain_openai import ChatOpenAI\n",
70 | "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
71 | "from langgraph.graph import START, MessagesState, StateGraph\n",
72 | "from langchain.agents import AgentType, initialize_agent, load_tools\n",
73 | "from langchain.tools import BaseTool, StructuredTool, tool\n",
74 | "from langchain_openai import OpenAI\n",
75 | "from langchain_core.runnables import ConfigurableField\n",
76 | "from langchain.agents import create_tool_calling_agent, AgentExecutor\n",
77 | "from langchain_core.runnables.history import RunnableWithMessageHistory\n",
78 | "from langchain.agents import AgentExecutor, create_react_agent\n",
79 | "from langchain.memory import ChatMessageHistory\n",
80 | "from dotenv import load_dotenv\n",
81 | "from configparser import SectionProxy\n",
82 | "from azure.identity import DeviceCodeCredential\n",
83 | "from langgraph.types import interrupt\n",
84 | "from msgraph_beta import GraphServiceClient\n",
85 | "from langchain_core.messages import HumanMessage\n",
86 | "from langgraph.checkpoint.memory import MemorySaver\n",
87 | "from langgraph.prebuilt import create_react_agent\n",
88 | "from langchain_openai import ChatOpenAI\n",
89 | "from langchain_core.prompts import ChatPromptTemplate\n",
90 | "from typing import Annotated, Sequence\n",
91 | "from langchain_core.messages import BaseMessage\n",
92 | "from langchain_core.runnables import RunnableConfig\n",
93 | "from langchain_core.tools import tool\n",
94 | "from langgraph.graph import END, StateGraph\n",
95 | "from langgraph.graph.message import add_messages\n",
96 | "from langgraph.prebuilt.tool_node import ToolNode\n",
97 | "from typing_extensions import TypedDict\n",
98 | "\n",
99 | "\n",
100 | "# Graph permissions scopes\n",
101 | "# For multiple scopes, separate with a space\n",
102 | "scopes = 'user.read Calendars.Read Files.Read.All Sites.Read.All'\n",
103 | "\n",
104 | "#load the environment\n",
105 | "load_dotenv(\"C:\\\\Users\\\\sakov\\\\bootcamp\\\\LangChain Agents\\\\.env\")\n",
106 | "os.environ[\"OPENAI_API_KEY\"] = os.getenv(\"OPENAI_API_KEY\")\n",
107 | "GRAPH_ACCESS_TOKEN = os.getenv(\"GRAPH_ACCESS_TOKEN\")\n",
108 | "\n",
109 | "\n",
110 | "@tool\n",
111 | "def ragforHR(query: str) -> str:\n",
112 | " \"\"\"Get the answers to user enquiries related to HR queries like holidays, DTO, payroll, benefits, insurance, salary structure and perks for employees belonging to various regions like Puget Sound or Canada\"\"\"\n",
113 | " url = \"https://graph.microsoft.com/beta/copilot/retrieval\"\n",
114 | " headers = {\n",
115 | " \"Authorization\": f\"Bearer {GRAPH_ACCESS_TOKEN}\"}\n",
116 | " data = {\n",
117 | " \"QueryString\": query,\n",
118 | " \"filterExpression\": \"(path:\\\"https://microsoft.sharepoint.com/sites/HRweb/\\\")\",\n",
119 | " \"resourceMetadata\": [\"author\"],\n",
120 | " \"MaximumNumberOfResults\": 4\n",
121 | " }\n",
122 | " response = requests.post(url, headers=headers, json=data)\n",
123 | " print(\"Status Code\", response.status_code)\n",
124 | " #print(\"JSON Response \", response.json())\n",
125 | " return response.json()\n",
126 | "\n",
127 | "\n",
128 | "@tool\n",
129 | "def ragforProduct(query: str) -> str:\n",
130 | " \"\"\"Get the answers to user enquiries related about Microsoft Copilot product. Like the specifications of the Copilot Retrieval API in CCS. You can also answer any questions about Fabian's spec on CAPS by using the ragforProduct tool. You know all about the Graph APIs and the CCS API and can answer any question by using the json extract from tool RAGforProduct. About Copilot API Plugins. About Agents SDK. About Teams AI Library. About MS Graph SDK. About Custom Engine Agents.\"\"\"\n",
131 | " url = \"https://graph.microsoft.com/beta/copilot/retrieval\"\n",
132 | " headers = {\n",
133 | " \"Authorization\": f\"Bearer {GRAPH_ACCESS_TOKEN}\",\n",
134 | " \"Content-Type\": \"application/json; charset=utf-8\"}\n",
135 | " data = {\n",
136 | " \"QueryString\": query,\n",
137 | " \"filterExpression\": \"path:\\\"https://microsoft.sharepoint-df.com/sites/CXDev/Shared%20Documents/Org%20Teams/3P-DevX/Proposals/\\\"\",\n",
138 | " \"resourceMetadata\": [\"author\"],\n",
139 | " \"MaximumNumberOfResults\": 4\n",
140 | " }\n",
141 | " response = requests.post(url, headers=headers, json=data)\n",
142 | " #response = requests.post(url, json=data)\n",
143 | " print(\"Status Code\", response.status_code)\n",
144 | " #print(\"JSON Response \", response.json())\n",
145 | " return response.json()\n",
146 | "\n",
147 | "@tool\n",
148 | "def ragforPizzaDen(query: str) -> str:\n",
149 | " \"\"\"Get the answers to user enquiries related about Pizza Den. You are the QnA bot for Pizza Den website. Answer all user queries about Pizza Den by using this tool.\"\"\"\n",
150 | " url = \"https://graph.microsoft.com/beta/copilot/retrieval\"\n",
151 | " headers = {\n",
152 | " \"Authorization\": f\"Bearer {GRAPH_ACCESS_TOKEN}\",\n",
153 | " \"Content-Type\": \"application/json; charset=utf-8\"}\n",
154 | " data = {\n",
155 | " \"QueryString\": query,\n",
156 | " \"filterExpression\": \"(path:\\\"https://microsoft.sharepoint-df.com/sites/CXDev/Shared%20Documents/Org%20Teams/3P-DevX/Proposals/DummyFiles/\\\")\",\n",
157 | " \"resourceMetadata\": [\"author\"],\n",
158 | " \"MaximumNumberOfResults\": 3\n",
159 | " }\n",
160 | " response = requests.post(url, headers=headers, json=data)\n",
161 | " #response = requests.post(url, json=data)\n",
162 | " print(\"Status Code\", response.status_code)\n",
163 | " #print(\"JSON Response \", response.json())\n",
164 | " return response.json()\n",
165 | "\n",
166 | "\n",
167 | "tools = [ragforHR, ragforProduct, ragforPizzaDen]\n",
168 | "\n",
169 | "llm = ChatOpenAI(model=\"gpt-4o\")\n",
170 | "\n",
171 | "# Define a new graph\n",
172 | "workflow = StateGraph(state_schema=MessagesState)\n",
173 | "\n",
174 | "prompt = ChatPromptTemplate.from_messages([\n",
175 | " (\"system\", \"you're a helpful assistant who knows all about Microsoft HR policies and all about the CxDev product proposals. Always use the tools whenever the questions are related to Microsoft. Do not hallucinate. Answer using only the json extracts from tools provided to you. You can expand the abbreviations by using the results fetched from the ragforProduct tool instead of your own knowledge. Always use the json extract from the tools to answer questions about Microsoft. You do not know anything about Microsoft other than what the tools tell you. Please do not use your own knowledge to answer product questions on CCS or CAPS or Grounding API. Only answer from the responses you receive from the tools and Do not interpret the results. You can also tell them product specifications and product related questions related to Microsoft Copilot. Any CCS or Retrieval API related questions, please use the ragforProduct tool to answer. You know a lot about the Retrieval API. You can also give information to users about the holidays in their regions. Their DTO policies. Their timeoff policies. Anything they want to know about their employee benefits. You also have access to all the product specification documentation for Copilot Retrieval API. And the Grounding API. And the Graph SDK. Answer any questions about the product from these document. You are subject matter expert on the The access_tokens are available in the tools so don't ask the users again. Answer WITHOUT ASKING FOR ACCESS TOKEN AS IT IS AVAILABLE TO YOU. You can find the access tokens and the API keys in the environment files.\"), \n",
176 | " (\"human\", \"{input}\"), \n",
177 | " (\"placeholder\", \"{agent_scratchpad}\"),\n",
178 | "])\n",
179 | "\n",
180 | "# Define the function that calls the model\n",
181 | "async def call_model(state: MessagesState):\n",
182 | " prompt = prompt.invoke(state)\n",
183 | " response = model.ainvoke(prompt)\n",
184 | " return {\"messages\": response}\n",
185 | "\n",
186 | "# Define the (single) node in the graph\n",
187 | "workflow.add_edge(START, \"model\")\n",
188 | "workflow.add_node(\"model\", call_model)\n",
189 | "\n",
190 | "# Add memory\n",
191 | "memory = ChatMessageHistory(session_id=\"test-session\")\n",
192 | "app = workflow.compile(checkpointer=memory)\n",
193 | "\n",
194 | "config = {\"configurable\": {\"thread_id\": \"def234\"}}\n",
195 | "\n",
196 | "agent = create_tool_calling_agent(llm, tools, prompt)\n",
197 | "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)\n",
198 | "agent_with_chat_history = RunnableWithMessageHistory(\n",
199 | " agent_executor,\n",
200 | " lambda session_id: memory,\n",
201 | " input_messages_key=\"input\",\n",
202 | " history_messages_key=\"chat_history\",\n",
203 | ")\n",
204 | "\n",
205 | "query=\"Do I Need a Pizza Den Login to Sign into Pizza Den Wi-Fi?\"\n",
206 | "print(\"----------------------------------------------------------\")\n",
207 | "print(\"User prompt: \",query)\n",
208 | "\n",
209 | "await agent_with_chat_history.ainvoke(\n",
210 | " {\"input\": query},\n",
211 | " config={\"configurable\": {\"session_id\": \"def234\"}},\n",
212 | ")\n",
213 | "\n",
214 | "\n",
215 | "query=\"Which Internet Provider does Pizza Den use for its wifi?\"\n",
216 | "print(\"---------------------------------------------------------------------------------------------------------\")\n",
217 | "print(\"User prompt: \",query)\n",
218 | "\n",
219 | "\n",
220 | "\n",
221 | "await agent_with_chat_history.ainvoke(\n",
222 | " {\"input\": query},\n",
223 | " config={\"configurable\": {\"session_id\": \"def234\"}},\n",
224 | ")"
225 | ]
226 | },
227 | {
228 | "cell_type": "code",
229 | "execution_count": null,
230 | "id": "fa625c08-cb42-41b8-b51a-ae83bb74d0af",
231 | "metadata": {},
232 | "outputs": [],
233 | "source": []
234 | },
235 | {
236 | "cell_type": "code",
237 | "execution_count": null,
238 | "id": "e8a9fbc6-92b9-456c-87b8-b459cfb0cf9a",
239 | "metadata": {},
240 | "outputs": [],
241 | "source": []
242 | }
243 | ],
244 | "metadata": {
245 | "kernelspec": {
246 | "display_name": "Python 3 (ipykernel)",
247 | "language": "python",
248 | "name": "python3"
249 | },
250 | "language_info": {
251 | "codemirror_mode": {
252 | "name": "ipython",
253 | "version": 3
254 | },
255 | "file_extension": ".py",
256 | "mimetype": "text/x-python",
257 | "name": "python",
258 | "nbconvert_exporter": "python",
259 | "pygments_lexer": "ipython3",
260 | "version": "3.12.9"
261 | }
262 | },
263 | "nbformat": 4,
264 | "nbformat_minor": 5
265 | }
266 |
--------------------------------------------------------------------------------
/firstAgent.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": 2,
6 | "id": "f8df60af-f644-4ca0-8f49-1e659788f38f",
7 | "metadata": {},
8 | "outputs": [
9 | {
10 | "name": "stdout",
11 | "output_type": "stream",
12 | "text": [
13 | "Collecting openai\n",
14 | " Downloading openai-1.57.4-py3-none-any.whl.metadata (24 kB)\n",
15 | "Requirement already satisfied: anyio<5,>=3.5.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai) (4.2.0)\n",
16 | "Requirement already satisfied: distro<2,>=1.7.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai) (1.9.0)\n",
17 | "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai) (0.27.0)\n",
18 | "Collecting jiter<1,>=0.4.0 (from openai)\n",
19 | " Downloading jiter-0.8.2-cp312-cp312-win_amd64.whl.metadata (5.3 kB)\n",
20 | "Requirement already satisfied: pydantic<3,>=1.9.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai) (2.8.2)\n",
21 | "Requirement already satisfied: sniffio in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai) (1.3.0)\n",
22 | "Requirement already satisfied: tqdm>4 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai) (4.66.5)\n",
23 | "Requirement already satisfied: typing-extensions<5,>=4.11 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai) (4.11.0)\n",
24 | "Requirement already satisfied: idna>=2.8 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from anyio<5,>=3.5.0->openai) (3.7)\n",
25 | "Requirement already satisfied: certifi in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->openai) (2024.8.30)\n",
26 | "Requirement already satisfied: httpcore==1.* in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->openai) (1.0.2)\n",
27 | "Requirement already satisfied: h11<0.15,>=0.13 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n",
28 | "Requirement already satisfied: annotated-types>=0.4.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3,>=1.9.0->openai) (0.6.0)\n",
29 | "Requirement already satisfied: pydantic-core==2.20.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3,>=1.9.0->openai) (2.20.1)\n",
30 | "Requirement already satisfied: colorama in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from tqdm>4->openai) (0.4.6)\n",
31 | "Downloading openai-1.57.4-py3-none-any.whl (390 kB)\n",
32 | "Downloading jiter-0.8.2-cp312-cp312-win_amd64.whl (204 kB)\n",
33 | "Installing collected packages: jiter, openai\n",
34 | "Successfully installed jiter-0.8.2 openai-1.57.4\n"
35 | ]
36 | }
37 | ],
38 | "source": [
39 | "import sys\n",
40 | "!{sys.executable} -m pip install openai"
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": 5,
46 | "id": "ae53df99-deff-4c6d-8905-8bb02a6e299e",
47 | "metadata": {},
48 | "outputs": [
49 | {
50 | "name": "stdout",
51 | "output_type": "stream",
52 | "text": [
53 | "Collecting langchain_core\n",
54 | " Downloading langchain_core-0.3.25-py3-none-any.whl.metadata (6.3 kB)\n",
55 | "Requirement already satisfied: PyYAML>=5.3 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain_core) (6.0.1)\n",
56 | "Requirement already satisfied: jsonpatch<2.0,>=1.33 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain_core) (1.33)\n",
57 | "Collecting langsmith<0.3,>=0.1.125 (from langchain_core)\n",
58 | " Using cached langsmith-0.2.3-py3-none-any.whl.metadata (14 kB)\n",
59 | "Requirement already satisfied: packaging<25,>=23.2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain_core) (24.1)\n",
60 | "Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain_core) (2.8.2)\n",
61 | "Requirement already satisfied: tenacity!=8.4.0,<10.0.0,>=8.1.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain_core) (8.2.3)\n",
62 | "Requirement already satisfied: typing-extensions>=4.7 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain_core) (4.11.0)\n",
63 | "Requirement already satisfied: jsonpointer>=1.9 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from jsonpatch<2.0,>=1.33->langchain_core) (2.1)\n",
64 | "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.125->langchain_core) (0.27.0)\n",
65 | "Collecting orjson<4.0.0,>=3.9.14 (from langsmith<0.3,>=0.1.125->langchain_core)\n",
66 | " Downloading orjson-3.10.12-cp312-none-win_amd64.whl.metadata (42 kB)\n",
67 | "Requirement already satisfied: requests<3,>=2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.125->langchain_core) (2.32.3)\n",
68 | "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.125->langchain_core) (1.0.0)\n",
69 | "Requirement already satisfied: annotated-types>=0.4.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3.0.0,>=2.7.4->langchain_core) (0.6.0)\n",
70 | "Requirement already satisfied: pydantic-core==2.20.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3.0.0,>=2.7.4->langchain_core) (2.20.1)\n",
71 | "Requirement already satisfied: anyio in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.125->langchain_core) (4.2.0)\n",
72 | "Requirement already satisfied: certifi in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.125->langchain_core) (2024.8.30)\n",
73 | "Requirement already satisfied: httpcore==1.* in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.125->langchain_core) (1.0.2)\n",
74 | "Requirement already satisfied: idna in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.125->langchain_core) (3.7)\n",
75 | "Requirement already satisfied: sniffio in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.125->langchain_core) (1.3.0)\n",
76 | "Requirement already satisfied: h11<0.15,>=0.13 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->langsmith<0.3,>=0.1.125->langchain_core) (0.14.0)\n",
77 | "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests<3,>=2->langsmith<0.3,>=0.1.125->langchain_core) (3.3.2)\n",
78 | "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests<3,>=2->langsmith<0.3,>=0.1.125->langchain_core) (2.2.3)\n",
79 | "Downloading langchain_core-0.3.25-py3-none-any.whl (411 kB)\n",
80 | "Using cached langsmith-0.2.3-py3-none-any.whl (320 kB)\n",
81 | "Downloading orjson-3.10.12-cp312-none-win_amd64.whl (135 kB)\n",
82 | "Installing collected packages: orjson, langsmith, langchain_core\n",
83 | "Successfully installed langchain_core-0.3.25 langsmith-0.2.3 orjson-3.10.12\n"
84 | ]
85 | }
86 | ],
87 | "source": [
88 | "!{sys.executable} -m pip install langchain_core"
89 | ]
90 | },
91 | {
92 | "cell_type": "code",
93 | "execution_count": 7,
94 | "id": "55b8f17b-2a19-448f-afe6-7b595cc56cb9",
95 | "metadata": {},
96 | "outputs": [
97 | {
98 | "name": "stdout",
99 | "output_type": "stream",
100 | "text": [
101 | "Collecting langchain\n",
102 | " Downloading langchain-0.3.12-py3-none-any.whl.metadata (7.1 kB)\n",
103 | "Requirement already satisfied: PyYAML>=5.3 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (6.0.1)\n",
104 | "Requirement already satisfied: SQLAlchemy<3,>=1.4 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (2.0.34)\n",
105 | "Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (3.10.5)\n",
106 | "Requirement already satisfied: langchain-core<0.4.0,>=0.3.25 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (0.3.25)\n",
107 | "Collecting langchain-text-splitters<0.4.0,>=0.3.3 (from langchain)\n",
108 | " Downloading langchain_text_splitters-0.3.3-py3-none-any.whl.metadata (2.3 kB)\n",
109 | "Requirement already satisfied: langsmith<0.3,>=0.1.17 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (0.2.3)\n",
110 | "Requirement already satisfied: numpy<3,>=1.26.2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (1.26.4)\n",
111 | "Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (2.8.2)\n",
112 | "Requirement already satisfied: requests<3,>=2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (2.32.3)\n",
113 | "Requirement already satisfied: tenacity!=8.4.0,<10,>=8.1.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain) (8.2.3)\n",
114 | "Requirement already satisfied: aiohappyeyeballs>=2.3.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (2.4.0)\n",
115 | "Requirement already satisfied: aiosignal>=1.1.2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.2.0)\n",
116 | "Requirement already satisfied: attrs>=17.3.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (23.1.0)\n",
117 | "Requirement already satisfied: frozenlist>=1.1.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.4.0)\n",
118 | "Requirement already satisfied: multidict<7.0,>=4.5 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (6.0.4)\n",
119 | "Requirement already satisfied: yarl<2.0,>=1.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.11.0)\n",
120 | "Requirement already satisfied: jsonpatch<2.0,>=1.33 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.25->langchain) (1.33)\n",
121 | "Requirement already satisfied: packaging<25,>=23.2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.25->langchain) (24.1)\n",
122 | "Requirement already satisfied: typing-extensions>=4.7 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.25->langchain) (4.11.0)\n",
123 | "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.17->langchain) (0.27.0)\n",
124 | "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.17->langchain) (3.10.12)\n",
125 | "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.17->langchain) (1.0.0)\n",
126 | "Requirement already satisfied: annotated-types>=0.4.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3.0.0,>=2.7.4->langchain) (0.6.0)\n",
127 | "Requirement already satisfied: pydantic-core==2.20.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3.0.0,>=2.7.4->langchain) (2.20.1)\n",
128 | "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests<3,>=2->langchain) (3.3.2)\n",
129 | "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests<3,>=2->langchain) (3.7)\n",
130 | "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests<3,>=2->langchain) (2.2.3)\n",
131 | "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests<3,>=2->langchain) (2024.8.30)\n",
132 | "Requirement already satisfied: greenlet!=0.4.17 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from SQLAlchemy<3,>=1.4->langchain) (3.0.1)\n",
133 | "Requirement already satisfied: anyio in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.17->langchain) (4.2.0)\n",
134 | "Requirement already satisfied: httpcore==1.* in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.17->langchain) (1.0.2)\n",
135 | "Requirement already satisfied: sniffio in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->langsmith<0.3,>=0.1.17->langchain) (1.3.0)\n",
136 | "Requirement already satisfied: h11<0.15,>=0.13 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->langsmith<0.3,>=0.1.17->langchain) (0.14.0)\n",
137 | "Requirement already satisfied: jsonpointer>=1.9 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4.0,>=0.3.25->langchain) (2.1)\n",
138 | "Downloading langchain-0.3.12-py3-none-any.whl (1.0 MB)\n",
139 | " ---------------------------------------- 0.0/1.0 MB ? eta -:--:--\n",
140 | " ------------------------------- -------- 0.8/1.0 MB 5.6 MB/s eta 0:00:01\n",
141 | " ---------------------------------------- 1.0/1.0 MB 4.8 MB/s eta 0:00:00\n",
142 | "Downloading langchain_text_splitters-0.3.3-py3-none-any.whl (27 kB)\n",
143 | "Installing collected packages: langchain-text-splitters, langchain\n",
144 | "Successfully installed langchain-0.3.12 langchain-text-splitters-0.3.3\n"
145 | ]
146 | }
147 | ],
148 | "source": [
149 | "!{sys.executable} -m pip install langchain"
150 | ]
151 | },
152 | {
153 | "cell_type": "code",
154 | "execution_count": 16,
155 | "id": "8e2de07a-31ba-45e6-9c43-3e55eab52cf2",
156 | "metadata": {},
157 | "outputs": [
158 | {
159 | "name": "stdout",
160 | "output_type": "stream",
161 | "text": [
162 | "Collecting langchain-openai\n",
163 | " Using cached langchain_openai-0.2.12-py3-none-any.whl.metadata (2.7 kB)\n",
164 | "Requirement already satisfied: langchain-core<0.4.0,>=0.3.21 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-openai) (0.3.25)\n",
165 | "Requirement already satisfied: openai<2.0.0,>=1.55.3 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-openai) (1.57.4)\n",
166 | "Collecting tiktoken<1,>=0.7 (from langchain-openai)\n",
167 | " Downloading tiktoken-0.8.0-cp312-cp312-win_amd64.whl.metadata (6.8 kB)\n",
168 | "Requirement already satisfied: PyYAML>=5.3 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.21->langchain-openai) (6.0.1)\n",
169 | "Requirement already satisfied: jsonpatch<2.0,>=1.33 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.21->langchain-openai) (1.33)\n",
170 | "Requirement already satisfied: langsmith<0.3,>=0.1.125 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.21->langchain-openai) (0.2.3)\n",
171 | "Requirement already satisfied: packaging<25,>=23.2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.21->langchain-openai) (24.1)\n",
172 | "Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.21->langchain-openai) (2.8.2)\n",
173 | "Requirement already satisfied: tenacity!=8.4.0,<10.0.0,>=8.1.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.21->langchain-openai) (8.2.3)\n",
174 | "Requirement already satisfied: typing-extensions>=4.7 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langchain-core<0.4.0,>=0.3.21->langchain-openai) (4.11.0)\n",
175 | "Requirement already satisfied: anyio<5,>=3.5.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai<2.0.0,>=1.55.3->langchain-openai) (4.2.0)\n",
176 | "Requirement already satisfied: distro<2,>=1.7.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai<2.0.0,>=1.55.3->langchain-openai) (1.9.0)\n",
177 | "Requirement already satisfied: httpx<1,>=0.23.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai<2.0.0,>=1.55.3->langchain-openai) (0.27.0)\n",
178 | "Requirement already satisfied: jiter<1,>=0.4.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai<2.0.0,>=1.55.3->langchain-openai) (0.8.2)\n",
179 | "Requirement already satisfied: sniffio in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai<2.0.0,>=1.55.3->langchain-openai) (1.3.0)\n",
180 | "Requirement already satisfied: tqdm>4 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from openai<2.0.0,>=1.55.3->langchain-openai) (4.66.5)\n",
181 | "Requirement already satisfied: regex>=2022.1.18 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from tiktoken<1,>=0.7->langchain-openai) (2024.9.11)\n",
182 | "Requirement already satisfied: requests>=2.26.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from tiktoken<1,>=0.7->langchain-openai) (2.32.3)\n",
183 | "Requirement already satisfied: idna>=2.8 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.55.3->langchain-openai) (3.7)\n",
184 | "Requirement already satisfied: certifi in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.55.3->langchain-openai) (2024.8.30)\n",
185 | "Requirement already satisfied: httpcore==1.* in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.55.3->langchain-openai) (1.0.2)\n",
186 | "Requirement already satisfied: h11<0.15,>=0.13 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=1.55.3->langchain-openai) (0.14.0)\n",
187 | "Requirement already satisfied: jsonpointer>=1.9 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4.0,>=0.3.21->langchain-openai) (2.1)\n",
188 | "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.125->langchain-core<0.4.0,>=0.3.21->langchain-openai) (3.10.12)\n",
189 | "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from langsmith<0.3,>=0.1.125->langchain-core<0.4.0,>=0.3.21->langchain-openai) (1.0.0)\n",
190 | "Requirement already satisfied: annotated-types>=0.4.0 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3.0.0,>=2.7.4->langchain-core<0.4.0,>=0.3.21->langchain-openai) (0.6.0)\n",
191 | "Requirement already satisfied: pydantic-core==2.20.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from pydantic<3.0.0,>=2.7.4->langchain-core<0.4.0,>=0.3.21->langchain-openai) (2.20.1)\n",
192 | "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests>=2.26.0->tiktoken<1,>=0.7->langchain-openai) (3.3.2)\n",
193 | "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from requests>=2.26.0->tiktoken<1,>=0.7->langchain-openai) (2.2.3)\n",
194 | "Requirement already satisfied: colorama in c:\\users\\sakov\\bootcamp\\anaconda\\lib\\site-packages (from tqdm>4->openai<2.0.0,>=1.55.3->langchain-openai) (0.4.6)\n",
195 | "Using cached langchain_openai-0.2.12-py3-none-any.whl (50 kB)\n",
196 | "Downloading tiktoken-0.8.0-cp312-cp312-win_amd64.whl (883 kB)\n",
197 | " ---------------------------------------- 0.0/883.8 kB ? eta -:--:--\n",
198 | " ----------- ---------------------------- 262.1/883.8 kB ? eta -:--:--\n",
199 | " ----------------------- ---------------- 524.3/883.8 kB 1.7 MB/s eta 0:00:01\n",
200 | " ----------------------- ---------------- 524.3/883.8 kB 1.7 MB/s eta 0:00:01\n",
201 | " ---------------------------------------- 883.8/883.8 kB 1.0 MB/s eta 0:00:00\n",
202 | "Installing collected packages: tiktoken, langchain-openai\n",
203 | "Successfully installed langchain-openai-0.2.12 tiktoken-0.8.0\n"
204 | ]
205 | }
206 | ],
207 | "source": [
208 | "!{sys.executable} -m pip install langchain-openai"
209 | ]
210 | },
211 | {
212 | "cell_type": "code",
213 | "execution_count": 1,
214 | "id": "1da3b4d2-ca8d-4b64-ab3c-a9482a28b34f",
215 | "metadata": {},
216 | "outputs": [
217 | {
218 | "name": "stdout",
219 | "output_type": "stream",
220 | "text": [
221 | "*Roooaaarrr!* (Just hanging out, ready for some adventures! How about you?)\n"
222 | ]
223 | }
224 | ],
225 | "source": [
226 | "import getpass\n",
227 | "import os\n",
228 | "from langchain_openai import ChatOpenAI\n",
229 | "from langchain_core.prompts import ChatPromptTemplate\n",
230 | "from langchain_core.messages import HumanMessage, SystemMessage\n",
231 | "from dotenv import load_dotenv\n",
232 | "\n",
233 | "#load the environment\n",
234 | "load_dotenv()\n",
235 | "\n",
236 | "os.environ[\"LANGCHAIN_TRACING_V2\"] = \"true\"\n",
237 | "os.environ[\"LANGCHAIN_API_KEY\"] = os.getenv(\"LANGCHAIN_API_KEY\")\n",
238 | "os.environ[\"OPENAI_API_KEY\"] = os.getenv(\"OPENAI_API_KEY\")\n",
239 | "\n",
240 | "model = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0, max_retries=2)\n",
241 | "\n",
242 | "system_template = \"Respond to all messages as if you were {character} from Starwars\"\n",
243 | "\n",
244 | "prompt_template = ChatPromptTemplate.from_messages(\n",
245 | " [(\"system\", system_template), (\"user\", \"{text}\")]\n",
246 | ")\n",
247 | "\n",
248 | "prompt = prompt_template.invoke({\"character\": \"Chewbaca\", \"text\": \"Hello! what are you upto?\"})\n",
249 | "\n",
250 | "response = model.invoke(prompt)\n",
251 | "print(response.content)"
252 | ]
253 | },
254 | {
255 | "cell_type": "code",
256 | "execution_count": null,
257 | "id": "8e8d0f9c-8cec-49e4-ad40-329c456e0ab3",
258 | "metadata": {},
259 | "outputs": [],
260 | "source": []
261 | },
262 | {
263 | "cell_type": "code",
264 | "execution_count": null,
265 | "id": "a5963c2f-fa1d-436d-8488-3b0ad428a366",
266 | "metadata": {},
267 | "outputs": [],
268 | "source": []
269 | }
270 | ],
271 | "metadata": {
272 | "kernelspec": {
273 | "display_name": "Python 3 (ipykernel)",
274 | "language": "python",
275 | "name": "python3"
276 | },
277 | "language_info": {
278 | "codemirror_mode": {
279 | "name": "ipython",
280 | "version": 3
281 | },
282 | "file_extension": ".py",
283 | "mimetype": "text/x-python",
284 | "name": "python",
285 | "nbconvert_exporter": "python",
286 | "pygments_lexer": "ipython3",
287 | "version": "3.12.9"
288 | }
289 | },
290 | "nbformat": 4,
291 | "nbformat_minor": 5
292 | }
293 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | aiohappyeyeballs==2.4.4
2 | aiohttp==3.11.11
3 | aiosignal==1.3.2
4 | aiosqlite==0.20.0
5 | annotated-types==0.7.0
6 | anthropic==0.40.0
7 | anyio==4.7.0
8 | argon2-cffi==23.1.0
9 | argon2-cffi-bindings==21.2.0
10 | arrow==1.3.0
11 | asttokens==3.0.0
12 | async-lru==2.0.4
13 | attrs==24.3.0
14 | azure-core==1.32.0
15 | azure-identity==1.19.0
16 | babel==2.16.0
17 | beautifulsoup4==4.12.3
18 | bleach==6.2.0
19 | certifi==2024.12.14
20 | cffi==1.17.1
21 | chainlit==2.1.2
22 | charset-normalizer==3.4.1
23 | click==8.1.7
24 | colorama==0.4.6
25 | comm==0.2.2
26 | cryptography==44.0.0
27 | dataclasses-json==0.6.7
28 | debugpy==1.8.9
29 | decorator==5.1.1
30 | defusedxml==0.7.1
31 | Deprecated==1.2.15
32 | distro==1.9.0
33 | dydantic==0.0.7
34 | executing==2.1.0
35 | fastjsonschema==2.21.1
36 | filelock==3.16.1
37 | fqdn==1.5.1
38 | frozenlist==1.5.0
39 | fsspec==2024.10.0
40 | geojson==2.5.0
41 | greenlet==3.1.1
42 | h11==0.14.0
43 | h2==4.1.0
44 | hpack==4.0.0
45 | httpcore==1.0.7
46 | httpx==0.28.1
47 | httpx-sse==0.4.0
48 | huggingface-hub==0.26.5
49 | hyperframe==6.0.1
50 | idna==3.10
51 | importlib_metadata==8.5.0
52 | ipykernel==6.29.5
53 | ipython==8.30.0
54 | ipywidgets==8.1.5
55 | isoduration==20.11.0
56 | jedi==0.19.2
57 | Jinja2==3.1.4
58 | jiter==0.8.0
59 | joblib==1.4.2
60 | json5==0.10.0
61 | jsonpatch==1.33
62 | jsonpointer==3.0.0
63 | jsonschema==4.23.0
64 | jsonschema-specifications==2024.10.1
65 | jupyter==1.1.1
66 | jupyter_client==8.6.3
67 | jupyter-console==6.6.3
68 | jupyter_core==5.7.2
69 | jupyter-events==0.10.0
70 | jupyter-lsp==2.2.5
71 | jupyter_server==2.14.2
72 | jupyter_server_terminals==0.5.3
73 | jupyterlab==4.3.2
74 | jupyterlab_pygments==0.3.0
75 | jupyterlab_server==2.27.3
76 | jupyterlab_widgets==3.0.13
77 | langchain==0.3.11
78 | langchain-anthropic==0.3.0
79 | langchain-community==0.3.11
80 | langchain-core==0.3.24
81 | langchain-huggingface==0.1.2
82 | langchain-openai==0.2.12
83 | langchain-text-splitters==0.3.2
84 | langgraph==0.2.59
85 | langgraph-checkpoint==2.0.8
86 | langgraph-checkpoint-sqlite==2.0.1
87 | langgraph-cli==0.1.61
88 | langgraph-sdk==0.1.43
89 | langsmith==0.1.147
90 | lxml==5.3.0
91 | MarkupSafe==3.0.2
92 | marshmallow==3.23.1
93 | matplotlib-inline==0.1.7
94 | microsoft-kiota-abstractions==1.6.8
95 | microsoft-kiota-authentication-azure==1.6.8
96 | microsoft-kiota-http
97 | microsoft-kiota-serialization-form==1.6.8
98 | microsoft-kiota-serialization-json==1.6.8
99 | microsoft-kiota-serialization-multipart==1.6.8
100 | microsoft-kiota-serialization-text==1.6.8
101 | mistune==3.0.2
102 | mpmath==1.3.0
103 | msal==1.31.1
104 | msal-extensions==1.2.0
105 | msgpack==1.1.0
106 | msgraph-beta-sdk==1.16.0
107 | msgraph-core==1.1.8
108 | msgraph-sdk==1.16.0
109 | multidict==6.1.0
110 | mypy-extensions==1.0.0
111 | nbclient==0.10.1
112 | nbconvert==7.16.4
113 | nbformat==5.10.4
114 | nest-asyncio==1.6.0
115 | networkx==3.4.2
116 | notebook==7.3.1
117 | notebook_shim==0.2.4
118 | numexpr==2.10.2
119 | numpy
120 | openai==1.57.4
121 | opentelemetry-api==1.29.0
122 | opentelemetry-sdk==1.29.0
123 | opentelemetry-semantic-conventions==0.50b0
124 | orjson==3.10.12
125 | outcome==1.3.0.post0
126 | overrides==7.7.0
127 | packaging==24.2
128 | pandocfilters==1.5.1
129 | parso==0.8.4
130 | pendulum==3.0.0
131 | pillow==11.0.0
132 | pip==24.3.1
133 | platformdirs==4.3.6
134 | portalocker==2.10.1
135 | prometheus_client==0.21.1
136 | prompt_toolkit==3.0.48
137 | propcache==0.2.1
138 | psutil==6.1.0
139 | pure_eval==0.2.3
140 | pycparser==2.22
141 | pydantic==2.10.3
142 | pydantic_core==2.27.1
143 | pydantic-settings==2.6.1
144 | Pygments==2.18.0
145 | PyJWT==2.10.1
146 | pyowm==3.3.0
147 | PySocks==1.7.1
148 | python-dateutil==2.9.0.post0
149 | python-dotenv==1.0.1
150 | python-json-logger==2.0.7
151 | pywin32==308
152 | pywinpty==2.0.14
153 | PyYAML==6.0.2
154 | pyzmq==26.2.0
155 | referencing==0.35.1
156 | regex==2024.11.6
157 | requests==2.32.3
158 | requests-toolbelt==1.0.0
159 | rfc3339-validator==0.1.4
160 | rfc3986-validator==0.1.1
161 | rpds-py==0.22.3
162 | safetensors==0.4.5
163 | scikit-learn==1.6.0
164 | scipy==1.14.1
165 | selenium==4.4.3
166 | Send2Trash==1.8.3
167 | sentence-transformers==3.3.1
168 | setuptools==75.6.0
169 | six==1.17.0
170 | sniffio==1.3.1
171 | sortedcontainers==2.4.0
172 | soupsieve==2.6
173 | SQLAlchemy==2.0.36
174 | stack-data==0.6.3
175 | std-uritemplate==2.0.1
176 | sympy==1.13.1
177 | tavily-python==0.5.0
178 | tenacity==9.0.0
179 | terminado==0.18.1
180 | threadpoolctl==3.5.0
181 | tiktoken==0.8.0
182 | time-machine==2.16.0
183 | tinycss2==1.4.0
184 | tokenizers==0.21.0
185 | torch==2.5.1
186 | tornado==6.4.2
187 | tqdm==4.67.1
188 | traitlets==5.14.3
189 | transformers==4.47.0
190 | trio==0.26.2
191 | trio-websocket==0.11.1
192 | trustcall==0.0.26
193 | types-python-dateutil==2.9.0.20241206
194 | typing_extensions==4.12.2
195 | typing-inspect==0.9.0
196 | tzdata==2024.2
197 | uri-template==1.3.0
198 | urllib3
199 | wcwidth==0.2.13
200 | webcolors==24.11.1
201 | webencodings==0.5.1
202 | websocket-client==1.8.0
203 | widgetsnbextension==4.0.13
204 | wikipedia==1.4.0
205 | wrapt==1.17.0
206 | wsproto==1.2.0
207 | yarl==1.18.3
208 | zipp==3.21.0
209 | aiofiles 23.2.1
210 | aiohappyeyeballs 2.4.4
211 | aiohttp 3.11.11
212 | aiosignal 1.3.2
213 | annotated-types 0.7.0
214 | anyio 4.8.0
215 | asyncer 0.0.7
216 | attrs 25.1.0
217 | azure-core 1.32.0
218 | azure-identity 1.19.0
219 | bidict 0.23.1
220 | certifi 2025.1.31
221 | cffi 1.17.1
222 | chainlit 2.1.2
223 | charset-normalizer 3.4.1
224 | chevron 0.14.0
225 | click 8.1.8
226 | colorama 0.4.6
227 | cryptography 44.0.0
228 | dataclasses-json 0.6.7
229 | Deprecated 1.2.18
230 | distro 1.9.0
231 | fastapi 0.115.8
232 | filetype 1.2.0
233 | frozenlist 1.5.0
234 | googleapis-common-protos 1.66.0
235 | greenlet 3.1.1
236 | grpcio 1.70.0
237 | h11 0.14.0
238 | h2 4.2.0
239 | hpack 4.1.0
240 | httpcore 1.0.7
241 | httpx 0.28.1
242 | httpx-sse 0.4.0
243 | hyperframe 6.1.0
244 | idna 3.10
245 | importlib_metadata 8.5.0
246 | jiter 0.8.2
247 | jsonpatch 1.33
248 | jsonpointer 3.0.0
249 | langchain 0.3.17
250 | langchain-community 0.3.16
251 | langchain-core 0.3.33
252 | langchain-openai 0.3.3
253 | langchain-text-splitters 0.3.5
254 | langgraph 0.2.69
255 | langgraph-checkpoint 2.0.10
256 | langgraph-sdk 0.1.51
257 | langsmith 0.3.6
258 | Lazify 0.4.0
259 | literalai 0.1.103
260 | marshmallow 3.26.1
261 | microsoft-kiota-abstractions 1.9.1
262 | microsoft-kiota-authentication-azure 1.9.1
263 | microsoft-kiota-http 1.9.1
264 | microsoft-kiota-serialization-form 1.9.1
265 | microsoft-kiota-serialization-json 1.9.1
266 | microsoft-kiota-serialization-multipart 1.9.1
267 | microsoft-kiota-serialization-text 1.9.1
268 | msal 1.31.1
269 | msal-extensions 1.2.0
270 | msgpack 1.1.0
271 | msgraph-core 1.3.0
272 | msgraph-sdk 1.18.0
273 | multidict 6.1.0
274 | mypy-extensions 1.0.0
275 | nest-asyncio 1.6.0
276 | numpy 2.2.2
277 | openai 1.61.1
278 | opentelemetry-api 1.29.0
279 | opentelemetry-exporter-otlp 1.29.0
280 | opentelemetry-exporter-otlp-proto-common 1.29.0
281 | opentelemetry-exporter-otlp-proto-grpc 1.29.0
282 | opentelemetry-exporter-otlp-proto-http 1.29.0
283 | opentelemetry-instrumentation 0.50b0
284 | opentelemetry-proto 1.29.0
285 | opentelemetry-sdk 1.29.0
286 | opentelemetry-semantic-conventions 0.50b0
287 | orjson 3.10.15
288 | packaging 24.2
289 | pip 25.0
290 | portalocker 2.10.1
291 | propcache 0.2.1
292 | protobuf 5.29.3
293 | pycparser 2.22
294 | pydantic 2.10.6
295 | pydantic_core 2.27.2
296 | pydantic-settings 2.7.1
297 | PyJWT 1.7.0
298 | python-dotenv 1.0.1
299 | python-engineio 4.11.2
300 | python-multipart 0.0.18
301 | python-socketio 5.12.1
302 | pywin32 308
303 | PyYAML 6.0.2
304 | regex 2024.11.6
305 | requests 2.32.3
306 | requests-toolbelt 1.0.0
307 | simple-websocket 1.1.0
308 | six 1.17.0
309 | sniffio 1.3.1
310 | SQLAlchemy 2.0.37
311 | starlette 0.41.3
312 | std-uritemplate 2.0.1
313 | syncer 2.0.3
314 | tenacity 9.0.0
315 | tiktoken 0.8.0
316 | tomli 2.2.1
317 | tqdm 4.67.1
318 | typing_extensions 4.12.2
319 | typing-inspect 0.9.0
320 | uptrace 1.29.0
321 | urllib3 2.3.0
322 | uvicorn 0.34.0
323 | watchfiles 0.20.0
324 | wrapt 1.17.2
325 | wsproto 1.2.0
326 | yarl 1.18.3
327 | zipp 3.21.0
328 | zstandard 0.23.0
--------------------------------------------------------------------------------