chrissoria commited on
Commit
338ad7e
·
1 Parent(s): b9fb772

Clean up: replace code dump with proper system prompt for chat

Browse files
Files changed (2) hide show
  1. R/sir_model.R +0 -459
  2. app.R +36 -3
R/sir_model.R CHANGED
@@ -530,462 +530,3 @@ sir_three_group_pu <- function(## parameters related to popn
530
 
531
  }
532
 
533
- function_in_string <- "You are in expert in these functions being run in a shiny app:
534
-
535
- avg_contact_matrix_3gp <- function(dbar_a, dbar_b, dbar_c,
536
- N_a, N_b, N_c,
537
- beta_a, beta_b) {
538
- #h_a, h_b) {
539
-
540
- # fraction of total degree in group a and group b
541
- m_a <- (N_a * dbar_a) / ((N_a * dbar_a) + (N_b * dbar_b) + (N_c * dbar_c))
542
- m_b <- (N_b * dbar_b) / ((N_a * dbar_a) + (N_b * dbar_b) + (N_c * dbar_c))
543
- m_c <- (N_c * dbar_c) / ((N_a * dbar_a) + (N_b * dbar_b) + (N_c * dbar_c))
544
-
545
- q_aa <- m_a^(1/beta_a)
546
- q_bb <- m_b^(1/beta_b)
547
-
548
- #q_aa <- h_a
549
- #q_bb <- h_b
550
-
551
-
552
- ## for a's contacts w/ other groups, assume they are distributed
553
- ## in proportion to the other groups' share of edges
554
-
555
- q_ab <- (1-q_aa) * (m_b / (m_b + m_c))
556
- q_ac <- (1-q_aa) * (m_c / (m_b + m_c))
557
-
558
- # implied by q_ab and q_ac
559
- q_ba <- q_ab*(dbar_a*N_a)/(N_b*dbar_b)
560
- # and then q_bc has to make them add up to 1
561
- q_bc <- (1 - (q_ba + q_bb))
562
-
563
- q_ca <- q_ac*dbar_a*N_a/(N_c*dbar_c)
564
-
565
- q_cb <- q_bc * (dbar_b*N_b)/(dbar_c*N_c)
566
-
567
- # q_cc is residual
568
- q_cc <- 1 - (q_ca + q_cb)
569
-
570
- # implied beta_c
571
- beta_c_implied <- log(m_c) / log(q_bb)
572
-
573
- # q matrix
574
- q_beta <- t(matrix(c(q_aa, q_ab, q_ac,
575
- q_ba, q_bb, q_bc,
576
- q_ca, q_cb, q_cc),
577
- nrow=3))
578
- ## this matrix has the avg number of contacts between groups
579
-
580
- c_mat <- q_beta
581
- c_mat[1,] <- c_mat[1,] * dbar_a
582
- c_mat[2,] <- c_mat[2,] * dbar_b
583
- c_mat[3,] <- c_mat[3,] * dbar_c
584
-
585
- return(c_mat)
586
-
587
- }
588
-
589
-
590
- sir_three_group_pu <- function(## parameters related to popn
591
- N0 = 10000000, # population size
592
- frac_a = 0.33, # fraction of population in group A
593
- frac_b = 0.33, # fraction of population in group B
594
- ## parameters related to contacts
595
- cmax = NA, # initial/max average number of contacts per day (specify only if its the same for both groups, otherwise NA)
596
- cmax_a = 8, cmax_b = 8, cmax_c=8, # initial/max average number of contacts per day by group
597
- cmin = NA, # min average contact
598
- cmin_a = 3, cmin_b = 3, cmin_c=3,
599
- beta_a=1, # homophily parameter for group a (beta_a = 1 means unbiased mixing; bigger values mean homophily)
600
- beta_b=1, # homophily parameter for group b (beta_b = 1 means unbiased mixing; bigger values mean homophily)
601
- #h_a=.5, # proportion of group A's total contact with members of their own group
602
- #h_b=.5, # proportion of group A's total contact with members of their own group
603
- ##
604
- zeta = NA, # responsiveness of contact to deaths
605
- zeta_a = 0.01, zeta_b = 0, zeta_c = 0.005,
606
- trans_p = 0.05, # probability of transmission given contact (or susceptibility to infection given contact)
607
- rho=1/10,# 1 / infectious period or recovery rate
608
- mu = NA,# probability of dying following infection
609
- mu_a = 0.01, mu_b = 0.01, mu_c = .01, # can let it differ between groups to crudely account for difference in age composition between groups
610
- kappa=0.9, # scaling factor for probability of transmission given contact resulting from protective behavior; kappa=1 means no protection, kappa = 0 means perfect protection
611
- phi = NA, # waning of protective behavior
612
- phi_a = 0, phi_b=0, phi_c=0,
613
- I0_a=1, I0_b=1, I0_c=1, #intial infected in each group
614
- time = 500, # time steps for simulation
615
- pi = NA, # background rate of adopting protective behavior
616
- pi_a = 0.05, pi_b = 0.05, pi_c = 0.05,
617
- ell = 1, # time window for considering deaths that influence adoption of protective behavior
618
- vacc = NA, # vaccination rate (goes from S to R)
619
- # in Roubenoff et al. we assume about 2 million daily doses are distributed which is ~ 0.6 % of the population per day
620
- vacc_a = 0.006, vacc_b = 0.006, vacc_c = 0.006,
621
- vstart = 365, # start of vaccination
622
- gamma = 1/182.5, # wanning immunity
623
-
624
- get_params=FALSE) {
625
- # set following parameters to be the same for both groups unless specified otherwise
626
-
627
- if(!is.na(mu)){
628
- mu_a<-mu
629
- mu_b<-mu
630
- mu_c<-mu
631
- }
632
-
633
- if(!is.na(zeta)){
634
- zeta_a<-zeta
635
- zeta_b<-zeta
636
- zeta_c<-zeta
637
- }
638
-
639
- if(!is.na(pi)){
640
- pi_a<-pi
641
- pi_b<-pi
642
- pi_c<-pi
643
- }
644
-
645
- if(!is.na(phi)){
646
- phi_a<-phi
647
- phi_b<-phi
648
- phi_c<-phi
649
- }
650
-
651
-
652
- if(!is.na(vacc)){
653
- vacc_a<-vacc
654
- vacc_b<-vacc
655
- vacc_c<-vacc
656
- }
657
-
658
- if(!is.na(cmin)){
659
- cmin_a<-cmin
660
- cmin_b<-cmin
661
- cmin_c<-cmin
662
- }
663
-
664
-
665
- if(!is.na(cmax)){
666
- cmax_a<-cmax
667
- cmax_b<-cmax
668
- cmax_c<-cmax
669
- }
670
-
671
- N0_a = N0 * frac_a
672
- N0_b = N0 * frac_b
673
- N0_c = N0 * (1 - frac_a - frac_b)
674
-
675
-
676
-
677
- params<-c(‘trans_p’ = trans_p, # probability of transmission given contact
678
- ‘beta_a’= beta_a, # homophily parameter for group a (beta_a = 1 means unbiased mixing; beta_a > 1 means homophily)
679
- ‘beta_b’= beta_b, # homophily parameter for group b (beta_b = 1 means unbiased mixing; beta_b > 1 means homophily)
680
- #’h_a’= h_a, # # proportion of group A's total contact with members of their own group (bounded by population size and total contacts in group B)
681
- #’h_b’= h_b, # # proportion of group A's total contact with members of their own group (bounded by population size and total contacts in group B)
682
- ‘cmax_a’ = cmax_a, ‘cmax_b’ = cmax_b, ‘cmax_c’ = cmax_c, # upper and lower bounds for contacts
683
- ‘zeta_a’ = zeta_a, ‘zeta_b’ = zeta_b, ‘zeta_c’ = zeta_c, # responsiveness of contact to deaths
684
- ‘pi_a’ = pi_a, ‘pi_b’ = pi_b, ‘pi_c’ = pi_c, # background rate of adopting protective behavior
685
- ‘kappa’ = kappa, # scaling factor for probability of transmission given contact resulting from protective behavior; kappa=1 means no protection, kappa = 0 means perfect protection
686
- ‘phi_a’=phi_a, ‘phi_b’ = phi_b, ‘phi_c’ = phi_c, # waning rate of protective behavior
687
- ‘rho’=rho, # 1 / infectious period
688
- ‘mu_a’=mu_a, ‘mu_b’ = mu_b, ‘mu_c’ = mu_c, # probability of dying following infection
689
- ‘time’=time, # time steps in simulation
690
- ‘I0_a’=I0_a, ‘I0_b’=I0_b, ‘I0_c’=I0_c, # starting number infected in each group
691
- ‘N0_a’ = N0_a, ‘N0_b’= N0_b, ‘N0_c’=N0_c, # population size in each group at time zero
692
- ‘ell’=ell, # time window for considering deaths that influence adoption of protective behavior
693
- ‘vacc_a’=vacc_a, ‘vacc_b’=vacc_b, ‘vacc_c’=vacc_c, # vaccination rate
694
- ‘vstart’ = vstart, # start of vaccination
695
- ‘gamma’ = gamma #waning immunity
696
- ) # responsiveness to proportion of protected individuals for adopting protective behavior
697
-
698
- state<-c(
699
-
700
- #group a
701
- ca <- cmax_a,
702
- SUa<-(N0_a - I0_a),
703
- SPa<-0,
704
- IUa<-I0_a,
705
- IPa<-0,
706
- RUa<-0,
707
- RPa<-0,
708
- DUa<-0,
709
- DPa<-0,
710
-
711
- #group b
712
- cb <- cmax_b,
713
- SUb<-N0_b - I0_b,
714
- SPb<-0,
715
- IUb<-I0_b,
716
- IPb<-0,
717
- RUb<-0,
718
- RPb<-0,
719
- DUb<-0,
720
- DPb<-0,
721
-
722
- #group c
723
- cc <- cmax_c,
724
- SUc<-N0_c - I0_c,
725
- SPc<-0,
726
- IUc<-I0_c,
727
- IPc<-0,
728
- RUc<-0,
729
- RPc<-0,
730
- DUc<-0,
731
- DPc<-0
732
- )
733
-
734
- names(state)<- c(‘ca’,’SUa’, ‘SPa’, ‘IUa’, ‘IPa’, ‘RUa’, ‘RPa’, ‘DUa’, ‘DPa’,
735
- ‘cb’,’SUb’, ‘SPb’, ‘IUb’, ‘IPb’, ‘RUb’, ‘RPb’, ‘DUb’, ‘DPb’,
736
- ‘cc’,’SUc’, ‘SPc’, ‘IUc’, ‘IPc’, ‘RUc’, ‘RPc’, ‘DUc’, ‘DPc’)
737
-
738
- sir_up<-function(t, state, parameter){
739
-
740
- with(as.list(c(parameter, state)), {
741
-
742
-
743
- if(t<ell){
744
- lag_ell<-rep(0, length(state))
745
- }
746
- else{
747
- lag_ell<-lagvalue(t-ell) #provide access to past (lagged) values of all state variables; below we make sure we only look at D
748
- }
749
-
750
-
751
- if(t<vstart){
752
- vacc_a <- 0
753
- vacc_b <- 0
754
- vacc_c <- 0
755
- }
756
- else{
757
- vacc_a <- vacc_a
758
- vacc_b <- vacc_b
759
- vacc_c <- vacc_c
760
- }
761
-
762
- # for the transitions there are seven processes that are currently modeled:
763
- # 1: transmission process (infection, recovery/death)
764
- # 2: changes in contact rate for group A in response to deaths
765
- # 3: adoption of protective behavior
766
- # 5: waning of protective behavior
767
- # 6: vaccination
768
- # 7: waning of immunity
769
-
770
-
771
-
772
- # recalculate population size (will change due to deaths)
773
- N_a = SUa + IUa + RUa + SPa + IPa + RPa
774
- N_b = SUb + IUb + RUb + SPb + IPb + RPb
775
- N_c = SUc + IUc + RUc + SPc + IPc + RPc
776
-
777
-
778
-
779
- # contact matrix
780
- c_mat <- avg_contact_matrix_3gp(dbar_a = ca,
781
- dbar_b = cb,
782
- dbar_c = cc,
783
- N_a = N_a,
784
- N_b = N_b,
785
- N_c = N_c,
786
- beta_a = beta_a,
787
- beta_b = beta_b)
788
- #h_a = h_a,
789
- #h_b = h_b)
790
-
791
- ## TODO - should we throw an error if any implied contacts are negative?
792
-
793
-
794
- ################################
795
- ## transitions for group a
796
- ################################
797
-
798
- # Force of infection
799
- lambda_a = trans_p*(c_mat[1,1]*(IUa/N_a + kappa*IPa/N_a) + c_mat[1,2]*(IUb/N_b + kappa*IPb/N_b) + c_mat[1,3]*(IUc/N_c + kappa*IPc/N_c))
800
-
801
-
802
- # change in contacts in response to deaths occuring over a time window defined by ell (constrained to maximum/minimum observed values)
803
-
804
- deaths_t <- rho*mu_a*IUa + rho*mu_a*IPa + rho*mu_b*IUb + rho*mu_b*IPb + rho*mu_c*IUc + rho*mu_c*IPc
805
-
806
-
807
- deaths_tminusell <- rho*mu_a*(lag_ell[which(names(state) == ‘IUa’)]) +
808
- rho*mu_a*(lag_ell[which(names(state) == ‘IPa’)]) +
809
- rho*mu_b*(lag_ell[which(names(state) == ‘IUb’)]) +
810
- rho*mu_b*(lag_ell[which(names(state) == ‘IPb’)]) +
811
- rho*mu_c*(lag_ell[which(names(state) == ‘IUc’)]) +
812
- rho*mu_c*(lag_ell[which(names(state) == ‘IPc’)])
813
-
814
- cum_deaths_ell <- DUa - lag_ell[which(names(state) == ‘DUa’)] +
815
- DPa - lag_ell[which(names(state) == ‘DPa’)] +
816
- DUb - lag_ell[which(names(state) == ‘DUb’)] +
817
- DPb - lag_ell[which(names(state) == ‘DPb’)] +
818
- DUc - lag_ell[which(names(state) == ‘DUc’)] +
819
- DPc - lag_ell[which(names(state) == ‘DPc’)]
820
-
821
- dca <- (-zeta_a)*(cmax_a - cmin_a)*(deaths_t - deaths_tminusell)*exp(-zeta_a*(cum_deaths_ell))
822
-
823
- dSUa <- -SUa*lambda_a - #transmission process
824
- pi_a * SUa + # adoption of protective behavior
825
- phi_a * SPa + #waning of protective behavior
826
- gamma * RUa - #waning immunity
827
- vacc_a * SUa
828
-
829
- dSPa <- -SPa*kappa*lambda_a +
830
- pi_a * SUa -
831
- phi_a * SPa +
832
- gamma * RPa -
833
- vacc_a * SPa
834
-
835
- dIUa <- SUa*lambda_a -
836
- pi_a*IUa +
837
- phi_a * IPa -
838
- (rho) * IUa
839
-
840
- dIPa <- SPa*kappa*lambda_a +
841
- pi_a * IUa -
842
- phi_a * IPa -
843
- (rho) * IPa
844
-
845
- dRUa <- rho * (1-mu_a) * IUa -
846
- pi_a * RUa +
847
- phi_a * RPa -
848
- gamma * RUa +
849
- vacc_a * SUa
850
-
851
- dRPa <- rho * (1-mu_a) * IPa +
852
- pi_a * RUa -
853
- phi_a * RPa -
854
- gamma * RPa +
855
- vacc_a * SPa
856
-
857
- dDUa <- rho*mu_a*IUa
858
-
859
- dDPa <- rho*mu_a*IPa
860
-
861
-
862
- ################################
863
- ## transitions for group b
864
- ################################
865
-
866
- # Force of infection
867
- lambda_b = trans_p*(c_mat[2,1]*(IUa/N_a + kappa*IPa/N_a) + c_mat[2,2]*(IUb/N_b + kappa*IPb/N_b) + c_mat[2,3]*(IUc/N_c + kappa*IPc/N_c) )
868
-
869
-
870
- # change in contacts in response to deaths (constrained to maximum/minimum observed values)
871
- dcb <- (-zeta_b)*(cmax_b - cmin_b)*(deaths_t - deaths_tminusell)*exp(-zeta_b*(cum_deaths_ell))
872
-
873
-
874
- dSUb <- -SUb*lambda_b -
875
- pi_b * SUb +
876
- phi_b * SPb +
877
- gamma * RUb -
878
- vacc_b * SUb
879
-
880
- dSPb <- -SPb*kappa*lambda_b +
881
- pi_b * SUb -
882
- phi_b * SPb +
883
- gamma * RPb -
884
- vacc_b * SPb
885
-
886
- dIUb <- SUb*lambda_b -
887
- pi_b * IUb +
888
- phi_b * IPb -
889
- (rho) * IUb
890
-
891
- dIPb <- SPb*kappa*lambda_b +
892
- pi_b * IUb -
893
- phi_b * IPb -
894
- (rho) * IPb
895
-
896
- dRUb <- (1-mu_b) * rho * IUb -
897
- pi_b * RUb +
898
- phi_b * RPb -
899
- gamma * RUb +
900
- vacc_b * SUb
901
-
902
- dRPb <- (1-mu_b) * rho * IPb +
903
- pi_b * RUb -
904
- phi_b * RPb -
905
- gamma * RPb +
906
- vacc_b * SPb
907
-
908
- dDUb <- rho*mu_b*IUb
909
-
910
- dDPb <- rho*mu_b*IPb
911
-
912
-
913
- ################################
914
- ## transitions for group c
915
- ################################
916
-
917
- # Force of infection
918
- lambda_c = trans_p*(c_mat[3,1]*(IUa/N_a + kappa*IPa/N_a) + c_mat[3,2]*(IUb/N_b + kappa*IPb/N_b) + c_mat[3,3]*(IUc/N_c + kappa*IPc/N_c) )
919
-
920
-
921
- # change in contacts in response to deaths (constrained to maximum/minimum observed values)
922
- dcc <- (-zeta_c)*(cmax_c - cmin_c)*(deaths_t - deaths_tminusell)*exp(-zeta_c*(cum_deaths_ell))
923
-
924
-
925
- dSUc <- -SUc*lambda_c -
926
- pi_c * SUc +
927
- phi_c * SPc +
928
- gamma * RUc -
929
- vacc_c * SUc
930
-
931
- dSPc <- -SPc*kappa*lambda_c +
932
- pi_c * SUc -
933
- phi_c * SPc +
934
- gamma * RPc -
935
- vacc_c * SPc
936
-
937
- dIUc <- SUc*lambda_c -
938
- pi_c * IUc +
939
- phi_c * IPc -
940
- (rho) * IUc
941
-
942
- dIPc <- SPc*kappa*lambda_c +
943
- pi_c * IUc -
944
- phi_c * IPc -
945
- (rho) * IPc
946
-
947
- dRUc <- (1-mu_c) * rho * IUc -
948
- pi_c * RUc +
949
- phi_c * RPc -
950
- gamma * RUc +
951
- vacc_c * SUc
952
-
953
- dRPc <- (1-mu_c) * rho * IPc +
954
- pi_c * RUc -
955
- phi_c * RPc -
956
- gamma * RPc +
957
- vacc_c * SPc
958
-
959
- dDUc <- rho*mu_c*IUc
960
-
961
- dDPc <- rho*mu_c*IPc
962
-
963
-
964
-
965
-
966
- return(list(c(dca, dSUa, dSPa, dIUa, dIPa, dRUa, dRPa, dDUa, dDPa,
967
- dcb, dSUb, dSPb, dIUb, dIPb, dRUb, dRPb, dDUb, dDPb,
968
- dcc, dSUc, dSPc, dIUc, dIPc, dRUc, dRPc, dDUc, dDPc
969
- )))
970
- })
971
- }
972
-
973
- times<-seq(from=0, to=time, by=1)
974
-
975
- as.data.frame(dede(state, times, sir_up, params))->sim
976
-
977
- if(get_params){
978
- return(list(sim=sim, params=params))
979
- }
980
-
981
- else{
982
- return(sim)
983
- }
984
-
985
-
986
-
987
- }
988
- "
989
-
990
- function_in_string <- gsub("\\s+", " ", function_in_string)
991
- function_in_string <- trimws(function_in_string)
 
