Johan713 commited on
Commit
dacabff
·
verified ·
1 Parent(s): ed33401

Update app2.py

Browse files
Files changed (1) hide show
  1. app2.py +720 -313
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 estimate_legal_costs(case_type: str, complexity: str, country: str, state: str = None) -> Dict[str, Any]:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  """
397
  Estimates legal costs based on case type, complexity, and location.
398
- Performs web searches for more accurate estimates and lawyer recommendations.
399
  """
400
- # Base cost ranges per hour (in USD) for different countries
401
  base_costs = {
402
- "USA": {"Simple": (150, 300), "Moderate": (250, 500), "Complex": (400, 1000)},
403
- "UK": {"Simple": (100, 250), "Moderate": (200, 400), "Complex": (350, 800)},
404
- "Canada": {"Simple": (125, 275), "Moderate": (225, 450), "Complex": (375, 900)},
405
  }
406
 
407
- # Adjust costs based on case type
408
  case_type_multipliers = {
409
  "Civil Litigation": 1.2,
410
- "Criminal Defense": 1.5,
411
  "Family Law": 1.0,
412
- "Corporate Law": 1.3,
 
 
 
 
 
 
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
- # Get base cost range for the specified country and complexity
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
- # Perform web search for recent cost estimates
437
- search_query = f"{case_type} legal costs {country} {state if state else ''}"
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
- # Potential high-cost areas
 
 
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": lawyer_results,
493
  "finding_best_lawyer_tips": lawyer_tips,
494
- "web_search_results": web_results # Add this new key
 
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.subheader("Legal Cost Estimator")
 
 
 
 
 
 
 
 
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
- if country == "USA":
568
- state = st.selectbox("Select state", ["California", "New York", "Texas", "Florida"])
569
- else:
570
- state = None
 
 
 
 
 
 
 
571
 
572
  if st.button("Estimate Costs"):
573
- with st.spinner("Estimating costs and performing web search..."):
574
- cost_estimate = estimate_legal_costs(case_type, complexity, country, state)
575
 
576
- st.write("### Estimated Legal Costs")
577
  for key, value in cost_estimate["cost_breakdown"].items():
578
- if key != "Web search estimates":
579
- st.write(f"**{key}:** {value}")
580
 
581
- st.write("### Web Search Estimates")
582
- if cost_estimate["cost_breakdown"]["Web search estimates"]:
583
- for result in cost_estimate["cost_breakdown"]["Web search estimates"]:
584
- st.write(f"**Source:** [{result['source']}]({result['link']})")
585
- st.write("**Estimated Costs:**")
586
- for estimate in result['estimates']:
587
- st.write(f"- {estimate}")
588
  st.write("---")
589
  else:
590
- st.write("No specific cost estimates found from web search.")
591
 
592
- st.write("### Potential High-Cost Areas")
 
 
 
 
 
 
 
 
 
593
  for area in cost_estimate["high_cost_areas"]:
594
  st.write(f"- {area}")
595
 
596
- st.write("### Cost-Saving Tips")
597
  for tip in cost_estimate["cost_saving_tips"]:
598
  st.write(f"- {tip}")
599
 
600
- st.write("### Recommended Lawyers/Law Firms")
601
- for lawyer in cost_estimate["lawyer_recommendations"][:5]: # Display top 5 recommendations
602
- st.write(f"**[{lawyer['title']}]({lawyer['link']})**")
603
- st.write(lawyer["snippet"])
604
- st.write("---")
 
 
 
 
 
 
 
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", "Social Security", "Tax", "Constitutional", "Criminal",
643
- "Environmental", "Antitrust", "Securities", "Administrative", "Admiralty", "Family Law",
644
- "Probate", "Personal Injury"
645
  ]
646
 
647
  DATA_SOURCES = {
648
- "Civil Rights": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
649
- "Contract": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
650
- "Real Property": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
651
- "Tort": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
652
- "Labor": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
653
- "Intellectual Property": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
654
- "Bankruptcy": "https://www.uscourts.gov/sites/default/files/data_tables/jb_f_0930.2022.pdf",
655
- "Immigration": "https://www.justice.gov/eoir/workload-and-adjudication-statistics",
656
- "Social Security": "https://www.ssa.gov/open/data/hearings-and-appeals-filed.html",
657
- "Tax": "https://www.ustaxcourt.gov/statistics.html",
658
- "Constitutional": "https://www.uscourts.gov/sites/default/files/data_tables/jb_c2_0930.2022.pdf",
659
- "Criminal": "https://www.uscourts.gov/sites/default/files/data_tables/jb_d1_0930.2022.pdf",
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
- url = DATA_SOURCES[case_type]
673
- response = requests.get(url)
674
- if response.status_code == 200:
675
- if url.endswith('.pdf'):
676
- # For PDF sources, we'll use a placeholder DataFrame
677
- # In a real-world scenario, you'd need to implement PDF parsing
678
- df = pd.DataFrame({
679
- 'Year': range(2013, 2023),
680
- 'Number of Cases': [random.randint(1000, 5000) for _ in range(10)]
681
- })
682
- else:
683
- # For non-PDF sources, we'll assume CSV format
684
- df = pd.read_csv(StringIO(response.text))
685
- else:
686
- st.error(f"Failed to fetch data for {case_type}. Using placeholder data.")
687
- df = pd.DataFrame({
688
- 'Year': range(2013, 2023),
689
- 'Number of Cases': [random.randint(1000, 5000) for _ in range(10)]
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
- fig = px.line(df, x='Year', y='Number of Cases', title=f"Trend of {case_type} Cases")
 
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 fig, df # Return both the image and the raw data
 
 
 
 
 
 
 
 
 
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 = search_web(user_input)
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
- st.subheader("Legal Cost Estimator")
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
- st.subheader("Case Trend Visualizer")
970
-
971
- case_type = st.selectbox("Select case type to visualize", CASE_TYPES)
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