From bcdc091db61277a27a69bce5c479122c5f2a7361 Mon Sep 17 00:00:00 2001 From: Sarah Guthals Date: Fri, 28 Nov 2025 09:45:19 -0800 Subject: [PATCH] updates --- Applications/.DS_Store | Bin 0 -> 8196 bytes ...rty Insurance Claim Assessment Report.docx | Bin 0 -> 11618 bytes .../docx-remote-testing.py | 7 + .../docx-tracked-changes.py | 243 ++++++++++++++++ .../docx-tracked-changes/requirements.txt | 4 + output_compare.txt | 262 ++++++++++++++++++ 6 files changed, 516 insertions(+) create mode 100644 Applications/.DS_Store create mode 100644 Applications/docx-tracked-changes/Commercial Property Insurance Claim Assessment Report.docx create mode 100644 Applications/docx-tracked-changes/docx-remote-testing.py create mode 100644 Applications/docx-tracked-changes/docx-tracked-changes.py create mode 100644 Applications/docx-tracked-changes/requirements.txt create mode 100644 output_compare.txt diff --git a/Applications/.DS_Store b/Applications/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..16a5453777c615509bc9bb879e06856c5fbc0b77 GIT binary patch literal 8196 zcmeHMU2GIp6u#fIz>FPaT3aZ{vMUQnptVbZQYhlmmY+&1$hLG_igka6cI_i5E1Y=gyrimY+ltf+WsO?mhRO zd(XLZ&YbVwJ+q84H0QG`7^`NC$y7Pj%BZ#w@Ic^!zyr5~2k6e`MZV6xFJ^-_@Ic^!|D^}``4FMXY22sdf_g^>HC_rp zl&1h*p+4mSo=n82ai5M0>WPw0kv+f{g`Z+Th|_$8FDDxJ>A0XmoI!{)_&dYTP~h!O zauIJiLtN0H4LlHd;A#(W_*AkivnglaHzj}9iCatDLCWVXHo$b|q(_~Rv}vbF=6HI< zG#ob;I|HetblUV8@(j65-jf)#M-y(!%{$Gh+-^SVv~4q8?5EPZ41Kg;t8B3?H)U9Q z&J!@QIxXqzHms~Y+HB{otmDZh#DuKKO20Pe;K9Z-8^*>I zxhh)Mw6lN69JcJk!b13`1ePfo#KDVf7%2cw~v2$*Vr>tMo@{Yb!CtXHCZzYYSs)FyfeT1uVcIi2XXfz%Z<}1hU zoD*KOw6=cD`uL`{j)x~^Y2_8FS~a`7U^qtF)O%7+Mz^wtHPAI`WZl7Da=hgldksCO zDCMZ>v{J+RL`C)7d3Vnbg~Xc6GDR)PeA;+CZ@Bxls4R;;LJOmctbN>RQ!ChNXn73@q&gjPkpGym6^f!cokJ8ILR4MdAS+t7%S@$p(`T(~ zBG$I?3x9on)uk8Fr4H zXTPzF?05DDyMz*`sK9(ILM`eL!wRfJ6V_t`wxJVU*o8EPU}6|HT#VrfJc&bi1~1@6 zyo6Wq2HwUyIEwdh49D>aKE)UK3SZ+izQH;Cg7f$l7w{)8;V-FNnkOxi7E4Q{Iw>aA zODm<#(iUll)FY*(0clX!AQhpwXVNCGBkd>huTLI=qJQ#8$F2><@RqG@5323AJruvc zlY{TB%BtCOB8!*Rt!lh~<79}6h%N^4Kf&SQVG4>oJa{p4Wh{FrRTqT22r&A-%P!GSGL@YVOI(Xcj+ASH%N)TLoAW{mxpV^nnWlT!&tap)k+AXiYL1|T&rr3 z#bB-4q-v#vRx#Y5E>Jb5h(U9>HLP*$$u}DX-?FppM?%2`b`jH21`S~>#eHa`sNamO zXhS{?zz_HdKVK2$9aEzm7j7iV3yGX%+SUNc6j3u(-OU}92zAvw|KD`| z@BcS<(?DC`fxrW|l?PDTnrLmNN4nmj!*lHj)kmrF!q<%p>WNUpmvFw9juV~y!;tzB ke=hFRaY1Q@$}Rs8@E`va5AOfq{`dYLzeaw2EARim0d`ZX)c^nh literal 0 HcmV?d00001 diff --git a/Applications/docx-tracked-changes/Commercial Property Insurance Claim Assessment Report.docx b/Applications/docx-tracked-changes/Commercial Property Insurance Claim Assessment Report.docx new file mode 100644 index 0000000000000000000000000000000000000000..5260888b72ccdb03d505bbb6c40022fbf54ae744 GIT binary patch literal 11618 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 literal 0 HcmV?d00001 diff --git a/Applications/docx-tracked-changes/docx-remote-testing.py b/Applications/docx-tracked-changes/docx-remote-testing.py new file mode 100644 index 0000000..5b6ec2f --- /dev/null +++ b/Applications/docx-tracked-changes/docx-remote-testing.py @@ -0,0 +1,7 @@ +from tensorlake.runtime import run_remote_application + +# Deploy and run at scale +changes = run_remote_application( + analyze_contract_revisions, + contract_urls=contracts +) diff --git a/Applications/docx-tracked-changes/docx-tracked-changes.py b/Applications/docx-tracked-changes/docx-tracked-changes.py new file mode 100644 index 0000000..8c2367a --- /dev/null +++ b/Applications/docx-tracked-changes/docx-tracked-changes.py @@ -0,0 +1,243 @@ +import os +from typing import List +from tensorlake.applications import Image, application, function, cls +from tensorlake.documentai import DocumentAI + +# Define the runtime environment +image = ( + Image(base_image="python:3.11-slim", name="docx-example") + .run("pip install tensorlake beautifulsoup4") +) + +@application() +@function( + secrets=["TENSORLAKE_API_KEY"], + image=image +) +def analyze_contract_revisions(contract_urls: List[str]) -> None: + """ + Main application that processes contracts with tracked changes + and loads analysis results + """ + print(f"[DEBUG] Starting analysis of {len(contract_urls)} contracts") + + # Process each contract in parallel + print("[DEBUG] Processing contracts in parallel...") + results = process_single_contract.map(contract_urls) + + # Collect and analyze all results + all_changes = [] + for result in results: + all_changes.extend(result) + + print(f"Processed {len(contract_urls)} contracts") + print(f"Found {len(all_changes)} tracked changes total") + + return all_changes + + +@function( + secrets=["TENSORLAKE_API_KEY"], +image=image +) +def process_single_contract(url: str) -> List[dict]: + """ + Process a single contract and extract tracked changes with locations + """ + print(f"[DEBUG] Processing contract: {url}") + from bs4 import BeautifulSoup + + doc_ai = DocumentAI() + + # Parse the DOCX file + print("[DEBUG] Parsing DOCX file...") + try: + result = doc_ai.parse_and_wait(file=url) + except Exception as e: + print(f"[ERROR] Parse failed: {e}") + # Handle tracked changes manually from markdown if needed + return [] + print("[DEBUG] DOCX parsing complete") + + changes = [] + + # Extract tracked changes from each chunk + print(f"[DEBUG] Processing {len(result.chunks)} document chunks") + for chunk_idx, chunk in enumerate(result.chunks, 1): + print(f"[DEBUG] Processing chunk {chunk_idx}/{len(result.chunks)}") + soup = BeautifulSoup(chunk.markdown, 'html.parser') + + # Find insertions + insertions = soup.find_all('ins') + print(f"[DEBUG] Found {len(insertions)} insertions in chunk {chunk_idx}") + for ins in insertions: + text = ins.get_text() + print(f"[DEBUG] Processing insertion: '{text[:50]}{'...' if len(text) > 50 else ''}'") + changes.append({ + 'type': 'insertion', + 'text': text, + 'context': get_surrounding_context(ins), + 'page': chunk.page_number if hasattr(chunk, 'page_number') else None + }) + + # Find deletions + deletions = soup.find_all('del') + print(f"[DEBUG] Found {len(deletions)} deletions in chunk {chunk_idx}") + for del_tag in deletions: + text = del_tag.get_text() + print(f"[DEBUG] Processing deletion: '{text[:50]}{'...' if len(text) > 50 else ''}'") + changes.append({ + 'type': 'deletion', + 'text': text, + 'context': get_surrounding_context(del_tag), + 'page': chunk.page_number if hasattr(chunk, 'page_number') else None + }) + + # Find comments + comments = soup.find_all('span', class_='comment') + print(f"[DEBUG] Found {len(comments)} comments in chunk {chunk_idx}") + for comment in comments: + note = comment.get('data-note') + print(f"[DEBUG] Processing comment: '{note[:50]}{'...' if len(note) > 50 else ''}'") + changes.append({ + 'type': 'comment', + 'text': note, + 'highlighted_text': comment.get_text(), + 'page': chunk.page_number if hasattr(chunk, 'page_number') else None + }) + + # Also extract spatial information for key clauses + for page in result.pages: + for fragment in page.page_fragments: + if fragment.fragment_type == 'text' and is_key_clause(fragment.content): + # Find any tracked changes in this fragment + fragment_changes = [ + c for c in changes + if c.get('page') == page.page_number and + c.get('text', '') in fragment.content + ] + + for change in fragment_changes: + change['bbox'] = fragment.bbox + change['reading_order'] = fragment.reading_order + + return changes + + +@function(image=image) +def get_surrounding_context(tag, chars=100): + """Extract surrounding text context for a tracked change""" + text = tag.parent.get_text() if tag.parent else "" + tag_text = tag.get_text() + + if tag_text in text: + start = max(0, text.index(tag_text) - chars) + end = min(len(text), text.index(tag_text) + len(tag_text) + chars) + return text[start:end] + + return text[:chars] + + +@function(image=image) +def is_key_clause(text: str) -> bool: + """Identify if text contains a key contract clause""" + key_terms = [ + 'indemnification', 'liability', 'warranty', 'termination', + 'confidentiality', 'intellectual property', 'force majeure', + 'governing law', 'dispute resolution', 'payment terms' + ] + + text_lower = text.lower() + return any(term in text_lower for term in key_terms) + + +@application() +@function( + secrets=["TENSORLAKE_API_KEY"], + image=image +) +def query_contract_changes(contract_tuple: tuple[str, str]) -> str: + """ + Query a contract about specific changes using an LLM with full context + """ + print(f"[DEBUG] Starting contract query with parameters: {contract_tuple}") + doc_ai = DocumentAI() + + # Parse the contract + print("[DEBUG] Parsing contract for querying...") + result = doc_ai.parse_and_wait(file=contract_tuple[0]) + print("[DEBUG] Contract parsing complete") + + # Build context from tracked changes and spatial data + context = build_contract_context(result) + + # Use an LLM to answer the question (pseudo-code) + # In production, you'd call your LLM API here + answer = f""" + Based on the tracked changes in the document: + + Question: { contract_tuple[1] } + + Analysis: + {context} + """ + + return answer + + +@function(image=image) +def build_contract_context(result) -> str: + """Build a comprehensive context string with tracked changes and locations""" + from bs4 import BeautifulSoup + + context_parts = [] + + for chunk in result.chunks: + soup = BeautifulSoup(chunk.markdown, 'html.parser') + + # Extract insertions with page numbers + for ins in soup.find_all('ins'): + context_parts.append( + f"INSERTION: Added '{ins.get_text()}' " + f"(Page {chunk.page_number if hasattr(chunk, 'page_number') else 'unknown'})" + ) + + # Extract deletions with page numbers + for del_tag in soup.find_all('del'): + context_parts.append( + f"DELETION: Removed '{del_tag.get_text()}' " + f"(Page {chunk.page_number if hasattr(chunk, 'page_number') else 'unknown'})" + ) + + # Extract comments + for comment in soup.find_all('span', class_='comment'): + context_parts.append( + f"COMMENT: '{comment.get('data-note')}' on text '{comment.get_text()}' " + f"(Page {chunk.page_number if hasattr(chunk, 'page_number') else 'unknown'})" + ) + + return "\n".join(context_parts) + +if __name__ == "__main__": + from tensorlake.applications import run_local_application + + # Analyze multiple contracts + contracts_urls = [ + "https://pub-226479de18b2493f96b64c6674705dd8.r2.dev/Commercial%20Property%20Insurance%20Claim%20Assessment%20Report.docx" + ] + + changes = run_local_application( + analyze_contract_revisions, + contracts_urls + ) + + print(f"Found {changes} tracked changes across all contracts") + + # Query a specific contract + answer = run_local_application( + query_contract_changes, + ("https://pub-226479de18b2493f96b64c6674705dd8.r2.dev/Commercial%20Property%20Insurance%20Claim%20Assessment%20Report.docx", + "What changes did opposing counsel make to the liability section?") + ) + + print(answer) \ No newline at end of file diff --git a/Applications/docx-tracked-changes/requirements.txt b/Applications/docx-tracked-changes/requirements.txt new file mode 100644 index 0000000..f057b56 --- /dev/null +++ b/Applications/docx-tracked-changes/requirements.txt @@ -0,0 +1,4 @@ +tensorlake>=0.1.0 + + + diff --git a/output_compare.txt b/output_compare.txt new file mode 100644 index 0000000..800c4af --- /dev/null +++ b/output_compare.txt @@ -0,0 +1,262 @@ +# Azure: +Contract Concerning 1234 Vista Lane, Austin, TX 12345 +Page 8 of 11 11-04-2024 +# (Address of Property) +21. NOTICES: All notices from one party to the other must be in writing and are effective when mailed to, hand-delivered at, or transmitted by fax or electronic transmission as follows: To Buyer at: 122 Rainbow Street To Seller at: 456 mountain street Lakehills, TX 12345 +Riverview, TX 34567 +Phone: +( 123 )456-7890 +Phone: +456 )789-1234 +E-mail/Fax: +john@gmail.com +E-mail/Fax: doe@gmail.com +E-mail/Fax: +E-mail/Fax: +With a copy to Buyer's agent at: +buyinglake@gmail.com +With a copy to Seller's agent at: +sellinglake@gmail.com +22. AGREEMENT OF PARTIES: This contract contains the entire agreement of the parties and cannot be changed except by their written agreement. Addenda which are a part of this contract are (Check all applicable boxes): [x] Third Party Financing Addendum +[ ] Seller's Temporary Residential Lease [ ] Seller Financing Addendum +[ ] [ ] Addendum for Property Located Seaward of the Gulf Intracoastal Waterway Short Sale Addendum [ ] Addendum for Property Subject to Mandatory Membership in a Property Owners Association [ ] Buyer's Temporary Residential Lease [ ] Loan Assumption Addendum [ ] Addendum for Sale of Other Property by Buyer [ ] Addendum for Property in a Propane Gas System Service Area [ ] Addendum Regarding Residential Leases [ ] Addendum Regarding Fixture Leases +[ ] Addendum for Reservation of Oil, Gas and Other Minerals [ ] Addendum for "Back-Up" Contract [ ] Addendum for Coastal Area Property [ ] Addendum for Authorizing Hydrostatic Testing [ ] Addendum Concerning Right to Terminate Due to Lender's Appraisal [ ] Environmental Assessment, Threatened or Endangered Species and Wetlands Addendum +[x] Addendum for Seller's Disclosure of Information on Lead-based Paint and Lead-based Paint Hazards as Required by Federal Law +[ ] Addendum containing Notice of Obligation to Pay Improvement District Assessment [ ] Addendum for Section 1031 Exchange [ ] Other (list): +23. CONSULT AN ATTORNEY BEFORE SIGNING: TREC rules prohibit real estate brokers and sales agents from giving legal advice. READ THIS CONTRACT CAREFULLY. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Buyer's
Attorney is:
Phone:
)
Fax:)
E-mail:
+Seller's Attorney is: +Phone: +) +Fax: +) +E-mail: +Initialed for identification by Buyer +and Seller +TREC NO. 20-18 + + + + + + +#Textract +Contract Concerning 1234 Vista Lane, Austin, TX 12345 (Address of Property) +Page 8 of 11 +11-04-2024 +21. NOTICES: All notices from one party to the other must be in writing and are effective when + mailed to, hand-delivered at, or transmitted by fax or electronic transmission as follows: + To Buyer at: 122 Rainbow Street +To Seller at: 456 mountain street +Lakehills, TX 12345 +Riverview, TX 34567 +Phone: +( 456 789-1234 +E-mail/Fax: doe@gmail.com +E-mail/Fax: +With a copy to Buyer's agent at: +With a copy to Seller's agent at: + buyinglake@gmail.com +sellinglake@gmail.com +22. AGREEMENT OF PARTIES: This contract contains the entire agreement of the parties and + cannot be changed except by their written agreement. Addenda which are a part of this contract + are (Check all applicable boxes): + Third Party Financing Addendum +Seller's Temporary Residential Lease + Seller Financing Addendum +Short Sale Addendum + Addendum for Property Subject to + Mandatory Membership in a Property +Addendum for Property Located Seaward + Owners Association +of the Gulf Intracoastal Waterway + Buyer's Temporary Residential Lease +Addendum for Seller's Disclosure of +Information on Lead-based Paint and +Loan Assumption Addendum +Lead-based Paint Hazards as Required by + Addendum for Sale of Other Property by +Federal Law + Buyer +Addendum for Property in a Propane Gas +Addendum for Reservation of Oil, Gas +System Service Area + and Other Minerals +Addendum Regarding Residential Leases +Addendum for "Back-Up" Contract +Addendum Regarding Fixture Leases + Addendum for Coastal Area Property + Addendum for Authorizing Hydrostatic +Addendum containing Notice of Obligation + Testing +to Pay Improvement District Assessment + Addendum Concerning Right to +Addendum for Section 1031 Exchange + Terminate Due to Lender's Appraisal + Environmental Assessment, Threatened +Other (list): + or Endangered Species and Wetlands + Addendum +23. CONSULT AN ATTORNEY BEFORE SIGNING: TREC rules prohibit real estate brokers and sales + agents from giving legal advice. READ THIS CONTRACT CAREFULLY. +Buyer's +Seller's + Attorney is: +Attorney is: +
+ + + +
Phone:( 123 )456-7890
E-mail/Fax:john@gmail.com
E-mail/Fax:
+
+
+ + +
Phone:( )
Fax:( )
E-mail:
+
+
+ + +
Phone:( )
Fax:( )
E-mail:
+
+Initialed for identification by Buyer +and Seller +TREC NO. 20-18 + + + + + +# Tensorlake03 (Dots) +Contract Concerning +1234 Vista Lane, Austin, TX 12345 +(Address of Property) +Page 8 of 11 +11-04-2024 +**21. NOTICES:** All notices from one party to the other must be in writing and are effective when mailed to, hand-delivered at, or transmitted by fax or electronic transmission as follows: +**To Buyer at:** 122 Rainbow Street +Lakehills, TX 12345 +Phone: (123)456-7890 +E-mail/Fax: john@gmail.com +E-mail/Fax: +With a copy to Buyer's agent at: +buyinglake@gmail.com +**To Seller at:** 456 mountain street +Riverview, TX 34567 +Phone: (456)789-1234 +E-mail/Fax: doe@gmail.com +E-mail/Fax: +With a copy to Seller's agent at: +sellinglake@gmail.com +**22. AGREEMENT OF PARTIES:** This contract contains the entire agreement of the parties and cannot be changed except by their written agreement. Addenda which are a part of this contract are (Check all applicable boxes): +[x] Third Party Financing Addendum +[ ] Seller Financing Addendum +[ ] Addendum for Property Subject to Mandatory Membership in a Property Owners Association +[ ] Buyer's Temporary Residential Lease +[ ] Loan Assumption Addendum +[ ] Addendum for Sale of Other Property by Buyer +[ ] Addendum for Reservation of Oil, Gas and Other Minerals +[ ] Addendum for "Back-Up" Contract +[ ] Addendum for Coastal Area Property +[ ] Addendum for Authorizing Hydrostatic Testing +[ ] Addendum Concerning Right to Terminate Due to Lender's Appraisal +[ ] Environmental Assessment, Threatened or Endangered Species and Wetlands Addendum +[ ] Seller's Temporary Residential Lease +[ ] Short Sale Addendum +[ ] Addendum for Property Located Seaward of the Gulf Intracoastal Waterway +[x] Addendum for Seller's Disclosure of Information on Lead-based Paint and Lead-based Paint Hazards as Required by Federal Law +[ ] Addendum for Property in a Propane Gas System Service Area +[ ] Addendum Regarding Residential Leases +[ ] Addendum Regarding Fixture Leases +[ ] Addendum containing Notice of Obligation to Pay Improvement District Assessment +[ ] Addendum for Section 1031 Exchange +[ ] Other (list): +**23. CONSULT AN ATTORNEY BEFORE SIGNING:** TREC rules prohibit real estate brokers and sales agents from giving legal advice. READ THIS CONTRACT CAREFULLY. +Buyer's +Attorney is: +### Figure +Phone: +### Figure +Fax: +### Figure +E-mail: +### Figure +Seller's +Attorney is: +### Figure +Phone: +### Figure +Fax: +### Figure +E-mail: +### Figure +Initialed for identification by Buyer +### Figure +TREC NO. 20-18 \ No newline at end of file