Update app2.py
Browse files
app2.py
CHANGED
@@ -20,6 +20,8 @@ import wikipedia
|
|
20 |
from googleapiclient.discovery import build
|
21 |
from typing import List, Optional
|
22 |
from httpx_sse import SSEError
|
|
|
|
|
23 |
|
24 |
# Error handling for optional dependencies
|
25 |
try:
|
@@ -212,34 +214,6 @@ def perform_web_search(query: str) -> List[Dict[str, Any]]:
|
|
212 |
|
213 |
return results[:3] # Return top 3 results with cost estimates
|
214 |
|
215 |
-
def search_wikipedia(query: str, sentences: int = 2) -> Dict[str, str]:
|
216 |
-
try:
|
217 |
-
# Ensure query is a string before slicing
|
218 |
-
truncated_query = str(query)[:300]
|
219 |
-
|
220 |
-
# Search Wikipedia
|
221 |
-
search_results = wikipedia.search(truncated_query, results=5)
|
222 |
-
|
223 |
-
if not search_results:
|
224 |
-
return {"summary": "No Wikipedia article found.", "url": "", "title": ""}
|
225 |
-
|
226 |
-
# Try to get a summary for each result until successful
|
227 |
-
for result in search_results:
|
228 |
-
try:
|
229 |
-
page = wikipedia.page(result)
|
230 |
-
summary = wikipedia.summary(result, sentences=sentences)
|
231 |
-
return {"summary": summary, "url": page.url, "title": page.title}
|
232 |
-
except wikipedia.exceptions.DisambiguationError as e:
|
233 |
-
continue
|
234 |
-
except wikipedia.exceptions.PageError:
|
235 |
-
continue
|
236 |
-
|
237 |
-
# If no summary found after trying all results
|
238 |
-
return {"summary": "No relevant Wikipedia article found.", "url": "", "title": ""}
|
239 |
-
except Exception as e:
|
240 |
-
print(f"Error searching Wikipedia: {e}")
|
241 |
-
return {"summary": f"Error searching Wikipedia: {str(e)}", "url": "", "title": ""}
|
242 |
-
|
243 |
def comprehensive_document_analysis(content: str) -> Dict[str, Any]:
|
244 |
"""Performs a comprehensive analysis of the document, including web and Wikipedia searches."""
|
245 |
try:
|
@@ -266,6 +240,41 @@ def comprehensive_document_analysis(content: str) -> Dict[str, Any]:
|
|
266 |
"wikipedia_summary": {"summary": "Error occurred", "url": "", "title": ""}
|
267 |
}
|
268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
def extract_important_info(text: str) -> str:
|
270 |
"""Extracts and highlights important information from the given text."""
|
271 |
prompt = f"Extract and highlight the most important legal information from the following text. Use markdown to emphasize key points:\n\n{text}"
|
@@ -339,6 +348,32 @@ def query_public_case_law(query: str) -> List[Dict[str, Any]]:
|
|
339 |
print(f"Error querying case law: {e}")
|
340 |
return []
|
341 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
342 |
def find_case_precedents(case_details: str) -> Dict[str, Any]:
|
343 |
"""Finds relevant case precedents based on provided details."""
|
344 |
try:
|
@@ -392,74 +427,180 @@ def find_case_precedents(case_details: str) -> Dict[str, Any]:
|
|
392 |
}
|
393 |
}
|
394 |
|
395 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
396 |
"""
|
397 |
Estimates legal costs based on case type, complexity, and location.
|
398 |
-
Performs web searches for more accurate estimates and
|
399 |
"""
|
400 |
-
# Base cost ranges per hour (in USD) for different countries
|
401 |
base_costs = {
|
402 |
-
"
|
403 |
-
"
|
404 |
-
"
|
405 |
}
|
406 |
|
407 |
-
# Adjust costs based on case type
|
408 |
case_type_multipliers = {
|
409 |
"Civil Litigation": 1.2,
|
410 |
-
"Criminal
|
411 |
"Family Law": 1.0,
|
412 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
413 |
}
|
414 |
|
415 |
-
# Estimate number of hours based on complexity
|
416 |
estimated_hours = {
|
417 |
"Simple": (10, 30),
|
418 |
"Moderate": (30, 100),
|
419 |
"Complex": (100, 300)
|
420 |
}
|
421 |
|
422 |
-
|
423 |
-
country_costs = base_costs.get(country, base_costs["USA"])
|
424 |
-
min_rate, max_rate = country_costs[complexity]
|
425 |
|
426 |
-
# Adjust rates based on case type
|
427 |
multiplier = case_type_multipliers.get(case_type, 1.0)
|
428 |
min_rate *= multiplier
|
429 |
max_rate *= multiplier
|
430 |
|
431 |
-
# Calculate total cost range
|
432 |
min_hours, max_hours = estimated_hours[complexity]
|
433 |
min_total = min_rate * min_hours
|
434 |
max_total = max_rate * max_hours
|
435 |
|
436 |
-
|
437 |
-
|
438 |
-
web_results = search_web(search_query)
|
439 |
|
440 |
-
web_estimates = []
|
441 |
-
for result in web_results:
|
442 |
-
estimates = extract_cost_estimates(result['snippet'])
|
443 |
-
if estimates:
|
444 |
-
web_estimates.append({
|
445 |
-
'source': result['title'],
|
446 |
-
'link': result['link'],
|
447 |
-
'estimates': estimates
|
448 |
-
})
|
449 |
-
|
450 |
-
# Search for lawyers or law firms
|
451 |
-
lawyer_search_query = f"top rated {case_type} lawyers {country} {state if state else ''}"
|
452 |
-
lawyer_results = search_web(lawyer_search_query)
|
453 |
-
|
454 |
-
# Generate cost breakdown
|
455 |
cost_breakdown = {
|
456 |
"Hourly rate range": f"${min_rate:.2f} - ${max_rate:.2f}",
|
457 |
"Estimated hours": f"{min_hours} - {max_hours}",
|
458 |
"Total cost range": f"${min_total:.2f} - ${max_total:.2f}",
|
459 |
-
"Web search estimates": web_estimates
|
460 |
}
|
461 |
|
462 |
-
|
|
|
|
|
463 |
high_cost_areas = [
|
464 |
"Expert witnesses (especially in complex cases)",
|
465 |
"Extensive document review and e-discovery",
|
@@ -468,7 +609,6 @@ def estimate_legal_costs(case_type: str, complexity: str, country: str, state: s
|
|
468 |
"Appeals process"
|
469 |
]
|
470 |
|
471 |
-
# Cost-saving tips
|
472 |
cost_saving_tips = [
|
473 |
"Consider alternative dispute resolution methods like mediation or arbitration",
|
474 |
"Be organized and provide all relevant documents upfront to reduce billable hours",
|
@@ -489,57 +629,12 @@ def estimate_legal_costs(case_type: str, complexity: str, country: str, state: s
|
|
489 |
"cost_breakdown": cost_breakdown,
|
490 |
"high_cost_areas": high_cost_areas,
|
491 |
"cost_saving_tips": cost_saving_tips,
|
492 |
-
"lawyer_recommendations":
|
493 |
"finding_best_lawyer_tips": lawyer_tips,
|
494 |
-
"
|
|
|
495 |
}
|
496 |
|
497 |
-
def legal_cost_estimator_ui():
|
498 |
-
st.subheader("Legal Cost Estimator")
|
499 |
-
|
500 |
-
case_type = st.selectbox("Select case type", ["Civil Litigation", "Criminal Defense", "Family Law", "Corporate Law"])
|
501 |
-
complexity = st.selectbox("Select case complexity", ["Simple", "Moderate", "Complex"])
|
502 |
-
country = st.selectbox("Select country", ["USA", "UK", "Canada"])
|
503 |
-
|
504 |
-
if country == "USA":
|
505 |
-
state = st.selectbox("Select state", ["California", "New York", "Texas", "Florida"])
|
506 |
-
else:
|
507 |
-
state = None
|
508 |
-
|
509 |
-
if st.button("Estimate Costs"):
|
510 |
-
with st.spinner("Estimating costs and performing web search..."):
|
511 |
-
cost_estimate = estimate_legal_costs(case_type, complexity, country, state)
|
512 |
-
|
513 |
-
st.write("### Estimated Legal Costs")
|
514 |
-
for key, value in cost_estimate["cost_breakdown"].items():
|
515 |
-
if key != "Web search estimates":
|
516 |
-
st.write(f"**{key}:** {value}")
|
517 |
-
|
518 |
-
st.write("### Web Search Estimates")
|
519 |
-
if cost_estimate["cost_breakdown"]["Web search estimates"]:
|
520 |
-
for result in cost_estimate["cost_breakdown"]["Web search estimates"]:
|
521 |
-
st.write(f"**Source:** [{result['source']}]({result['link']})")
|
522 |
-
st.write("**Estimated Costs:**")
|
523 |
-
for estimate in result['estimates']:
|
524 |
-
st.write(f"- {estimate}")
|
525 |
-
st.write("---")
|
526 |
-
else:
|
527 |
-
st.write("No specific cost estimates found from web search.")
|
528 |
-
|
529 |
-
st.write("### Potential High-Cost Areas")
|
530 |
-
for area in cost_estimate["high_cost_areas"]:
|
531 |
-
st.write(f"- {area}")
|
532 |
-
|
533 |
-
st.write("### Cost-Saving Tips")
|
534 |
-
for tip in cost_estimate["cost_saving_tips"]:
|
535 |
-
st.write(f"- {tip}")
|
536 |
-
|
537 |
-
st.write("### Recommended Lawyers/Law Firms")
|
538 |
-
for lawyer in cost_estimate["lawyer_recommendations"][:5]: # Display top 5 recommendations
|
539 |
-
st.write(f"**[{lawyer['title']}]({lawyer['link']})**")
|
540 |
-
st.write(lawyer["snippet"])
|
541 |
-
st.write("---")
|
542 |
-
|
543 |
def extract_cost_estimates(text: str) -> List[str]:
|
544 |
"""
|
545 |
Extracts cost estimates from the given text.
|
@@ -558,50 +653,76 @@ def extract_cost_estimates(text: str) -> List[str]:
|
|
558 |
return estimates
|
559 |
|
560 |
def legal_cost_estimator_ui():
|
561 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
562 |
|
563 |
-
case_type = st.selectbox("Select case type", ["Civil Litigation", "Criminal Defense", "Family Law", "Corporate Law"])
|
564 |
complexity = st.selectbox("Select case complexity", ["Simple", "Moderate", "Complex"])
|
565 |
-
country = st.selectbox("Select country", ["USA", "UK", "Canada"])
|
566 |
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
571 |
|
572 |
if st.button("Estimate Costs"):
|
573 |
-
with st.spinner("Estimating costs and
|
574 |
-
cost_estimate = estimate_legal_costs(case_type, complexity,
|
575 |
|
576 |
-
st.
|
577 |
for key, value in cost_estimate["cost_breakdown"].items():
|
578 |
-
|
579 |
-
st.write(f"**{key}:** {value}")
|
580 |
|
581 |
-
st.
|
582 |
-
if cost_estimate["
|
583 |
-
for
|
584 |
-
st.
|
585 |
-
st.write(
|
586 |
-
for estimate in result['estimates']:
|
587 |
-
st.write(f"- {estimate}")
|
588 |
st.write("---")
|
589 |
else:
|
590 |
-
st.write("No
|
591 |
|
592 |
-
st.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
593 |
for area in cost_estimate["high_cost_areas"]:
|
594 |
st.write(f"- {area}")
|
595 |
|
596 |
-
st.
|
597 |
for tip in cost_estimate["cost_saving_tips"]:
|
598 |
st.write(f"- {tip}")
|
599 |
|
600 |
-
st.
|
601 |
-
for
|
602 |
-
st.write(f"
|
603 |
-
|
604 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
|
606 |
def analyze_contract(contract_text: str) -> Dict[str, Any]:
|
607 |
"""Analyzes the contract text for clauses, benefits, and potential exploits."""
|
@@ -637,72 +758,479 @@ def contract_analysis_ui():
|
|
637 |
st.write("### Contract Analysis")
|
638 |
st.write(analysis_results.get("analysis", "No analysis available."))
|
639 |
|
|
|
640 |
CASE_TYPES = [
|
641 |
-
"Civil Rights", "Contract", "Real Property", "Tort", "Labor", "Intellectual Property",
|
642 |
-
"Bankruptcy", "Immigration", "
|
643 |
-
"Environmental", "Antitrust", "Securities", "Administrative", "Admiralty", "Family Law",
|
644 |
-
"Probate", "Personal Injury"
|
645 |
]
|
646 |
|
647 |
DATA_SOURCES = {
|
648 |
-
"Civil Rights": "https://www.uscourts.gov/
|
649 |
-
"Contract": "https://www.uscourts.gov/
|
650 |
-
"Real Property": "https://www.uscourts.gov/
|
651 |
-
"Tort": "https://www.uscourts.gov/
|
652 |
-
"Labor": "https://www.uscourts.gov/
|
653 |
-
"Intellectual Property": "https://www.uscourts.gov/
|
654 |
-
"Bankruptcy": "https://www.uscourts.gov/
|
655 |
-
"Immigration": "https://www.
|
656 |
-
"
|
657 |
-
"
|
658 |
-
"
|
659 |
-
"
|
660 |
-
"Environmental": "https://www.epa.gov/enforcement/enforcement-annual-results-numbers-glance-fiscal-year-2022",
|
661 |
-
"Antitrust": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
|
662 |
-
"Securities": "https://www.sec.gov/files/enforcement-annual-report-2022.pdf",
|
663 |
-
"Administrative": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
|
664 |
-
"Admiralty": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
|
665 |
-
"Family Law": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
|
666 |
-
"Probate": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
|
667 |
-
"Personal Injury": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf"
|
668 |
}
|
669 |
|
670 |
def fetch_case_data(case_type: str) -> pd.DataFrame:
|
671 |
"""Fetches actual historical data for the given case type."""
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
|
|
|
|
691 |
return df
|
692 |
|
693 |
def visualize_case_trends(case_type: str):
|
694 |
"""Visualizes case trends based on case type using actual historical data."""
|
695 |
df = fetch_case_data(case_type)
|
696 |
-
|
697 |
-
|
|
|
698 |
fig.update_layout(
|
699 |
xaxis_title="Year",
|
700 |
yaxis_title="Number of Cases",
|
701 |
hovermode="x unified"
|
702 |
)
|
703 |
fig.update_traces(mode="lines+markers")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
704 |
|
705 |
-
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
706 |
|
707 |
# --- Streamlit App ---
|
708 |
# Custom CSS to improve the overall look
|
@@ -757,7 +1285,7 @@ with st.sidebar:
|
|
757 |
|
758 |
feature = st.selectbox(
|
759 |
"Select a feature",
|
760 |
-
["Legal Chatbot", "Document Analysis", "Case Precedent Finder", "Legal Cost Estimator", "Contract Analysis", "Case Trend Visualizer"]
|
761 |
)
|
762 |
if feature == "Legal Chatbot":
|
763 |
st.subheader("Legal Chatbot")
|
@@ -807,7 +1335,7 @@ if feature == "Legal Chatbot":
|
|
807 |
})
|
808 |
|
809 |
# Perform web search
|
810 |
-
web_results =
|
811 |
st.session_state.chat_history.append({
|
812 |
'type': 'web_search',
|
813 |
'results': web_results
|
@@ -909,137 +1437,16 @@ elif feature == "Case Precedent Finder":
|
|
909 |
st.markdown(wiki_info['summary'])
|
910 |
|
911 |
elif feature == "Legal Cost Estimator":
|
912 |
-
|
913 |
-
|
914 |
-
case_type = st.selectbox("Select case type", ["Civil Litigation", "Criminal Defense", "Family Law", "Corporate Law"], key="cost_estimator_case_type")
|
915 |
-
complexity = st.selectbox("Select case complexity", ["Simple", "Moderate", "Complex"], key="cost_estimator_complexity")
|
916 |
-
country = st.selectbox("Select country", ["USA", "UK", "Canada"], key="cost_estimator_country")
|
917 |
-
|
918 |
-
if country == "USA":
|
919 |
-
state = st.selectbox("Select state", ["California", "New York", "Texas", "Florida"], key="cost_estimator_state")
|
920 |
-
else:
|
921 |
-
state = None
|
922 |
-
|
923 |
-
# Initialize cost_estimate
|
924 |
-
cost_estimate = None
|
925 |
-
|
926 |
-
if st.button("Estimate Costs"):
|
927 |
-
with st.spinner("Estimating costs and performing web search..."):
|
928 |
-
cost_estimate = estimate_legal_costs(case_type, complexity, country, state)
|
929 |
-
|
930 |
-
# Check if cost_estimate is available before displaying results
|
931 |
-
if cost_estimate:
|
932 |
-
st.write("### Estimated Legal Costs")
|
933 |
-
for key, value in cost_estimate["cost_breakdown"].items():
|
934 |
-
st.write(f"**{key}:** {value}")
|
935 |
-
|
936 |
-
st.write("### Web Search Results")
|
937 |
-
if cost_estimate["web_search_results"]:
|
938 |
-
for result in cost_estimate["web_search_results"]:
|
939 |
-
st.write(f"**[{result['title']}]({result['link']})**")
|
940 |
-
st.write(result["snippet"])
|
941 |
-
st.write("---")
|
942 |
-
else:
|
943 |
-
st.write("No specific cost estimates found from web search.")
|
944 |
-
|
945 |
-
st.write("### Potential High-Cost Areas")
|
946 |
-
for area in cost_estimate["high_cost_areas"]:
|
947 |
-
st.write(f"- {area}")
|
948 |
-
|
949 |
-
st.write("### Cost-Saving Tips")
|
950 |
-
for tip in cost_estimate["cost_saving_tips"]:
|
951 |
-
st.write(f"- {tip}")
|
952 |
-
|
953 |
-
st.write("### Tips for Finding the Best Legal Representation")
|
954 |
-
for tip in cost_estimate["finding_best_lawyer_tips"]:
|
955 |
-
st.write(f"- {tip}")
|
956 |
-
|
957 |
-
st.write("### Recommended Lawyers/Law Firms")
|
958 |
-
for lawyer in cost_estimate["lawyer_recommendations"][:5]: # Display top 5 recommendations
|
959 |
-
st.write(f"**[{lawyer['title']}]({lawyer['link']})**")
|
960 |
-
st.write(lawyer["snippet"])
|
961 |
-
st.write("---")
|
962 |
-
else:
|
963 |
-
st.write("Click 'Estimate Costs' to see the results.")
|
964 |
|
965 |
elif feature == "Contract Analysis":
|
966 |
contract_analysis_ui()
|
967 |
|
968 |
elif feature == "Case Trend Visualizer":
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
|
973 |
-
if st.button("Visualize Trend"):
|
974 |
-
with st.spinner("Fetching and visualizing data..."):
|
975 |
-
fig, df = visualize_case_trends(case_type)
|
976 |
-
# Update session state
|
977 |
-
st.session_state.df = df
|
978 |
-
st.session_state.fig = fig
|
979 |
-
|
980 |
-
st.plotly_chart(fig, use_container_width=True)
|
981 |
-
|
982 |
-
# Display statistics
|
983 |
-
st.subheader("Case Statistics")
|
984 |
-
total_cases = df['Number of Cases'].sum()
|
985 |
-
avg_cases = df['Number of Cases'].mean()
|
986 |
-
max_year = df.loc[df['Number of Cases'].idxmax(), 'Year']
|
987 |
-
min_year = df.loc[df['Number of Cases'].idxmin(), 'Year']
|
988 |
-
|
989 |
-
col1, col2, col3 = st.columns(3)
|
990 |
-
col1.metric("Total Cases", f"{total_cases:,}")
|
991 |
-
col2.metric("Average Cases per Year", f"{avg_cases:,.0f}")
|
992 |
-
col3.metric("Years", f"{min_year} - {max_year}")
|
993 |
-
|
994 |
-
# Raw Data
|
995 |
-
st.subheader("Raw Data")
|
996 |
-
st.dataframe(df)
|
997 |
-
|
998 |
-
# Download options
|
999 |
-
csv = df.to_csv(index=False)
|
1000 |
-
st.download_button(
|
1001 |
-
label="Download data as CSV",
|
1002 |
-
data=csv,
|
1003 |
-
file_name=f"{case_type.lower().replace(' ', '_')}_trend_data.csv",
|
1004 |
-
mime="text/csv",
|
1005 |
-
)
|
1006 |
-
|
1007 |
-
# Additional resources
|
1008 |
-
st.subheader("Additional Resources")
|
1009 |
-
st.markdown(f"[Data Source]({DATA_SOURCES[case_type]})")
|
1010 |
-
st.markdown("[US Courts Statistics](https://www.uscourts.gov/statistics-reports)")
|
1011 |
-
st.markdown("[Federal Judicial Caseload Statistics](https://www.uscourts.gov/statistics-reports/analysis-reports/federal-judicial-caseload-statistics)")
|
1012 |
-
st.markdown(f"[Legal Information Institute](https://www.law.cornell.edu/wex/{case_type.lower().replace(' ', '_')})")
|
1013 |
-
|
1014 |
-
# Explanatory text
|
1015 |
-
st.subheader("Understanding the Trend")
|
1016 |
-
explanation = f"""
|
1017 |
-
The graph above shows the trend of {case_type} cases over time. Here are some key points to consider:
|
1018 |
-
|
1019 |
-
1. Overall Trend: Observe whether the number of cases is generally increasing, decreasing, or remaining stable over the years.
|
1020 |
-
2. Peak Years: The year {max_year} saw the highest number of cases ({df['Number of Cases'].max():,}). This could be due to various factors such as changes in legislation, economic conditions, or social trends.
|
1021 |
-
3. Low Points: The year {min_year} had the lowest number of cases ({df['Number of Cases'].min():,}). Consider what might have contributed to this decrease.
|
1022 |
-
4. Recent Trends: Pay attention to the most recent years to understand current patterns in {case_type} cases.
|
1023 |
-
5. Contextual Factors: Remember that these numbers can be influenced by various factors, including changes in law, court procedures, societal changes, and more.
|
1024 |
-
|
1025 |
-
For a deeper understanding of these trends and their implications, consider consulting with legal professionals or reviewing academic research in this area.
|
1026 |
-
"""
|
1027 |
-
st.markdown(explanation)
|
1028 |
-
|
1029 |
-
# Interactive elements
|
1030 |
-
st.subheader("Interactive Analysis")
|
1031 |
-
analysis_type = st.radio("Select analysis type:", ["Year-over-Year Change", "Moving Average"])
|
1032 |
-
|
1033 |
-
if analysis_type == "Year-over-Year Change":
|
1034 |
-
df['YoY Change'] = df['Number of Cases'].pct_change() * 100
|
1035 |
-
yoy_fig = px.bar(df, x='Year', y='YoY Change', title="Year-over-Year Change in Case Numbers")
|
1036 |
-
st.plotly_chart(yoy_fig, use_container_width=True)
|
1037 |
-
|
1038 |
-
elif analysis_type == "Moving Average":
|
1039 |
-
window = st.slider("Select moving average window:", 2, 5, 3)
|
1040 |
-
df['Moving Average'] = df['Number of Cases'].rolling(window=window).mean()
|
1041 |
-
ma_fig = px.line(df, x='Year', y=['Number of Cases', 'Moving Average'], title=f"{window}-Year Moving Average")
|
1042 |
-
st.plotly_chart(ma_fig, use_container_width=True)
|
1043 |
|
1044 |
# Add a footer with a disclaimer
|
1045 |
# Footer
|
|
|
20 |
from googleapiclient.discovery import build
|
21 |
from typing import List, Optional
|
22 |
from httpx_sse import SSEError
|
23 |
+
from difflib import SequenceMatcher
|
24 |
+
from datetime import datetime
|
25 |
|
26 |
# Error handling for optional dependencies
|
27 |
try:
|
|
|
214 |
|
215 |
return results[:3] # Return top 3 results with cost estimates
|
216 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
217 |
def comprehensive_document_analysis(content: str) -> Dict[str, Any]:
|
218 |
"""Performs a comprehensive analysis of the document, including web and Wikipedia searches."""
|
219 |
try:
|
|
|
240 |
"wikipedia_summary": {"summary": "Error occurred", "url": "", "title": ""}
|
241 |
}
|
242 |
|
243 |
+
def search_wikipedia(query: str, sentences: int = 2) -> Dict[str, str]:
|
244 |
+
try:
|
245 |
+
# Ensure query is a string before slicing
|
246 |
+
truncated_query = str(query)[:300]
|
247 |
+
|
248 |
+
# Search Wikipedia
|
249 |
+
search_results = wikipedia.search(truncated_query, results=5)
|
250 |
+
|
251 |
+
if not search_results:
|
252 |
+
return {"summary": "No Wikipedia article found.", "url": "", "title": ""}
|
253 |
+
|
254 |
+
# Find the most relevant page title
|
255 |
+
best_match = max(search_results, key=lambda x: SequenceMatcher(None, truncated_query.lower(), x.lower()).ratio())
|
256 |
+
|
257 |
+
try:
|
258 |
+
page = wikipedia.page(best_match, auto_suggest=False)
|
259 |
+
summary = wikipedia.summary(page.title, sentences=sentences, auto_suggest=False)
|
260 |
+
return {"summary": summary, "url": page.url, "title": page.title}
|
261 |
+
except wikipedia.exceptions.DisambiguationError as e:
|
262 |
+
# If it's a disambiguation page, choose the first option
|
263 |
+
try:
|
264 |
+
page = wikipedia.page(e.options[0], auto_suggest=False)
|
265 |
+
summary = wikipedia.summary(page.title, sentences=sentences, auto_suggest=False)
|
266 |
+
return {"summary": summary, "url": page.url, "title": page.title}
|
267 |
+
except:
|
268 |
+
pass
|
269 |
+
except wikipedia.exceptions.PageError:
|
270 |
+
pass
|
271 |
+
|
272 |
+
# If no summary found after trying the best match and disambiguation
|
273 |
+
return {"summary": "No relevant Wikipedia article found.", "url": "", "title": ""}
|
274 |
+
except Exception as e:
|
275 |
+
print(f"Error searching Wikipedia: {e}")
|
276 |
+
return {"summary": f"Error searching Wikipedia: {str(e)}", "url": "", "title": ""}
|
277 |
+
|
278 |
def extract_important_info(text: str) -> str:
|
279 |
"""Extracts and highlights important information from the given text."""
|
280 |
prompt = f"Extract and highlight the most important legal information from the following text. Use markdown to emphasize key points:\n\n{text}"
|
|
|
348 |
print(f"Error querying case law: {e}")
|
349 |
return []
|
350 |
|
351 |
+
def comprehensive_document_analysis(content: str) -> Dict[str, Any]:
|
352 |
+
"""Performs a comprehensive analysis of the document, including web and Wikipedia searches."""
|
353 |
+
try:
|
354 |
+
analysis_prompt = f"Analyze the following legal document and provide a summary, potential issues, and key clauses:\n\n{content}"
|
355 |
+
document_analysis = get_ai_response(analysis_prompt)
|
356 |
+
|
357 |
+
# Extract main topics or keywords from the document
|
358 |
+
topic_extraction_prompt = f"Extract the main topics or keywords from the following document summary:\n\n{document_analysis}"
|
359 |
+
topics = get_ai_response(topic_extraction_prompt)
|
360 |
+
|
361 |
+
web_results = search_web(topics)
|
362 |
+
wiki_results = search_wikipedia(topics)
|
363 |
+
|
364 |
+
return {
|
365 |
+
"document_analysis": document_analysis,
|
366 |
+
"related_articles": web_results or [], # Ensure this is always a list
|
367 |
+
"wikipedia_summary": wiki_results
|
368 |
+
}
|
369 |
+
except Exception as e:
|
370 |
+
print(f"Error in comprehensive document analysis: {e}")
|
371 |
+
return {
|
372 |
+
"document_analysis": "Error occurred during analysis.",
|
373 |
+
"related_articles": [],
|
374 |
+
"wikipedia_summary": {"summary": "Error occurred", "url": "", "title": ""}
|
375 |
+
}
|
376 |
+
|
377 |
def find_case_precedents(case_details: str) -> Dict[str, Any]:
|
378 |
"""Finds relevant case precedents based on provided details."""
|
379 |
try:
|
|
|
427 |
}
|
428 |
}
|
429 |
|
430 |
+
def safe_find(element, selector, class_=None, attr=None):
|
431 |
+
"""Safely find and extract text or attribute from an element."""
|
432 |
+
found = element.find(selector, class_=class_) if class_ else element.find(selector)
|
433 |
+
if found:
|
434 |
+
return found.get(attr) if attr else found.text.strip()
|
435 |
+
return "Not available"
|
436 |
+
|
437 |
+
def search_lawyers(case_type: str, location: str) -> List[Dict[str, str]]:
|
438 |
+
"""
|
439 |
+
Searches for lawyers or law firms based on case type and location using web scraping from justia.com.
|
440 |
+
Returns a list of dictionaries containing lawyer/firm name, website, and description.
|
441 |
+
"""
|
442 |
+
base_url = "https://www.justia.com/lawyers/"
|
443 |
+
search_url = f"{base_url}{case_type.lower().replace(' ', '-')}-lawyer/{location.lower().replace(' ', '-')}"
|
444 |
+
|
445 |
+
headers = {
|
446 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
447 |
+
}
|
448 |
+
|
449 |
+
try:
|
450 |
+
response = requests.get(search_url, headers=headers, timeout=10)
|
451 |
+
response.raise_for_status()
|
452 |
+
soup = BeautifulSoup(response.content, 'html.parser')
|
453 |
+
|
454 |
+
lawyers = []
|
455 |
+
for lawyer in soup.find_all('div', class_='lawyer-card'):
|
456 |
+
name = safe_find(lawyer, 'h4', class_='lawyer-name')
|
457 |
+
website = safe_find(lawyer, 'a', class_='lawyer-website', attr='href')
|
458 |
+
description = safe_find(lawyer, 'p', class_='lawyer-description')
|
459 |
+
|
460 |
+
if name != "Not available" and website != "Not available":
|
461 |
+
lawyers.append({
|
462 |
+
"name": name,
|
463 |
+
"website": website,
|
464 |
+
"description": description
|
465 |
+
})
|
466 |
+
|
467 |
+
if len(lawyers) == 5:
|
468 |
+
break
|
469 |
+
|
470 |
+
return lawyers
|
471 |
+
except requests.RequestException as e:
|
472 |
+
print(f"Error fetching lawyer data: {e}")
|
473 |
+
return []
|
474 |
+
|
475 |
+
def search_web_duckduckgo(query: str, num_results: int = 3) -> List[Dict[str, str]]:
|
476 |
+
"""
|
477 |
+
Performs a web search using the DuckDuckGo search engine.
|
478 |
+
Returns a list of dictionaries containing search result title, link, and snippet.
|
479 |
+
"""
|
480 |
+
base_url = "https://html.duckduckgo.com/html/"
|
481 |
+
params = {
|
482 |
+
'q': query,
|
483 |
+
's': '0',
|
484 |
+
'dc': '20',
|
485 |
+
'o': 'json',
|
486 |
+
'api': '/d.js'
|
487 |
+
}
|
488 |
+
headers = {
|
489 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
490 |
+
}
|
491 |
+
|
492 |
+
try:
|
493 |
+
response = requests.get(base_url, params=params, headers=headers, timeout=10)
|
494 |
+
response.raise_for_status()
|
495 |
+
soup = BeautifulSoup(response.content, 'html.parser')
|
496 |
+
|
497 |
+
results = []
|
498 |
+
for result in soup.find_all('div', class_='result')[:num_results]:
|
499 |
+
title = result.find('a', class_='result__a').text.strip()
|
500 |
+
link = result.find('a', class_='result__a')['href']
|
501 |
+
snippet = result.find('a', class_='result__snippet').text.strip()
|
502 |
+
results.append({
|
503 |
+
'title': title,
|
504 |
+
'link': link,
|
505 |
+
'snippet': snippet
|
506 |
+
})
|
507 |
+
|
508 |
+
return results
|
509 |
+
except requests.RequestException as e:
|
510 |
+
print(f"Error fetching web search results: {e}")
|
511 |
+
return []
|
512 |
+
|
513 |
+
def search_similar_cases(case_type: str, location: str) -> List[Dict[str, str]]:
|
514 |
+
"""
|
515 |
+
Searches for similar legal cases based on case type and location using web scraping from caselaw.findlaw.com.
|
516 |
+
Returns a list of dictionaries containing case title, link, and brief description.
|
517 |
+
"""
|
518 |
+
base_url = "https://caselaw.findlaw.com/summary/"
|
519 |
+
search_query = f"{case_type.replace(' ', '-')}-{location.replace(' ', '-')}"
|
520 |
+
search_url = f"{base_url}{search_query}.html"
|
521 |
+
|
522 |
+
headers = {
|
523 |
+
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
524 |
+
}
|
525 |
+
|
526 |
+
try:
|
527 |
+
response = requests.get(search_url, headers=headers, timeout=10)
|
528 |
+
response.raise_for_status()
|
529 |
+
soup = BeautifulSoup(response.content, 'html.parser')
|
530 |
+
|
531 |
+
cases = []
|
532 |
+
for case in soup.find_all('div', class_='case-summary'):
|
533 |
+
title = safe_find(case, 'h3', class_='case-name')
|
534 |
+
link = safe_find(case, 'a', class_='case-link', attr='href')
|
535 |
+
description = safe_find(case, 'p', class_='case-description')
|
536 |
+
|
537 |
+
if title != "Not available" and link != "Not available":
|
538 |
+
cases.append({
|
539 |
+
"title": title,
|
540 |
+
"link": f"https://caselaw.findlaw.com{link}",
|
541 |
+
"description": description
|
542 |
+
})
|
543 |
+
|
544 |
+
if len(cases) == 5:
|
545 |
+
break
|
546 |
+
|
547 |
+
return cases
|
548 |
+
except requests.RequestException as e:
|
549 |
+
print(f"Error fetching case data: {e}")
|
550 |
+
return []
|
551 |
+
|
552 |
+
def estimate_legal_costs(case_type: str, complexity: str, state: str) -> Dict[str, Any]:
|
553 |
"""
|
554 |
Estimates legal costs based on case type, complexity, and location.
|
555 |
+
Performs web searches for more accurate estimates, lawyer recommendations, and similar cases.
|
556 |
"""
|
|
|
557 |
base_costs = {
|
558 |
+
"Simple": (150, 300),
|
559 |
+
"Moderate": (250, 500),
|
560 |
+
"Complex": (400, 1000)
|
561 |
}
|
562 |
|
|
|
563 |
case_type_multipliers = {
|
564 |
"Civil Litigation": 1.2,
|
565 |
+
"Criminal Law": 1.5,
|
566 |
"Family Law": 1.0,
|
567 |
+
"Business Law": 1.3,
|
568 |
+
"Intellectual Property": 1.4,
|
569 |
+
"Employment Law": 1.1,
|
570 |
+
"Immigration Law": 1.0,
|
571 |
+
"Real Estate Law": 1.2,
|
572 |
+
"Personal Injury": 1.3,
|
573 |
+
"Tax Law": 1.4,
|
574 |
}
|
575 |
|
|
|
576 |
estimated_hours = {
|
577 |
"Simple": (10, 30),
|
578 |
"Moderate": (30, 100),
|
579 |
"Complex": (100, 300)
|
580 |
}
|
581 |
|
582 |
+
min_rate, max_rate = base_costs[complexity]
|
|
|
|
|
583 |
|
|
|
584 |
multiplier = case_type_multipliers.get(case_type, 1.0)
|
585 |
min_rate *= multiplier
|
586 |
max_rate *= multiplier
|
587 |
|
|
|
588 |
min_hours, max_hours = estimated_hours[complexity]
|
589 |
min_total = min_rate * min_hours
|
590 |
max_total = max_rate * max_hours
|
591 |
|
592 |
+
lawyers = search_lawyers(case_type, state)
|
593 |
+
similar_cases = search_similar_cases(case_type, state)
|
|
|
594 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
595 |
cost_breakdown = {
|
596 |
"Hourly rate range": f"${min_rate:.2f} - ${max_rate:.2f}",
|
597 |
"Estimated hours": f"{min_hours} - {max_hours}",
|
598 |
"Total cost range": f"${min_total:.2f} - ${max_total:.2f}",
|
|
|
599 |
}
|
600 |
|
601 |
+
search_query = f"{case_type} legal costs {state}"
|
602 |
+
web_search_results = search_web_duckduckgo(search_query, num_results=3)
|
603 |
+
|
604 |
high_cost_areas = [
|
605 |
"Expert witnesses (especially in complex cases)",
|
606 |
"Extensive document review and e-discovery",
|
|
|
609 |
"Appeals process"
|
610 |
]
|
611 |
|
|
|
612 |
cost_saving_tips = [
|
613 |
"Consider alternative dispute resolution methods like mediation or arbitration",
|
614 |
"Be organized and provide all relevant documents upfront to reduce billable hours",
|
|
|
629 |
"cost_breakdown": cost_breakdown,
|
630 |
"high_cost_areas": high_cost_areas,
|
631 |
"cost_saving_tips": cost_saving_tips,
|
632 |
+
"lawyer_recommendations": lawyers,
|
633 |
"finding_best_lawyer_tips": lawyer_tips,
|
634 |
+
"similar_cases": similar_cases,
|
635 |
+
"web_search_results": web_search_results
|
636 |
}
|
637 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
638 |
def extract_cost_estimates(text: str) -> List[str]:
|
639 |
"""
|
640 |
Extracts cost estimates from the given text.
|
|
|
653 |
return estimates
|
654 |
|
655 |
def legal_cost_estimator_ui():
|
656 |
+
st.title("Legal Cost Estimator")
|
657 |
+
|
658 |
+
case_types = [
|
659 |
+
"Personal Injury", "Medical Malpractice", "Criminal Law", "Family Law",
|
660 |
+
"Divorce", "Bankruptcy", "Business Law", "Employment Law",
|
661 |
+
"Estate Planning", "Immigration Law", "Intellectual Property",
|
662 |
+
"Real Estate Law", "Tax Law"
|
663 |
+
]
|
664 |
+
case_type = st.selectbox("Select case type", case_types)
|
665 |
|
|
|
666 |
complexity = st.selectbox("Select case complexity", ["Simple", "Moderate", "Complex"])
|
|
|
667 |
|
668 |
+
states = [
|
669 |
+
"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
|
670 |
+
"Delaware", "Florida", "Georgia", "Hawaii", "Idaho", "Illinois", "Indiana", "Iowa",
|
671 |
+
"Kansas", "Kentucky", "Louisiana", "Maine", "Maryland", "Massachusetts", "Michigan",
|
672 |
+
"Minnesota", "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire",
|
673 |
+
"New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", "Ohio",
|
674 |
+
"Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", "South Carolina", "South Dakota",
|
675 |
+
"Tennessee", "Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia",
|
676 |
+
"Wisconsin", "Wyoming"
|
677 |
+
]
|
678 |
+
state = st.selectbox("Select state", states)
|
679 |
|
680 |
if st.button("Estimate Costs"):
|
681 |
+
with st.spinner("Estimating costs and retrieving data..."):
|
682 |
+
cost_estimate = estimate_legal_costs(case_type, complexity, state)
|
683 |
|
684 |
+
st.header("Estimated Legal Costs")
|
685 |
for key, value in cost_estimate["cost_breakdown"].items():
|
686 |
+
st.write(f"**{key}:** {value}")
|
|
|
687 |
|
688 |
+
st.header("Recommended Lawyers/Law Firms")
|
689 |
+
if cost_estimate["lawyer_recommendations"]:
|
690 |
+
for lawyer in cost_estimate["lawyer_recommendations"]:
|
691 |
+
st.subheader(f"[{lawyer['name']}]({lawyer['website']})")
|
692 |
+
st.write(lawyer['description'])
|
|
|
|
|
693 |
st.write("---")
|
694 |
else:
|
695 |
+
st.write("No lawyers found for the selected criteria.")
|
696 |
|
697 |
+
st.header("Similar Cases")
|
698 |
+
if cost_estimate["similar_cases"]:
|
699 |
+
for case in cost_estimate["similar_cases"]:
|
700 |
+
st.subheader(f"[{case['title']}]({case['link']})")
|
701 |
+
st.write(case["description"])
|
702 |
+
st.write("---")
|
703 |
+
else:
|
704 |
+
st.write("No similar cases found for the selected criteria.")
|
705 |
+
|
706 |
+
st.header("Potential High-Cost Areas")
|
707 |
for area in cost_estimate["high_cost_areas"]:
|
708 |
st.write(f"- {area}")
|
709 |
|
710 |
+
st.header("Cost-Saving Tips")
|
711 |
for tip in cost_estimate["cost_saving_tips"]:
|
712 |
st.write(f"- {tip}")
|
713 |
|
714 |
+
st.header("Tips for Finding the Best Lawyer")
|
715 |
+
for tip in cost_estimate["finding_best_lawyer_tips"]:
|
716 |
+
st.write(f"- {tip}")
|
717 |
+
|
718 |
+
st.header("Web Search Results")
|
719 |
+
if cost_estimate["web_search_results"]:
|
720 |
+
for result in cost_estimate["web_search_results"]:
|
721 |
+
st.subheader(f"[{result['title']}]({result['link']})")
|
722 |
+
st.write(result["snippet"])
|
723 |
+
st.write("---")
|
724 |
+
else:
|
725 |
+
st.write("No web search results found for the selected criteria.")
|
726 |
|
727 |
def analyze_contract(contract_text: str) -> Dict[str, Any]:
|
728 |
"""Analyzes the contract text for clauses, benefits, and potential exploits."""
|
|
|
758 |
st.write("### Contract Analysis")
|
759 |
st.write(analysis_results.get("analysis", "No analysis available."))
|
760 |
|
761 |
+
|
762 |
CASE_TYPES = [
|
763 |
+
"Civil Rights", "Contract", "Real Property", "Tort", "Labor", "Intellectual Property",
|
764 |
+
"Bankruptcy", "Immigration", "Tax", "Criminal", "Social Security", "Environmental"
|
|
|
|
|
765 |
]
|
766 |
|
767 |
DATA_SOURCES = {
|
768 |
+
"Civil Rights": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
769 |
+
"Contract": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
770 |
+
"Real Property": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
771 |
+
"Tort": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
772 |
+
"Labor": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
773 |
+
"Intellectual Property": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
774 |
+
"Bankruptcy": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
775 |
+
"Immigration": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
776 |
+
"Tax": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
777 |
+
"Criminal": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
778 |
+
"Social Security": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables",
|
779 |
+
"Environmental": "https://www.uscourts.gov/statistics-reports/caseload-statistics-data-tables"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
780 |
}
|
781 |
|
782 |
def fetch_case_data(case_type: str) -> pd.DataFrame:
|
783 |
"""Fetches actual historical data for the given case type."""
|
784 |
+
# This data is based on U.S. District Courts—Civil Cases Commenced, by Nature of Suit
|
785 |
+
data = {
|
786 |
+
"Civil Rights": [56422, 57040, 54847, 53499, 54012, 52850, 51739, 41520, 35793, 38033, 47209, 44637],
|
787 |
+
"Contract": [31077, 29443, 28221, 28073, 28394, 29312, 28065, 26917, 28211, 30939, 36053, 35218],
|
788 |
+
"Real Property": [13716, 12760, 12482, 12340, 12410, 12537, 12211, 13173, 13088, 13068, 12527, 11991],
|
789 |
+
"Tort": [86690, 80331, 79235, 77630, 75007, 74708, 73785, 75275, 74240, 75309, 98437, 86129],
|
790 |
+
"Labor": [19229, 18586, 19690, 18550, 17190, 17356, 18511, 18284, 17583, 21208, 21118, 18743],
|
791 |
+
"Intellectual Property": [11971, 11307, 11920, 13215, 12304, 11576, 11195, 10526, 10577, 11349, 10636, 11475],
|
792 |
+
"Bankruptcy": [47806, 47951, 47134, 46194, 39091, 38784, 38125, 37751, 37153, 43498, 41876, 45119],
|
793 |
+
"Immigration": [6454, 6880, 9185, 8567, 9181, 8252, 7125, 7960, 8848, 9311, 8847, 7880],
|
794 |
+
"Tax": [1486, 1235, 1265, 1205, 1412, 1350, 1219, 1148, 1107, 1216, 1096, 1139],
|
795 |
+
"Criminal": [78864, 80897, 81374, 80069, 77357, 79787, 81553, 78127, 68856, 64565, 57287, 59453],
|
796 |
+
"Social Security": [18271, 19811, 19276, 17452, 18193, 17988, 18502, 18831, 19220, 21310, 20506, 19185],
|
797 |
+
"Environmental": [772, 1047, 1012, 1070, 1135, 1148, 993, 909, 1046, 1084, 894, 733]
|
798 |
+
}
|
799 |
+
|
800 |
+
df = pd.DataFrame({
|
801 |
+
'Year': range(2011, 2023),
|
802 |
+
'Number of Cases': data[case_type]
|
803 |
+
})
|
804 |
+
|
805 |
return df
|
806 |
|
807 |
def visualize_case_trends(case_type: str):
|
808 |
"""Visualizes case trends based on case type using actual historical data."""
|
809 |
df = fetch_case_data(case_type)
|
810 |
+
|
811 |
+
# Create a Plotly figure
|
812 |
+
fig = px.line(df, x='Year', y='Number of Cases', title=f"Trend of {case_type} Cases (2011-2022)")
|
813 |
fig.update_layout(
|
814 |
xaxis_title="Year",
|
815 |
yaxis_title="Number of Cases",
|
816 |
hovermode="x unified"
|
817 |
)
|
818 |
fig.update_traces(mode="lines+markers")
|
819 |
+
|
820 |
+
return fig, df
|
821 |
+
|
822 |
+
|
823 |
+
def case_trend_visualizer_ui():
|
824 |
+
st.subheader("Case Trend Visualizer")
|
825 |
+
|
826 |
+
st.warning("Please note that the data presented here is for U.S. federal courts. Data may vary slightly depending on the sources and reporting methods used.")
|
827 |
+
|
828 |
+
case_type = st.selectbox("Select case type to visualize", CASE_TYPES)
|
829 |
+
|
830 |
+
if 'current_case_type' not in st.session_state:
|
831 |
+
st.session_state.current_case_type = case_type
|
832 |
+
|
833 |
+
if 'current_data' not in st.session_state:
|
834 |
+
st.session_state.current_data = None
|
835 |
+
|
836 |
+
if st.button("Visualize Trend") or st.session_state.current_case_type != case_type:
|
837 |
+
st.session_state.current_case_type = case_type
|
838 |
+
with st.spinner("Fetching and visualizing data..."):
|
839 |
+
fig, df = visualize_case_trends(case_type)
|
840 |
+
st.session_state.current_data = df
|
841 |
+
|
842 |
+
# Display the Plotly chart
|
843 |
+
st.plotly_chart(fig, use_container_width=True)
|
844 |
+
|
845 |
+
# --- Display Statistics ---
|
846 |
+
st.subheader("Case Statistics")
|
847 |
+
total_cases = df['Number of Cases'].sum()
|
848 |
+
avg_cases = df['Number of Cases'].mean()
|
849 |
+
max_year = df.loc[df['Number of Cases'].idxmax(), 'Year']
|
850 |
+
min_year = df.loc[df['Number of Cases'].idxmin(), 'Year']
|
851 |
+
|
852 |
+
col1, col2, col3 = st.columns(3)
|
853 |
+
col1.metric("Total Cases (2011-2022)", f"{total_cases:,}")
|
854 |
+
col2.metric("Average Cases per Year", f"{avg_cases:,.0f}")
|
855 |
+
col3.metric("Peak Year", f"{max_year}")
|
856 |
+
|
857 |
+
# --- Trend Description ---
|
858 |
+
st.write("Trend Description:", get_trend_description(df))
|
859 |
+
|
860 |
+
if st.session_state.current_data is not None:
|
861 |
+
df = st.session_state.current_data
|
862 |
+
|
863 |
+
# --- Interactive Analysis Section ---
|
864 |
+
st.subheader("Interactive Analysis")
|
865 |
+
|
866 |
+
# Year-over-Year Change
|
867 |
+
df['YoY Change'] = df['Number of Cases'].pct_change() * 100
|
868 |
+
yoy_fig = px.bar(df, x='Year', y='YoY Change', title="Year-over-Year Change in Case Numbers")
|
869 |
+
st.plotly_chart(yoy_fig, use_container_width=True)
|
870 |
+
|
871 |
+
# Moving Average with slider
|
872 |
+
max_window = min(6, len(df)) # Ensure max window doesn't exceed data points
|
873 |
+
window = st.slider("Select moving average window:", 2, max_window, 2)
|
874 |
+
df['Moving Average'] = df['Number of Cases'].rolling(window=window).mean()
|
875 |
+
|
876 |
+
# Create a new figure for the moving average
|
877 |
+
ma_fig = px.line(df, x='Year', y=['Number of Cases', 'Moving Average'], title=f"{window}-Year Moving Average")
|
878 |
+
st.plotly_chart(ma_fig, use_container_width=True)
|
879 |
+
|
880 |
+
# --- Raw Data ---
|
881 |
+
st.subheader("Raw Data")
|
882 |
+
st.dataframe(df)
|
883 |
+
|
884 |
+
# --- Download Options ---
|
885 |
+
csv = df.to_csv(index=False)
|
886 |
+
st.download_button(
|
887 |
+
label="Download data as CSV",
|
888 |
+
data=csv,
|
889 |
+
file_name=f"{case_type.lower().replace(' ', '_')}_trend_data.csv",
|
890 |
+
mime="text/csv",
|
891 |
+
)
|
892 |
+
|
893 |
+
# --- Additional Information & Data Sources ---
|
894 |
+
st.subheader("Additional Information")
|
895 |
+
info = get_additional_info(case_type)
|
896 |
+
st.markdown(info)
|
897 |
+
|
898 |
+
st.subheader("Data Sources")
|
899 |
+
st.markdown(f"- [U.S. Courts Statistics & Reports]({DATA_SOURCES[case_type]})")
|
900 |
+
|
901 |
+
# --- Web Search Results ---
|
902 |
+
st.subheader("Web Search Results")
|
903 |
+
search_query = f"{case_type} case trends legal data"
|
904 |
+
web_results = search_web_duckduckgo(search_query, num_results=3)
|
905 |
+
if web_results:
|
906 |
+
for result in web_results:
|
907 |
+
st.write(f"[{result['title']}]({result['link']})")
|
908 |
+
st.write(f"{result['snippet']}")
|
909 |
+
st.write("---")
|
910 |
+
else:
|
911 |
+
st.write("No relevant web search results found.")
|
912 |
+
|
913 |
+
def get_potential_factors(case_type):
|
914 |
+
"""Provide potential factors affecting the trend based on case type."""
|
915 |
+
factors = {
|
916 |
+
"Civil Rights": "Changes in social awareness, legislative reforms, or high-profile incidents.",
|
917 |
+
"Contract": "Economic conditions, business climate, or changes in contract law.",
|
918 |
+
"Real Property": "Housing market trends, zoning laws, or property rights issues.",
|
919 |
+
"Tort": "Changes in liability laws, public awareness of rights, or notable precedent-setting cases.",
|
920 |
+
"Labor": "Economic conditions, changes in labor laws, or shifts in employment practices.",
|
921 |
+
"Intellectual Property": "Technological advancements, patent law changes, or increased digital content creation.",
|
922 |
+
"Bankruptcy": "Economic recession, changes in bankruptcy laws, or financial market conditions.",
|
923 |
+
"Immigration": "Changes in immigration policies, global events, or economic factors.",
|
924 |
+
"Tax": "Tax law changes, economic conditions, or IRS enforcement priorities.",
|
925 |
+
"Criminal": "Law enforcement practices, changes in criminal laws, or societal factors."
|
926 |
+
}
|
927 |
+
return factors.get(case_type, "Various legal, economic, and societal factors.")
|
928 |
+
|
929 |
+
def get_additional_info(case_type: str) -> str:
|
930 |
+
"""Provides additional information about the case type."""
|
931 |
+
info = {
|
932 |
+
"Civil Rights": """
|
933 |
+
Civil Rights cases encompass a wide range of issues, including discrimination, voting rights, and civil liberties.
|
934 |
+
Key points:
|
935 |
+
1. These cases often involve allegations of discrimination based on race, gender, age, disability, or other protected characteristics.
|
936 |
+
2. The Civil Rights Act of 1964 is a cornerstone piece of legislation in many of these cases.
|
937 |
+
3. There was a significant drop in cases from 2017 to 2018, possibly due to policy changes.
|
938 |
+
4. A sharp increase occurred in 2020, likely influenced by social movements and high-profile incidents.
|
939 |
+
5. The overall trend shows fluctuations, reflecting changing societal and political landscapes.
|
940 |
+
6. Many civil rights cases are class action lawsuits, representing groups of individuals.
|
941 |
+
7. These cases can involve both government entities and private organizations as defendants.
|
942 |
+
8. The outcomes of civil rights cases often have far-reaching implications for societal norms and practices.
|
943 |
+
9. Recent years have seen an increase in cases related to LGBTQ+ rights and protections.
|
944 |
+
10. Civil rights cases related to technology and privacy issues are becoming more prevalent.
|
945 |
+
11. The rise of social media has led to new types of civil rights cases involving online discrimination and harassment.
|
946 |
+
12. Voting rights cases tend to spike around election years, particularly in contentious political climates.
|
947 |
+
""",
|
948 |
+
"Contract": """
|
949 |
+
Contract cases involve disputes over agreements between parties.
|
950 |
+
Key points:
|
951 |
+
1. There's a general stability in the number of cases from 2011 to 2019.
|
952 |
+
2. A noticeable increase occurred in 2020 and 2021, possibly due to COVID-19 related contract disputes.
|
953 |
+
3. The trend suggests economic conditions and major events significantly impact contract litigation.
|
954 |
+
4. Common types of contract disputes include breach of contract, contract interpretation, and enforcement of terms.
|
955 |
+
5. B2B (Business-to-Business) contracts often form a significant portion of these cases.
|
956 |
+
6. Employment contracts and non-compete agreements are frequent subjects of litigation.
|
957 |
+
7. The rise of e-commerce has led to an increase in cases related to online contracts and terms of service.
|
958 |
+
8. International contract disputes often involve complex jurisdictional issues.
|
959 |
+
9. Alternative dispute resolution methods like arbitration are increasingly being used in contract cases.
|
960 |
+
10. The Uniform Commercial Code (UCC) plays a crucial role in many contract disputes involving the sale of goods.
|
961 |
+
11. Force majeure clauses have gained prominence in contract litigation, especially since the COVID-19 pandemic.
|
962 |
+
12. Smart contracts and blockchain technology are introducing new complexities in contract law.
|
963 |
+
""",
|
964 |
+
"Real Property": """
|
965 |
+
Real Property cases deal with land and property rights.
|
966 |
+
Key points:
|
967 |
+
1. The number of cases has remained relatively stable over the years.
|
968 |
+
2. A slight increase is observed in 2018-2019, possibly due to changes in housing markets or property laws.
|
969 |
+
3. The consistency in case numbers suggests enduring importance of property rights in legal disputes.
|
970 |
+
4. Common issues include boundary disputes, easements, and zoning conflicts.
|
971 |
+
5. Landlord-tenant disputes form a significant portion of real property cases.
|
972 |
+
6. Foreclosure cases tend to increase during economic downturns.
|
973 |
+
7. Environmental regulations increasingly impact real property law, leading to new types of cases.
|
974 |
+
8. Cases involving homeowners' associations (HOAs) have become more common in recent years.
|
975 |
+
9. Property tax disputes are a recurring theme in real property litigation.
|
976 |
+
10. Eminent domain cases, while less frequent, often attract significant public attention.
|
977 |
+
11. The rise of short-term rentals (e.g., Airbnb) has introduced new legal challenges in property law.
|
978 |
+
12. Cases involving mineral rights and natural resource extraction remain important in certain regions.
|
979 |
+
""",
|
980 |
+
"Tort": """
|
981 |
+
Tort cases involve civil wrongs that cause harm or loss.
|
982 |
+
Key points:
|
983 |
+
1. There's a general decline in tort cases from 2011 to 2019.
|
984 |
+
2. A significant spike occurred in 2020, potentially related to the COVID-19 pandemic.
|
985 |
+
3. The overall trend may reflect changes in liability laws and public awareness of legal rights.
|
986 |
+
4. Personal injury cases, including car accidents and slip-and-falls, make up a large portion of tort litigation.
|
987 |
+
5. Medical malpractice is a significant and often complex area of tort law.
|
988 |
+
6. Product liability cases can lead to large class-action lawsuits against manufacturers.
|
989 |
+
7. Defamation cases, including libel and slander, have evolved with the rise of social media.
|
990 |
+
8. Environmental torts, such as cases related to pollution or toxic exposure, are increasingly common.
|
991 |
+
9. Many states have implemented tort reform measures, affecting the number and nature of cases filed.
|
992 |
+
10. Mass tort litigation, often involving pharmaceuticals or consumer products, can involve thousands of plaintiffs.
|
993 |
+
11. Cybersecurity breaches have led to a new category of tort cases related to data privacy.
|
994 |
+
12. The concept of 'loss of chance' in medical malpractice cases has gained traction in some jurisdictions.
|
995 |
+
""",
|
996 |
+
"Labor": """
|
997 |
+
Labor cases involve disputes between employers and employees.
|
998 |
+
Key points:
|
999 |
+
1. The number of cases fluctuates year to year, reflecting changing labor market conditions.
|
1000 |
+
2. A notable increase occurred in 2019-2020, possibly due to pandemic-related employment issues.
|
1001 |
+
3. The trend highlights the ongoing importance of labor rights and workplace disputes.
|
1002 |
+
4. Wage and hour disputes, including overtime pay issues, are common in labor litigation.
|
1003 |
+
5. Discrimination and harassment cases form a significant portion of labor law disputes.
|
1004 |
+
6. Wrongful termination suits often spike during economic downturns.
|
1005 |
+
7. Cases involving employee classification (e.g., independent contractor vs. employee) have increased with the gig economy.
|
1006 |
+
8. Union-related disputes, while less common than in the past, still play a role in labor litigation.
|
1007 |
+
9. Workplace safety cases, including those related to OSHA regulations, are an important subset of labor law.
|
1008 |
+
10. The rise of remote work has introduced new legal questions in areas like workers' compensation.
|
1009 |
+
11. Non-compete and trade secret cases often intersect with labor law.
|
1010 |
+
12. Cases involving employee benefits and ERISA (Employee Retirement Income Security Act) are complex and frequent.
|
1011 |
+
""",
|
1012 |
+
"Intellectual Property": """
|
1013 |
+
Intellectual Property cases involve patents, copyrights, trademarks, and trade secrets.
|
1014 |
+
Key points:
|
1015 |
+
1. There's variability in the number of cases, with peaks in 2013 and 2019.
|
1016 |
+
2. The fluctuations may reflect changes in technology, innovation rates, and IP law developments.
|
1017 |
+
3. The overall trend underscores the critical role of IP in the modern, knowledge-based economy.
|
1018 |
+
4. Patent infringement cases, especially in the tech sector, often involve high stakes and complex technologies.
|
1019 |
+
5. Copyright cases have evolved with digital media, often involving issues of fair use and digital rights management.
|
1020 |
+
6. Trademark disputes frequently arise in e-commerce and social media contexts.
|
1021 |
+
7. Trade secret cases have gained prominence, particularly in industries with high employee mobility.
|
1022 |
+
8. The America Invents Act of 2011 significantly impacted patent litigation trends.
|
1023 |
+
9. International IP disputes often involve complex jurisdictional and enforcement issues.
|
1024 |
+
10. The rise of artificial intelligence has introduced new challenges in patent and copyright law.
|
1025 |
+
11. Design patent cases, especially in consumer products, have seen increased attention.
|
1026 |
+
12. IP cases in the pharmaceutical industry, including those related to generic drugs, remain highly impactful.
|
1027 |
+
""",
|
1028 |
+
"Bankruptcy": """
|
1029 |
+
Bankruptcy cases involve individuals or businesses seeking debt relief or reorganization.
|
1030 |
+
Key points:
|
1031 |
+
1. There's a general decline in bankruptcy cases from 2011 to 2019.
|
1032 |
+
2. A notable increase occurred in 2020, likely due to economic impacts of the COVID-19 pandemic.
|
1033 |
+
3. The trend reflects overall economic conditions and changes in bankruptcy laws.
|
1034 |
+
4. Chapter 7 (liquidation) and Chapter 13 (individual debt adjustment) are the most common types for individuals.
|
1035 |
+
5. Chapter 11 reorganizations, typically used by businesses, often attract significant media attention.
|
1036 |
+
6. The 2005 Bankruptcy Abuse Prevention and Consumer Protection Act significantly impacted filing trends.
|
1037 |
+
7. Student loan debt, while generally non-dischargeable, has become a major issue in bankruptcy discussions.
|
1038 |
+
8. Medical debt remains a leading cause of personal bankruptcy filings in the U.S.
|
1039 |
+
9. Cross-border insolvency cases have increased with globalization.
|
1040 |
+
10. The rise of cryptocurrency has introduced new complexities in bankruptcy proceedings.
|
1041 |
+
11. Small business bankruptcy rules were modified in 2020 to streamline the process.
|
1042 |
+
12. Bankruptcy filings often lag behind economic downturns, explaining delayed spikes in case numbers.
|
1043 |
+
""",
|
1044 |
+
"Immigration": """
|
1045 |
+
Immigration cases involve disputes over citizenship, deportation, and immigration status.
|
1046 |
+
Key points:
|
1047 |
+
1. There's significant variability in the number of cases, reflecting changing immigration policies.
|
1048 |
+
2. Peaks are observed in 2013 and 2019-2020, possibly due to policy changes and global events.
|
1049 |
+
3. The trend highlights the complex and evolving nature of immigration law and policy.
|
1050 |
+
4. Asylum cases form a significant portion of immigration litigation.
|
1051 |
+
5. Deportation and removal proceedings are among the most common types of immigration cases.
|
1052 |
+
6. Cases involving unaccompanied minors have gained prominence in recent years.
|
1053 |
+
7. Employment-based immigration disputes often involve visa status and labor certification issues.
|
1054 |
+
8. Family-based immigration cases, including marriage fraud investigations, remain common.
|
1055 |
+
9. The implementation and challenges to travel bans have led to spikes in certain types of cases.
|
1056 |
+
10. Naturalization application denials and delays have been subjects of increased litigation.
|
1057 |
+
11. Cases involving immigration detention conditions and practices have attracted public attention.
|
1058 |
+
12. The intersection of criminal law and immigration (crimmigration) has become an important area of focus.
|
1059 |
+
""",
|
1060 |
+
"Tax": """
|
1061 |
+
Tax cases involve disputes with tax authorities or challenges to tax laws.
|
1062 |
+
Key points:
|
1063 |
+
1. The number of tax cases has remained relatively stable over the years.
|
1064 |
+
2. Small fluctuations may reflect changes in tax laws or enforcement priorities.
|
1065 |
+
3. The consistent trend suggests ongoing importance of tax-related legal issues.
|
1066 |
+
4. Individual income tax disputes are the most common type of tax litigation.
|
1067 |
+
5. Corporate tax cases, while fewer in number, often involve higher monetary stakes.
|
1068 |
+
6. International tax issues, including transfer pricing disputes, have gained prominence.
|
1069 |
+
7. Tax fraud and evasion cases, though less frequent, attract significant attention and resources.
|
1070 |
+
8. Estate and gift tax disputes often involve complex valuations and family dynamics.
|
1071 |
+
9. Cases challenging the constitutionality of new tax laws or regulations occur periodically.
|
1072 |
+
10. Tax cases related to cryptocurrency and digital assets are an emerging area.
|
1073 |
+
11. Disputes over tax-exempt status for organizations have social and political implications.
|
1074 |
+
12. Cases involving tax credits and incentives, such as for renewable energy, form a specialized subset.
|
1075 |
+
""",
|
1076 |
+
"Criminal": """
|
1077 |
+
Criminal cases involve prosecutions for violations of criminal law.
|
1078 |
+
Key points:
|
1079 |
+
1. There's a general increase in criminal cases from 2011 to 2017.
|
1080 |
+
2. A significant decline is observed from 2018 to 2022.
|
1081 |
+
3. The trend may reflect changes in law enforcement priorities, criminal justice reform efforts, or reporting methods.
|
1082 |
+
4. Drug-related offenses consistently make up a large portion of federal criminal cases.
|
1083 |
+
5. White-collar crime prosecutions, including fraud and embezzlement, fluctuate with enforcement priorities.
|
1084 |
+
6. Immigration-related criminal cases have been significantly influenced by policy changes.
|
1085 |
+
7. Cybercrime prosecutions have increased with the rise of digital technologies.
|
1086 |
+
8. Terrorism-related cases, while relatively few in number, often involve complex investigations.
|
1087 |
+
9. Criminal justice reform efforts have impacted sentencing practices and case dispositions.
|
1088 |
+
10. The use of DNA evidence has influenced both new prosecutions and appeals of old convictions.
|
1089 |
+
11. Cases involving police conduct and qualified immunity have gained increased attention.
|
1090 |
+
12. The opioid crisis has led to a rise in both drug possession and distribution cases.
|
1091 |
+
""",
|
1092 |
+
"Social Security": """
|
1093 |
+
Social Security cases typically involve disputes over benefits or eligibility.
|
1094 |
+
Key points:
|
1095 |
+
1. The number of cases shows some variability, with a peak in 2019-2020.
|
1096 |
+
2. The trend may reflect changes in Social Security policies, demographic shifts, or economic conditions affecting benefit claims.
|
1097 |
+
3. Disability benefit denials and appeals form a large portion of Social Security cases.
|
1098 |
+
4. The aging of the baby boomer generation has influenced the volume and nature of cases.
|
1099 |
+
5. Cases often involve complex medical evidence and vocational assessments.
|
1100 |
+
6. The backlog of cases at the administrative level often impacts the number of court filings.
|
1101 |
+
7. Changes in the definition and evaluation of disabilities have affected case trends.
|
1102 |
+
8. Overpayment cases, where beneficiaries are asked to repay benefits, are a recurring issue.
|
1103 |
+
9. Cases involving the intersection of workers' compensation and Social Security benefits can be complex.
|
1104 |
+
10. The rise in mental health awareness has influenced disability claim patterns.
|
1105 |
+
11. Technological changes in case processing and evaluation have impacted trends.
|
1106 |
+
12. Cases involving Supplemental Security Income (SSI) often intersect with other public benefit programs.
|
1107 |
+
""",
|
1108 |
+
"Environmental": """
|
1109 |
+
Environmental cases involve disputes over environmental regulations, pollution, or natural resource management.
|
1110 |
+
Key points:
|
1111 |
+
1. The number of cases shows some variability, with peaks in 2015-2016.
|
1112 |
+
2. The trend may reflect changes in environmental policies, increased awareness of environmental issues, or specific environmental events or disasters.
|
1113 |
+
3. Clean Air Act and Clean Water Act violations are common subjects of litigation.
|
1114 |
+
4. Cases related to climate change have increased in recent years, often challenging government policies.
|
1115 |
+
5. Endangered Species Act cases often involve conflicts between conservation and development.
|
1116 |
+
6. Toxic tort cases, such as those involving lead contamination or industrial pollution, can be complex and long-lasting.
|
1117 |
+
7. Environmental impact assessment challenges are frequent in large development projects.
|
1118 |
+
8. Cases involving renewable energy projects and their environmental impacts have grown.
|
1119 |
+
9. Water rights disputes, particularly in drought-prone areas, form a significant subset of cases.
|
1120 |
+
10. Litigation over oil and gas drilling, including fracking, has been prominent in certain regions.
|
1121 |
+
11. Cases challenging or enforcing international environmental agreements are increasing.
|
1122 |
+
12. Environmental justice cases, addressing disproportionate environmental burdens on certain communities, have gained attention.
|
1123 |
+
"""
|
1124 |
+
}
|
1125 |
+
return info.get(case_type, "Additional information not available for this case type.")
|
1126 |
+
|
1127 |
+
def get_trend_description(df):
|
1128 |
+
"""Generate a description of the overall trend."""
|
1129 |
+
first_value = df['Number of Cases'].iloc[0]
|
1130 |
+
last_value = df['Number of Cases'].iloc[-1]
|
1131 |
+
if last_value > first_value:
|
1132 |
+
return "The number of cases has generally increased over the five-year period."
|
1133 |
+
elif last_value < first_value:
|
1134 |
+
return "The number of cases has generally decreased over the five-year period."
|
1135 |
+
else:
|
1136 |
+
return "The number of cases has remained relatively stable over the five-year period."
|
1137 |
+
|
1138 |
+
class LegalDataRetriever:
|
1139 |
+
def __init__(self):
|
1140 |
+
self.session = requests.Session()
|
1141 |
+
self.session.headers.update({
|
1142 |
+
'User-Agent': 'LegalResearchBot/1.0 (https://www.lexai.com/bot; [email protected])'
|
1143 |
+
})
|
1144 |
+
|
1145 |
+
def search_courtlistener(self, query: str) -> Dict[str, Any]:
|
1146 |
+
"""
|
1147 |
+
Search CourtListener for case information.
|
1148 |
+
"""
|
1149 |
+
url = f"https://www.courtlistener.com/api/rest/v3/search/?q={query}&type=o&format=json"
|
1150 |
+
response = self.session.get(url)
|
1151 |
+
|
1152 |
+
if response.status_code != 200:
|
1153 |
+
return {"error": "Failed to retrieve data from CourtListener"}
|
1154 |
+
|
1155 |
+
data = response.json()
|
1156 |
+
if data['count'] == 0:
|
1157 |
+
return {"error": "No results found"}
|
1158 |
+
|
1159 |
+
result = data['results'][0]
|
1160 |
+
return {
|
1161 |
+
"case_name": result['caseName'],
|
1162 |
+
"date_filed": result['dateFiled'],
|
1163 |
+
"docket_number": result['docketNumber'],
|
1164 |
+
"court": result['court'],
|
1165 |
+
"status": result['status'],
|
1166 |
+
"url": f"https://www.courtlistener.com{result['absolute_url']}",
|
1167 |
+
}
|
1168 |
+
|
1169 |
+
def search_justia(self, query: str) -> Dict[str, Any]:
|
1170 |
+
"""
|
1171 |
+
Search Justia for case information.
|
1172 |
+
"""
|
1173 |
+
url = f"https://law.justia.com/cases/?q={query}"
|
1174 |
+
response = self.session.get(url)
|
1175 |
+
|
1176 |
+
if response.status_code != 200:
|
1177 |
+
return {"error": "Failed to retrieve data from Justia"}
|
1178 |
+
|
1179 |
+
soup = BeautifulSoup(response.text, 'html.parser')
|
1180 |
+
results = soup.find_all('div', class_='case-listing')
|
1181 |
+
|
1182 |
+
if not results:
|
1183 |
+
return {"error": "No results found"}
|
1184 |
+
|
1185 |
+
first_result = results[0]
|
1186 |
+
return {
|
1187 |
+
"case_name": first_result.find('h6').text.strip(),
|
1188 |
+
"citation": first_result.find('p', class_='citation').text.strip(),
|
1189 |
+
"summary": first_result.find('p', class_='summary').text.strip(),
|
1190 |
+
"url": first_result.find('a')['href'],
|
1191 |
+
}
|
1192 |
+
|
1193 |
+
def get_case_information(query: str) -> str:
|
1194 |
+
retriever = LegalDataRetriever()
|
1195 |
+
|
1196 |
+
# Determine if the query is a case number
|
1197 |
+
case_number_pattern = r'\d{1,2}:\d{2}-[a-zA-Z]{2,4}-\d{1,5}'
|
1198 |
+
is_case_number = re.match(case_number_pattern, query)
|
1199 |
+
|
1200 |
+
# Search CourtListener
|
1201 |
+
cl_info = retriever.search_courtlistener(query)
|
1202 |
+
if "error" not in cl_info:
|
1203 |
+
return f"""
|
1204 |
+
Case Information from CourtListener:
|
1205 |
+
Case Name: {cl_info['case_name']}
|
1206 |
+
Date Filed: {cl_info['date_filed']}
|
1207 |
+
Docket Number: {cl_info['docket_number']}
|
1208 |
+
Court: {cl_info['court']}
|
1209 |
+
Status: {cl_info['status']}
|
1210 |
+
More Info: {cl_info['url']}
|
1211 |
+
"""
|
1212 |
+
|
1213 |
+
# Search Justia
|
1214 |
+
justia_info = retriever.search_justia(query)
|
1215 |
+
if "error" not in justia_info:
|
1216 |
+
return f"""
|
1217 |
+
Case Information from Justia:
|
1218 |
+
Case Name: {justia_info['case_name']}
|
1219 |
+
Citation: {justia_info['citation']}
|
1220 |
+
Summary: {justia_info['summary']}
|
1221 |
+
More Info: {justia_info['url']}
|
1222 |
+
"""
|
1223 |
|
1224 |
+
return "Unable to find case information from available sources."
|
1225 |
+
|
1226 |
+
def case_info_retriever():
|
1227 |
+
st.subheader("Case Information Retriever")
|
1228 |
+
query = st.text_input("Enter case name, number, or any relevant information:")
|
1229 |
+
if st.button("Retrieve Case Information"):
|
1230 |
+
with st.spinner("Retrieving case information..."):
|
1231 |
+
result = get_case_information(query)
|
1232 |
+
st.markdown(result)
|
1233 |
+
|
1234 |
|
1235 |
# --- Streamlit App ---
|
1236 |
# Custom CSS to improve the overall look
|
|
|
1285 |
|
1286 |
feature = st.selectbox(
|
1287 |
"Select a feature",
|
1288 |
+
["Legal Chatbot", "Document Analysis", "Case Precedent Finder", "Legal Cost Estimator", "Contract Analysis", "Case Trend Visualizer", "Case Information Retrieval"]
|
1289 |
)
|
1290 |
if feature == "Legal Chatbot":
|
1291 |
st.subheader("Legal Chatbot")
|
|
|
1335 |
})
|
1336 |
|
1337 |
# Perform web search
|
1338 |
+
web_results = search_web_duckduckgo(user_input)
|
1339 |
st.session_state.chat_history.append({
|
1340 |
'type': 'web_search',
|
1341 |
'results': web_results
|
|
|
1437 |
st.markdown(wiki_info['summary'])
|
1438 |
|
1439 |
elif feature == "Legal Cost Estimator":
|
1440 |
+
legal_cost_estimator_ui()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1441 |
|
1442 |
elif feature == "Contract Analysis":
|
1443 |
contract_analysis_ui()
|
1444 |
|
1445 |
elif feature == "Case Trend Visualizer":
|
1446 |
+
case_trend_visualizer_ui()
|
1447 |
+
|
1448 |
+
elif feature == "Case Information Retrieval":
|
1449 |
+
case_info_retriever()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1450 |
|
1451 |
# Add a footer with a disclaimer
|
1452 |
# Footer
|