11import Anthropic from "@anthropic-ai/sdk" ;
22import { convertXML } from "simple-xml-to-json" ;
33import fs from "fs/promises" ;
4- import { parse } from ' csv-parse/sync' ;
5- import { create } from ' xmlbuilder2' ;
4+ import { parse } from " csv-parse/sync" ;
5+ import { create } from " xmlbuilder2" ;
66
77const js2xmlparser = require ( "js2xmlparser" ) ;
8- const report_id = process . argv [ 2 ]
8+ const report_id = process . argv [ 2 ] ;
99
1010interface PolisRecord {
11- [ key : string ] : string ; // Allow any string keys
11+ [ key : string ] : string ; // Allow any string keys
1212}
1313
1414export class PolisConverter {
1515 static convertToXml ( csvContent : string ) : string {
1616 // Parse CSV content
1717 const records = parse ( csvContent , {
1818 columns : true ,
19- skip_empty_lines : true
19+ skip_empty_lines : true ,
2020 } ) as PolisRecord [ ] ;
2121
22- if ( records . length === 0 ) return '' ;
22+ if ( records . length === 0 ) return "" ;
2323
2424 // Create XML document
25- const doc = create ( { version : '1.0' , encoding : 'UTF-8' } )
26- . ele ( 'polis-comments' ) ;
25+ const doc = create ( { version : "1.0" , encoding : "UTF-8" } ) . ele (
26+ "polis-comments"
27+ ) ;
2728
2829 // Process each record
29- records . forEach ( record => {
30+ records . forEach ( ( record ) => {
3031 // Extract base comment data
31- const comment = doc . ele ( ' comment' , {
32- id : record [ ' comment-id' ] ,
33- votes : record [ ' total-votes' ] ,
34- agrees : record [ ' total-agrees' ] ,
35- disagrees : record [ ' total-disagrees' ] ,
36- passes : record [ ' total-passes' ]
32+ const comment = doc . ele ( " comment" , {
33+ id : record [ " comment-id" ] ,
34+ votes : record [ " total-votes" ] ,
35+ agrees : record [ " total-agrees" ] ,
36+ disagrees : record [ " total-disagrees" ] ,
37+ passes : record [ " total-passes" ] ,
3738 } ) ;
3839
3940 // Add comment text
40- comment . ele ( ' text' ) . txt ( record [ ' comment' ] ) ;
41+ comment . ele ( " text" ) . txt ( record [ " comment" ] ) ;
4142
4243 // Find and process all group data
4344 const groupKeys = Object . keys ( record )
44- . filter ( key => key . match ( / ^ g r o u p - [ a - z ] - / ) )
45+ . filter ( ( key ) => key . match ( / ^ g r o u p - [ a - z ] - / ) )
4546 . reduce ( ( groups , key ) => {
46- const groupId = key . split ( '-' ) [ 1 ] ; // Extract 'a' from 'group-a-votes'
47+ const groupId = key . split ( "-" ) [ 1 ] ; // Extract 'a' from 'group-a-votes'
4748 if ( ! groups . includes ( groupId ) ) groups . push ( groupId ) ;
4849 return groups ;
4950 } , [ ] as string [ ] ) ;
5051
5152 // Add data for each group
52- groupKeys . forEach ( groupId => {
53+ groupKeys . forEach ( ( groupId ) => {
5354 comment . ele ( `group-${ groupId } ` , {
5455 votes : record [ `group-${ groupId } -votes` ] ,
5556 agrees : record [ `group-${ groupId } -agrees` ] ,
5657 disagrees : record [ `group-${ groupId } -disagrees` ] ,
57- passes : record [ `group-${ groupId } -passes` ]
58+ passes : record [ `group-${ groupId } -passes` ] ,
5859 } ) ;
5960 } ) ;
6061 } ) ;
@@ -64,29 +65,29 @@ export class PolisConverter {
6465 }
6566
6667 static async convertFromFile ( filePath : string ) : Promise < string > {
67- const fs = await import ( ' fs/promises' ) ;
68- const csvContent = await fs . readFile ( filePath , ' utf-8' ) ;
68+ const fs = await import ( " fs/promises" ) ;
69+ const csvContent = await fs . readFile ( filePath , " utf-8" ) ;
6970 return PolisConverter . convertToXml ( csvContent ) ;
7071 }
7172
7273 // Helper method to validate CSV structure
7374 static validateCsvStructure ( headers : string [ ] ) : boolean {
7475 const requiredBaseFields = [
75- ' comment-id' ,
76- ' comment' ,
77- ' total-votes' ,
78- ' total-agrees' ,
79- ' total-disagrees' ,
80- ' total-passes'
76+ " comment-id" ,
77+ " comment" ,
78+ " total-votes" ,
79+ " total-agrees" ,
80+ " total-disagrees" ,
81+ " total-passes" ,
8182 ] ;
8283
83- const hasRequiredFields = requiredBaseFields . every ( field =>
84+ const hasRequiredFields = requiredBaseFields . every ( ( field ) =>
8485 headers . includes ( field )
8586 ) ;
8687
8788 // Check if group fields follow the expected pattern
88- const groupFields = headers . filter ( h => h . startsWith ( ' group-' ) ) ;
89- const validGroupPattern = groupFields . every ( field =>
89+ const groupFields = headers . filter ( ( h ) => h . startsWith ( " group-" ) ) ;
90+ const validGroupPattern = groupFields . every ( ( field ) =>
9091 field . match ( / ^ g r o u p - [ a - z ] - (?: v o t e s | a g r e e s | d i s a g r e e s | p a s s e s ) $ / )
9192 ) ;
9293
@@ -98,30 +99,41 @@ const anthropic = new Anthropic({
9899 // defaults to process.env["ANTHROPIC_API_KEY"]
99100} ) ;
100101
101-
102102const getJSONuserMsg = async ( ) => {
103- const report_xml_template = await fs . readFile ( "src/prompts/report_experimental/subtasks/uncertainty.xml" , "utf8" ) ; // unsure if this should be uncertainty or group_informed_consensus
103+ const report_xml_template = await fs . readFile (
104+ "src/prompts/report_experimental/subtasks/uncertainty.xml" ,
105+ "utf8"
106+ ) ; // unsure if this should be uncertainty or group_informed_consensus
104107 const asJSON = await convertXML ( report_xml_template ) ;
105108 return asJSON ;
106- }
109+ } ;
107110
108111const getCommentsAsJson = async ( id : string ) => {
109- const resp = await fetch ( `http://localhost/api/v3/reportExport/${ id } /comment-groups.csv` ) ; // this should be rewritten to call internal api or db, not depending on localhost
112+ const resp = await fetch (
113+ `http://localhost/api/v3/reportExport/${ id } /comment-groups.csv`
114+ ) ; // this should be rewritten to call internal api or db, not depending on localhost
110115 const data = await resp . text ( ) ;
111- const xml = PolisConverter . convertToXml ( data )
116+ const xml = PolisConverter . convertToXml ( data ) ;
112117 return xml ;
113- }
114-
118+ } ;
115119
116120async function main ( ) {
117- const system_lore = await fs . readFile ( "src/prompts/report_experimental/system.xml" , "utf8" ) ;
121+ const system_lore = await fs . readFile (
122+ "src/prompts/report_experimental/system.xml" ,
123+ "utf8"
124+ ) ;
118125 const json = await getJSONuserMsg ( ) ;
119126 const structured_comments = await getCommentsAsJson ( report_id ) ;
120- json . polisAnalysisPrompt . children [ json . polisAnalysisPrompt . children . length - 1 ] . data . content = { structured_comments } ; // insert dynamic report stuff here
121- const prompt_xml = js2xmlparser . parse ( "polis-comments-and-group-demographics" , json ) ; // then convert back to xml
122- console . log ( prompt_xml )
127+ json . polisAnalysisPrompt . children [
128+ json . polisAnalysisPrompt . children . length - 1
129+ ] . data . content = { structured_comments } ; // insert dynamic report stuff here
130+ const prompt_xml = js2xmlparser . parse (
131+ "polis-comments-and-group-demographics" ,
132+ json
133+ ) ; // then convert back to xml
134+ console . log ( prompt_xml ) ;
123135 const msg = await anthropic . messages . create ( {
124- model : "claude-3-5 -sonnet-20241022 " ,
136+ model : "claude-3-7 -sonnet-20250219 " ,
125137 max_tokens : 1000 ,
126138 temperature : 0 ,
127139 system : system_lore ,
@@ -131,8 +143,7 @@ async function main() {
131143 content : [
132144 {
133145 type : "text" ,
134- text :
135- prompt_xml ,
146+ text : prompt_xml ,
136147 } ,
137148 ] ,
138149 } ,
0 commit comments