diff --git a/backend/api/src/llm-extract-profile.ts b/backend/api/src/llm-extract-profile.ts index ae23c64c..bde3f0be 100644 --- a/backend/api/src/llm-extract-profile.ts +++ b/backend/api/src/llm-extract-profile.ts @@ -18,6 +18,7 @@ import { import {debug} from 'common/logger' import {ProfileWithoutUser} from 'common/profiles/profile' import {SITE_ORDER} from 'common/socials' +import {removeNullOrUndefinedProps} from 'common/util/object' import {parseJsonContentToText} from 'common/util/parse' import {createHash} from 'crypto' import {promises as fs} from 'fs' @@ -249,7 +250,7 @@ TASK: Extract structured profile data and return it as a single valid JSON objec RULES: - Only extract information that is EXPLICITLY stated — do not infer, guess, or hallucinate -- Return null for missing fields +- Omit the key in the output for missing fields - For taxonomy fields (interests, causes, work): match existing labels first; only add a new label if truly no existing one is close - For big5 scores: only populate if the person explicitly states a test result — never infer from personality description - Return valid JSON only — no markdown, no explanation, no extra text @@ -282,7 +283,8 @@ TEXT TO ANALYZE: let parsed: Partial try { - parsed = JSON.parse(outputText) + parsed = typeof outputText === 'string' ? JSON.parse(outputText) : outputText + parsed = removeNullOrUndefinedProps(parsed) } catch (parseError) { log('Failed to parse LLM response as JSON', {outputText, parseError}) throw APIErrors.internalServerError('Failed to parse extracted data') diff --git a/web/components/optional-profile-form.tsx b/web/components/optional-profile-form.tsx index 283030cc..eae0c194 100644 --- a/web/components/optional-profile-form.tsx +++ b/web/components/optional-profile-form.tsx @@ -18,6 +18,7 @@ import {isUrl} from 'common/parsing' import {MultipleChoiceOptions} from 'common/profiles/multiple-choice' import {Profile, ProfileWithoutUser} from 'common/profiles/profile' import {BaseUser} from 'common/user' +import {removeNullOrUndefinedProps} from 'common/util/object' import {urlize} from 'common/util/string' import {invert, range} from 'lodash' import {useRef, useState} from 'react' @@ -95,7 +96,7 @@ export const OptionalProfileUserForm = (props: { const payload = isInputUrl ? {url: urlize(llmContent).trim()} : {content: llmContent.trim()} const extracted = await api('llm-extract-profile', payload) - for (const data of Object.entries(extracted)) { + for (const data of Object.entries(removeNullOrUndefinedProps(extracted))) { const key = data[0] let value = data[1] let choices, setChoices: any