@@ -321,7 +321,7 @@ def get_activation_config() -> dict[str, Any]:
321321
322322 @staticmethod
323323 def get_memreader_config () -> dict [str , Any ]:
324- """Get MemReader configuration."""
324+ """Get MemReader configuration for chat/doc extraction (fine-tuned 0.6B model) ."""
325325 return {
326326 "backend" : "openai" ,
327327 "config" : {
@@ -338,6 +338,107 @@ def get_memreader_config() -> dict[str, Any]:
338338 },
339339 }
340340
341+ @staticmethod
342+ def get_memreader_general_llm_config () -> dict [str , Any ]:
343+ """Get general LLM configuration for non-chat/doc tasks.
344+
345+ Used for: hallucination filter, memory rewrite, memory merge,
346+ tool trajectory extraction, skill memory extraction.
347+
348+ This is the fallback for image_parser_llm and preference_extractor_llm.
349+ Fallback chain: MEMREADER_GENERAL_MODEL -> MEMRADER_MODEL (memreader config)
350+
351+ Note: If you have fine-tuned a custom model for chat/doc extraction only,
352+ you should configure MEMREADER_GENERAL_MODEL to use a general-purpose LLM
353+ for other tasks. Otherwise, all tasks will use the same MEMRADER_MODEL.
354+ """
355+ # Check if specific general model is configured
356+ general_model = os .getenv ("MEMREADER_GENERAL_MODEL" )
357+ if general_model :
358+ return {
359+ "backend" : os .getenv ("MEMREADER_GENERAL_BACKEND" , "openai" ),
360+ "config" : {
361+ "model_name_or_path" : general_model ,
362+ "temperature" : 0.6 ,
363+ "max_tokens" : int (os .getenv ("MEMREADER_GENERAL_MAX_TOKENS" , "8000" )),
364+ "top_p" : 0.95 ,
365+ "top_k" : 20 ,
366+ "api_key" : os .getenv (
367+ "MEMREADER_GENERAL_API_KEY" , os .getenv ("OPENAI_API_KEY" , "EMPTY" )
368+ ),
369+ "api_base" : os .getenv (
370+ "MEMREADER_GENERAL_API_BASE" ,
371+ os .getenv ("OPENAI_API_BASE" , "https://api.openai.com/v1" ),
372+ ),
373+ "remove_think_prefix" : True ,
374+ },
375+ }
376+ # Fallback to memreader config (same behavior as before for users who don't customize)
377+ return APIConfig .get_memreader_config ()
378+
379+ @staticmethod
380+ def get_image_parser_llm_config () -> dict [str , Any ]:
381+ """Get LLM configuration for image parsing (requires vision model).
382+
383+ Used for: image content extraction and analysis.
384+ Requires a vision-capable model like GPT-4V, GPT-4o, etc.
385+
386+ Fallback chain: IMAGE_PARSER_MODEL -> general_llm -> OpenAI config
387+ """
388+ image_model = os .getenv ("IMAGE_PARSER_MODEL" )
389+ if image_model :
390+ return {
391+ "backend" : os .getenv ("IMAGE_PARSER_BACKEND" , "openai" ),
392+ "config" : {
393+ "model_name_or_path" : image_model ,
394+ "temperature" : 0.6 ,
395+ "max_tokens" : int (os .getenv ("IMAGE_PARSER_MAX_TOKENS" , "4096" )),
396+ "top_p" : 0.95 ,
397+ "top_k" : 20 ,
398+ "api_key" : os .getenv (
399+ "IMAGE_PARSER_API_KEY" , os .getenv ("OPENAI_API_KEY" , "EMPTY" )
400+ ),
401+ "api_base" : os .getenv (
402+ "IMAGE_PARSER_API_BASE" ,
403+ os .getenv ("OPENAI_API_BASE" , "https://api.openai.com/v1" ),
404+ ),
405+ "remove_think_prefix" : True ,
406+ },
407+ }
408+ # Fallback to general_llm config (which itself falls back to OpenAI)
409+ return APIConfig .get_memreader_general_llm_config ()
410+
411+ @staticmethod
412+ def get_preference_extractor_llm_config () -> dict [str , Any ]:
413+ """Get LLM configuration for preference extraction.
414+
415+ Used for: extracting user preferences from conversations.
416+
417+ Fallback chain: PREFERENCE_EXTRACTOR_MODEL -> general_llm -> OpenAI config
418+ """
419+ pref_model = os .getenv ("PREFERENCE_EXTRACTOR_MODEL" )
420+ if pref_model :
421+ return {
422+ "backend" : os .getenv ("PREFERENCE_EXTRACTOR_BACKEND" , "openai" ),
423+ "config" : {
424+ "model_name_or_path" : pref_model ,
425+ "temperature" : 0.6 ,
426+ "max_tokens" : int (os .getenv ("PREFERENCE_EXTRACTOR_MAX_TOKENS" , "8000" )),
427+ "top_p" : 0.95 ,
428+ "top_k" : 20 ,
429+ "api_key" : os .getenv (
430+ "PREFERENCE_EXTRACTOR_API_KEY" , os .getenv ("OPENAI_API_KEY" , "EMPTY" )
431+ ),
432+ "api_base" : os .getenv (
433+ "PREFERENCE_EXTRACTOR_API_BASE" ,
434+ os .getenv ("OPENAI_API_BASE" , "https://api.openai.com/v1" ),
435+ ),
436+ "remove_think_prefix" : True ,
437+ },
438+ }
439+ # Fallback to general_llm config (which itself falls back to OpenAI)
440+ return APIConfig .get_memreader_general_llm_config ()
441+
341442 @staticmethod
342443 def get_activation_vllm_config () -> dict [str , Any ]:
343444 """Get Ollama configuration."""
@@ -358,7 +459,7 @@ def get_preference_memory_config() -> dict[str, Any]:
358459 return {
359460 "backend" : "pref_text" ,
360461 "config" : {
361- "extractor_llm" : APIConfig .get_memreader_config (),
462+ "extractor_llm" : APIConfig .get_preference_extractor_llm_config (),
362463 "vector_db" : {
363464 "backend" : "milvus" ,
364465 "config" : APIConfig .get_milvus_config (),
@@ -802,6 +903,10 @@ def get_product_default_config() -> dict[str, Any]:
802903 "backend" : reader_config ["backend" ],
803904 "config" : {
804905 "llm" : APIConfig .get_memreader_config (),
906+ # General LLM for non-chat/doc tasks (hallucination filter, rewrite, merge, etc.)
907+ "general_llm" : APIConfig .get_memreader_general_llm_config (),
908+ # Image parser LLM (requires vision model)
909+ "image_parser_llm" : APIConfig .get_image_parser_llm_config (),
805910 "embedder" : APIConfig .get_embedder_config (),
806911 "chunker" : {
807912 "backend" : "sentence" ,
@@ -924,6 +1029,10 @@ def create_user_config(user_name: str, user_id: str) -> tuple["MOSConfig", "Gene
9241029 "backend" : reader_config ["backend" ],
9251030 "config" : {
9261031 "llm" : APIConfig .get_memreader_config (),
1032+ # General LLM for non-chat/doc tasks (hallucination filter, rewrite, merge, etc.)
1033+ "general_llm" : APIConfig .get_memreader_general_llm_config (),
1034+ # Image parser LLM (requires vision model)
1035+ "image_parser_llm" : APIConfig .get_image_parser_llm_config (),
9271036 "embedder" : APIConfig .get_embedder_config (),
9281037 "chunker" : {
9291038 "backend" : "sentence" ,
0 commit comments