Structured output when calling GPT4o from Foundry Functions?

I want to have a json returned from a specific call I’m making to an LLM from a Foundry function.

Is it possible to get structured output like the GPT-API allows through AIP ?

What is the syntax required to have a structured output to be provided as a result of my call ?

From: https://www.palantir.com/docs/foundry/functions/language-models/

Is something like possible ?

const gptResponse = await GPT_4o.createChatCompletion({messages: [systemMessage, userMessage], params: { temperature: 0.7 }, structured:true});

Hey @VincentF, it’s possible currently to return a struct type from AIP Logic which you can destructure in a Workshop application or elsewhere.

See the FAQ in the Logic docs for this:
https://www.palantir.com/docs/foundry/logic/faq/

Make sense, then I would need to wrap the “structured output” call in an AIP Logic backed function, and then call it from FoO.

I’m still wondering if there is a direct way to enforce this from Function on object without AIP Logic ?

Hi @VincentF, if you would like to enforce a json format from ChatGPT response in code repositories for example, you can provide an additional argument to your CompletionRequest “response_format”.

For Python Transforms, GptChatWithVisionCompletionRequest supports response format, and the Json enum is “JSON_OBJECT”. Please find an example code snippet below.

# NOTE: Libraries must be manually imported through "Libraries" in the left-hand panel
from transforms.api import transform, Output
from palantir_models.transforms import OpenAiGptChatWithVisionLanguageModelInput
from palantir_models.models import OpenAiGptChatWithVisionLanguageModel
from language_model_service_api.languagemodelservice_api_completion_v3 import (
    GptChatWithVisionCompletionRequest,
    GptChatCompletionResponse
)
from language_model_service_api.languagemodelservice_api import (
    ChatMessageRole,
    ChatMessageContent,
    MultiContentChatMessage,
)
from pyspark.sql import functions as F
from pyspark.sql import types as T

MOCK = [
    (1, "Great product, highly recommend!", 5),
    (2, "Not bad, but could be better.", 3),
    (3, "Terrible experience, will not buy again.", 1),
    (4, "Okay product for the price.", 3),
    (5, "Loved it, exactly what I needed!", 5)
]

@transform(
    model=OpenAiGptChatWithVisionLanguageModelInput("ri.language-model-service..language-model.gpt-4-o"),
    output=Output(""),
)
def compute_sentiment(ctx, model: OpenAiGptChatWithVisionLanguageModel, output):

    def get_llm_response(prompt):
        request: GptChatWithVisionCompletionRequest = GptChatWithVisionCompletionRequest(
                    [
                        MultiContentChatMessage(
                            contents=[
                                ChatMessageContent(text="Take the following review determine the sentiment of the review. Respond in json format {'llm_response': response to user question, 'certainty': how certain you are the response is accurate}"),
                                    ],
                            role=ChatMessageRole.SYSTEM,
                        ),
                        MultiContentChatMessage(
                            contents=[
                                ChatMessageContent(text=prompt),
                                    ],
                            role=ChatMessageRole.USER,
                        )
                    ],
                    max_tokens=200, temperature=0.8, response_format={"type": "JSON_OBJECT"})
        response: GptChatCompletionResponse = model.create_chat_completion(request)
        return response.choices[0].message.content

    reviews_df = ctx.spark_session.createDataFrame(MOCK, schema=["review_id", "review_text", "rating"])

    get_llm_response_udf = F.udf(get_llm_response, T.StringType())

    # Define schema for JSON output
    json_schema = T.StructType([
        T.StructField("llm_response", T.StringType(), True),
        T.StructField("certainty", T.StringType(), True)
    ])

    output_df = reviews_df.withColumn('llm_response', get_llm_response_udf(F.col('review_text')))
    output_df = output_df.withColumn("json_parsed", F.from_json(F.col("llm_response"), json_schema))
    output_df = output_df.select(
        F.col("review_id"),
        F.col("review_text"),
        F.col("json_parsed.llm_response").alias("llm_response_json"),
        F.col("json_parsed.certainty").alias("certainty")
    )

    return output.write_dataframe(output_df)

Similarly, if you would like to enforce Json format in TS Functions you can similarly pass a responseFormat: {type: “json_object”} to createChatCompletion. Example code below:

import { Function } from "@foundry/functions-api"
// NOTE: Model Imports must be manually added through "Resource Imports" in the left-hand panel
import { GPT_4o } from "@foundry/models-api/language-models"
export class MyFunctions {
    @Function()
    public async createChatCompletion(userInput: string): Promise<string | undefined> {
        const response = await GPT_4o.createChatCompletion({
            params: {
                "temperature": 0,
                "maxTokens": 1000,
                responseFormat: {type: "json_object"}
            },
            messages: [{role:"SYSTEM", contents:[{text: "Provide response in json format specifying the answer and how certain you are of the response"}]},{ role: "USER", contents: [{ text: userInput }] }],
        });
        return response.choices[0].message.content;
    }
}

Hello,

This seem to show how to use JSON mode but not really structured output , see the difference here :
https://platform.openai.com/docs/guides/structured-outputs#structured-outputs-vs-json-mode

In structured output, you can actually pass the actual expected JSON schema.
It also uses another, chat completion method.(see here the node.js)

import OpenAI from "openai";
import { zodResponseFormat } from "openai/helpers/zod";
import { z } from "zod";

const openai = new OpenAI();

const CalendarEvent = z.object({
  name: z.string(),
  date: z.string(),
  participants: z.array(z.string()),
});

const completion = await openai.beta.chat.completions.parse({
  model: "gpt-4o-2024-08-06",
  messages: [
    { role: "system", content: "Extract the event information." },
    { role: "user", content: "Alice and Bob are going to a science fair on Friday." },
  ],
  response_format: zodResponseFormat(CalendarEvent, "event"),
});

const event = completion.choices[0].message.parsed;
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.