530
 
531
  }
532
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.R CHANGED
@@ -713,8 +713,41 @@ Chenoweth, M., Li, M., Gomez-Lopez, I. N., & Kollman, K. (2020). <i>National Nei
713
  )
714
  })
715
 
716
- # Set OPENAI_API_KEY environment variable before running the app
717
- # Sys.setenv(OPENAI_API_KEY = "your-api-key-here")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
718
  chat_history <- reactiveVal("")
719
 
720
  # Build context string for chat based on current user view
@@ -772,7 +805,7 @@ Chenoweth, M., Li, M., Gomez-Lopez, I. N., & Kollman, K. (2020). <i>National Nei
772
  body = toJSON(list(
773
  model = "Qwen/Qwen3-VL-235B-A22B-Instruct:novita",
774
  messages = list(
775
- list(role = "system", content = function_in_string),
776
  list(role = "user", content = message_with_context)
777
  ),
778
  max_tokens = 500,
 
713
  )
714
  })
715
 
716
+ # System prompt for chat assistant
717
+ chat_system_prompt <- "You are an expert assistant for the Partisan Epidemic Simulator, a Shiny app that models how partisan differences in health behaviors affect epidemic outcomes.
718
+
719
+ ## About the Model
720
+ This is a three-party SIR (Susceptible-Infected-Recovered) model that simulates disease spread among Republicans, Democrats, and Independents. The model incorporates:
721
+
722
+ - **Contact rates**: Different average daily contacts for each political group (Republicans typically have higher contact rates based on BICS survey data)
723
+ - **Protective behavior**: Rates of adopting protective measures like masking (Democrats adopt faster, Republicans slower)
724
+ - **Responsiveness to deaths (zeta)**: How groups adjust contact behavior based on mortality (Republicans show more responsiveness)
725
+ - **Vaccination rates**: Differential uptake across groups (Democrats ~74%, Independents ~61%, Republicans ~57%)
726
+ - **Contact homophily (beta)**: Tendency to interact with similar political affiliations (beta=1 means random mixing, higher values mean more within-group contact)
727
+ - **Mortality rates**: Age-adjusted death rates by party
728
+
729
+ ## Key Parameters
730
+ - **cmax**: Maximum daily contacts per group
731
+ - **pi**: Rate of adopting protective behavior
732
+ - **phi**: Rate of abandoning protective behavior (waning)
733
+ - **zeta**: Responsiveness of contact reduction to deaths
734
+ - **beta**: Homophily parameter (contact preference for own group)
735
+ - **kappa**: Protective behavior effectiveness (1=no protection, 0=perfect)
736
+ - **vacc**: Daily vaccination rate per group
737
+
738
+ ## Model Scenarios
739
+ - **Homogenous**: No partisan differences (baseline for comparison)
740
+ - **Partisan Behavior**: Full model with partisan heterogeneity
741
+ - **Manual**: User-controlled parameters
742
+
743
+ ## Interpreting Results
744
+ - Higher prevalence peaks indicate worse outbreaks
745
+ - Earlier peaks suggest faster spread
746
+ - Differences between party lines show disparate disease burden
747
+ - 'Excess deaths' compares partisan model to homogenous baseline
748
+
749
+ Be concise, helpful, and reference the specific metrics the user is viewing when answering questions."
750
+
751
  chat_history <- reactiveVal("")
752
 
753
  # Build context string for chat based on current user view
 
805
  body = toJSON(list(
806
  model = "Qwen/Qwen3-VL-235B-A22B-Instruct:novita",
807
  messages = list(
808
+ list(role = "system", content = chat_system_prompt),
809
  list(role = "user", content = message_with_context)
810
  ),
811
  max_tokens = 500,