ML-Learner / python_backend /src /Agents /nodes /resume_builder.py
VashuTheGreat2's picture
Upload folder using huggingface_hub
c01955c verified
from src.Agents.models.Resume_model import ResumeState,ResumeSchema
import logging
from src.Agents.llm.llm_loader import llm
from src.Agents.prompts import resumeGeneration_prompts as ResumeGenerationPrompt
from utils.asyncHandler import asyncHandler
from langsmith import traceable
@asyncHandler
@traceable(name="resume_builder",tags=['summary_generator'])
async def resume_maker(state: ResumeState):
logging.info("Entering resume_maker node")
logging.info(f"userDetails for LLM: {state.userDetails}")
prompt_template = ResumeGenerationPrompt
# Connect prompt to structured output with include_raw=True
llm_with_schema = prompt_template | llm.with_structured_output(ResumeSchema, include_raw=True)
# Invoke LLM
logging.info("Invoking LLM for resume generation")
full_result = await llm_with_schema.ainvoke({"userDetails": state.userDetails})
result = full_result.get("parsed")
raw_output = full_result.get("raw")
logging.info(f"LLM parsed result: {result}")
# Fallback parsing logic if the LLM returned text instead of a formal tool call
if result is None and raw_output and hasattr(raw_output, 'content'):
logging.info("Attempting fallback parsing for LLM content")
content = raw_output.content
if isinstance(content, list):
content = " ".join([c.get('text', '') if isinstance(c, dict) else str(c) for c in content])
try:
import json
import re
# Try to extract JSON from the text
# It might be a direct JSON or inside a "parameters" block of a pseudo-tool-call
json_match = re.search(r'\{.*\}', content, re.DOTALL)
if json_match:
json_str = json_match.group(0)
data = json.loads(json_str)
# If it looks like a tool call wrapper (e.g., {"type": "function", "parameters": {...}})
if "parameters" in data:
data = data["parameters"]
# Clean up "null" strings that should be actual None
def clean_nulls(d):
if isinstance(d, dict):
return {k: clean_nulls(v) for k, v in d.items()}
elif isinstance(d, list):
return [clean_nulls(v) for v in d]
elif d == "null":
return None
return d
data = clean_nulls(data)
result = ResumeSchema(**data)
logging.info("Successfully extracted ResumeSchema via fallback parser")
except Exception as parse_err:
logging.error(f"Fallback parsing failed: {str(parse_err)}")
if result is None:
logging.error(f"LLM raw output (could not be parsed): {raw_output}")
# Update state - return a dict of updates
logging.info("Exiting resume_maker node")
return {"ai_generated_schema": result}