diff --git a/dingo/model/llm/llm_keyword_matcher.py b/dingo/model/llm/llm_keyword_matcher.py index 440e58fb..d3948c12 100644 --- a/dingo/model/llm/llm_keyword_matcher.py +++ b/dingo/model/llm/llm_keyword_matcher.py @@ -9,19 +9,12 @@ from typing import List from dingo.io import Data +from dingo.io.output.eval_detail import EvalDetail, QualityLabel from dingo.model import Model from dingo.model.llm.base_openai import BaseOpenAI from dingo.utils import log from dingo.utils.exception import ConvertJsonError -# Import EvalDetail for dev branch compatibility, fallback to ModelRes for main branch -try: - from dingo.io.output.eval_detail import EvalDetail, QualityLabel - USE_EVAL_DETAIL = True -except ImportError: - from dingo.model.modelres import ModelRes - USE_EVAL_DETAIL = False - # Complete synonym mapping for keyword normalization SYNONYM_MAP = { "k8s": "Kubernetes", @@ -185,7 +178,7 @@ def _build_prompt(jd_text: str, resume_text: str) -> str: @classmethod def process_response(cls, response: str): - """Process LLM response. Returns EvalDetail (dev) or ModelRes (main).""" + """Process LLM response. Returns EvalDetail.""" log.info(f"Raw LLM response: {response}") # Extract think content and clean response @@ -213,29 +206,16 @@ def process_response(cls, response: str): log.info(f"Keyword match score: {score:.1%}, threshold: {cls.threshold:.0%}") - # Return appropriate result type based on branch - if USE_EVAL_DETAIL: - result = EvalDetail(metric=cls.__name__) - result.score = score - result.reason = [reason] - if score >= cls.threshold: - result.status = False - result.label = [QualityLabel.QUALITY_GOOD] - else: - result.status = True - result.label = [f"QUALITY_BAD.{cls.__name__}"] + # Return EvalDetail result + result = EvalDetail(metric=cls.__name__) + result.score = score + result.reason = [reason] + if score >= cls.threshold: + result.status = False + result.label = [QualityLabel.QUALITY_GOOD] else: - result = ModelRes() - result.score = score - result.reason = [reason] - if score >= cls.threshold: - result.error_status = False - result.type = "KEYWORD_MATCH_GOOD" - result.name = "MATCH_GOOD" - else: - result.error_status = True - result.type = "KEYWORD_MATCH_LOW" - result.name = "MATCH_LOW" + result.status = True + result.label = [f"QUALITY_BAD.{cls.__name__}"] return result @@ -346,38 +326,22 @@ def _generate_reason(cls, jd_analysis: dict, keyword_analysis: List[dict], score @classmethod def eval(cls, input_data: Data): - """Override eval to validate inputs. Returns EvalDetail (dev) or ModelRes (main).""" + """Override eval to validate inputs. Returns EvalDetail.""" # Validate that content (resume) is provided if not input_data.content: - if USE_EVAL_DETAIL: - result = EvalDetail(metric=cls.__name__) - result.status = True - result.label = [f"QUALITY_BAD.{cls.__name__}"] - result.reason = ["Resume text (content) is required but was not provided"] - return result - else: - return ModelRes( - error_status=True, - type="KEYWORD_MATCH_ERROR", - name="MISSING_RESUME", - reason=["Resume text (content) is required but was not provided"] - ) + result = EvalDetail(metric=cls.__name__) + result.status = True + result.label = [f"QUALITY_BAD.{cls.__name__}"] + result.reason = ["Resume text (content) is required but was not provided"] + return result # Validate that prompt (JD) is provided if not input_data.prompt: - if USE_EVAL_DETAIL: - result = EvalDetail(metric=cls.__name__) - result.status = True - result.label = [f"QUALITY_BAD.{cls.__name__}"] - result.reason = ["Job description (prompt) is required but was not provided"] - return result - else: - return ModelRes( - error_status=True, - type="KEYWORD_MATCH_ERROR", - name="MISSING_JD", - reason=["Job description (prompt) is required but was not provided"] - ) + result = EvalDetail(metric=cls.__name__) + result.status = True + result.label = [f"QUALITY_BAD.{cls.__name__}"] + result.reason = ["Job description (prompt) is required but was not provided"] + return result # Call parent eval method return super().eval(input_data) diff --git a/dingo/model/llm/llm_resume_optimizer.py b/dingo/model/llm/llm_resume_optimizer.py index 5bc243f8..85794ee4 100644 --- a/dingo/model/llm/llm_resume_optimizer.py +++ b/dingo/model/llm/llm_resume_optimizer.py @@ -9,19 +9,12 @@ from typing import List, Tuple from dingo.io import Data +from dingo.io.output.eval_detail import EvalDetail, QualityLabel from dingo.model import Model from dingo.model.llm.base_openai import BaseOpenAI from dingo.utils import log from dingo.utils.exception import ConvertJsonError -# Import EvalDetail for dev branch compatibility, fallback to ModelRes for main branch -try: - from dingo.io.output.eval_detail import EvalDetail, QualityLabel - USE_EVAL_DETAIL = True -except ImportError: - from dingo.model.modelres import ModelRes - USE_EVAL_DETAIL = False - @Model.llm_register("LLMResumeOptimizer") class LLMResumeOptimizer(BaseOpenAI): @@ -191,7 +184,7 @@ def _parse_match_report(cls, match_report) -> Tuple[List[str], List[str], List[s @classmethod def process_response(cls, response: str): - """Process LLM response. Returns EvalDetail (dev) or ModelRes (main).""" + """Process LLM response. Returns EvalDetail.""" log.info(f"Raw LLM response length: {len(response)} chars") # Clean response @@ -210,22 +203,13 @@ def process_response(cls, response: str): # Generate reason text reason = cls._generate_reason(optimization_summary, section_changes, overall_improvement) - # Return appropriate result type based on branch - if USE_EVAL_DETAIL: - result = EvalDetail(metric=cls.__name__) - result.status = False - result.label = [QualityLabel.QUALITY_GOOD] - result.reason = [reason] - # Store full response for downstream use (using extra field) - result.optimized_content = response_json - else: - result = ModelRes() - result.error_status = False - result.type = "RESUME_OPTIMIZED" - result.name = "OPTIMIZATION_COMPLETE" - result.reason = [reason] - # Store full response for downstream use - result.optimized_content = response_json + # Return EvalDetail result + result = EvalDetail(metric=cls.__name__) + result.status = False + result.label = [QualityLabel.QUALITY_GOOD] + result.reason = [reason] + # Store full response for downstream use (using extra field) + result.optimized_content = response_json return result @@ -287,22 +271,14 @@ def _generate_reason(cls, summary: dict, changes: List[dict], overall: str) -> s @classmethod def eval(cls, input_data: Data): - """Override eval to validate inputs. Returns EvalDetail (dev) or ModelRes (main).""" + """Override eval to validate inputs. Returns EvalDetail.""" # Validate that content (resume) is provided if not input_data.content: - if USE_EVAL_DETAIL: - result = EvalDetail(metric=cls.__name__) - result.status = True - result.label = [f"QUALITY_BAD.{cls.__name__}"] - result.reason = ["Resume text (content) is required but was not provided"] - return result - else: - return ModelRes( - error_status=True, - type="RESUME_OPTIMIZER_ERROR", - name="MISSING_RESUME", - reason=["Resume text (content) is required but was not provided"] - ) + result = EvalDetail(metric=cls.__name__) + result.status = True + result.label = [f"QUALITY_BAD.{cls.__name__}"] + result.reason = ["Resume text (content) is required but was not provided"] + return result # Call parent eval method return super().eval(input_data)