@@ -17,6 +17,14 @@ import { evaluateWithLangChain } from "./evaluate-lc";
1717
1818const log = getLogger ( "llm:userdefined" ) ;
1919
20+ const REDACTED_VALUE = "[redacted]" ;
21+ const SENSITIVE_KEYS = new Set ( [
22+ "apiKey" ,
23+ "openAIApiKey" ,
24+ "azureOpenAIApiKey" ,
25+ "api_key" ,
26+ ] ) ;
27+
2028interface UserDefinedOpts {
2129 input : string ; // new input that user types
2230 system ?: string ; // extra setup that we add for relevance and context
@@ -30,7 +38,7 @@ export async function evaluateUserDefinedLLM(
3038 opts : Readonly < UserDefinedOpts > ,
3139 account_id ?: string ,
3240) {
33- log . debug ( `evaluateUserDefinedLLM[${ account_id } ]` , opts ) ;
41+ log . debug ( `evaluateUserDefinedLLM[${ account_id } ]` , redactSensitive ( opts ) ) ;
3442
3543 const { user_defined_llm } = await getServerSettings ( ) ;
3644 if ( ! user_defined_llm ) {
@@ -48,7 +56,7 @@ export async function evaluateUserDefinedLLM(
4856 }
4957
5058 const conf = await getConfig ( account_id , um . service , um . model ) ;
51- log . debug ( "conf" , conf ) ;
59+ log . debug ( "conf" , redactSensitive ( conf ) ) ;
5260 if ( conf == null ) {
5361 throw new Error ( `Unable to retrieve user defined model ${ model } ` ) ;
5462 }
@@ -61,6 +69,8 @@ export async function evaluateUserDefinedLLM(
6169 return await evaluateOllama ( {
6270 ...opts ,
6371 model : toOllamaModel ( conf . model ) ,
72+ endpoint,
73+ maxTokens : conf . max_tokens ,
6474 } ) ;
6575 }
6676 case "openai" :
@@ -76,6 +86,7 @@ export async function evaluateUserDefinedLLM(
7686 apiKey,
7787 endpoint : endpoint || undefined , // don't pass along empty strings!
7888 service,
89+ maxTokens : conf . max_tokens , // Use max_tokens from config
7990 } ,
8091 "user" ,
8192 ) ;
@@ -106,8 +117,58 @@ async function getConfig(
106117 }
107118 }
108119 } catch ( err ) {
109- log . error ( "Failed to parse user defined llm" , user_llm_json , err ) ;
120+ log . error (
121+ "Failed to parse user defined llm" ,
122+ redactUserLLMJson ( user_llm_json ) ,
123+ err ,
124+ ) ;
110125 throw err ;
111126 }
112127 return null ;
113128}
129+
130+ function redactSensitive ( value : any ) : any {
131+ if ( value == null ) {
132+ return value ;
133+ }
134+ if ( typeof value === "function" ) {
135+ return value ;
136+ }
137+ if ( typeof value !== "object" ) {
138+ return value ;
139+ }
140+ if ( Array . isArray ( value ) ) {
141+ return value . map ( ( item ) => redactSensitive ( item ) ) ;
142+ }
143+ if ( value instanceof Date ) {
144+ return value ;
145+ }
146+ const output : Record < string , any > = { } ;
147+ for ( const [ key , val ] of Object . entries ( value ) ) {
148+ output [ key ] = SENSITIVE_KEYS . has ( key )
149+ ? REDACTED_VALUE
150+ : redactSensitive ( val ) ;
151+ }
152+ return output ;
153+ }
154+
155+ function redactUserLLMJson ( value : unknown ) : unknown {
156+ if ( typeof value !== "string" ) {
157+ return value ;
158+ }
159+ try {
160+ const parsed = JSON . parse ( value ) ;
161+ return JSON . stringify ( redactSensitive ( parsed ) ) ;
162+ } catch ( _err ) {
163+ return redactSensitiveString ( value ) ;
164+ }
165+ }
166+
167+ function redactSensitiveString ( value : string ) : string {
168+ let redacted = value ;
169+ for ( const key of SENSITIVE_KEYS ) {
170+ const regex = new RegExp ( `("${ key } "\\s*:\\s*")([^"]*)(")` , "g" ) ;
171+ redacted = redacted . replace ( regex , `$1${ REDACTED_VALUE } $3` ) ;
172+ }
173+ return redacted ;
174+ }
0 commit comments