A first-call walkthrough: Jev scores a closed skill list, Java applies a cutoff, and LangChain4j writes the note only from skills that passed.
I keep shipping the same resume mistake. A chat model receives the text and a prompt that says "extract skills as JSON." A chat model is the kind of model that writes: ChatGPT, Claude, and the models behind them. The parser gets a list. Kafka shows up because the candidate wrote "events." Python shows up because a bullet says "familiar with scripting." The list looks structured. It is still a guess wearing braces. That request is two jobs. One job is a decision: does this resume support each skill we hire for? The other is a sentence a recruiter can read. I want Jev on the first and LangChain4j on the second. If you have not used either one, the whole path is four steps. You already have the skill names, because they are on the job. Jev gives each name a probability. Your Java code keeps the names above a number you chose. LangChain4j, a Java library that calls a chat model for you, writes a short note that may mention only the names you kept. That request is two jobs. One of them should not be a language model. Words, before the API I will use these words as if they were obvious. They are not. Here is what each one means in this article. Word What it means here Catalog The skill list already stored on the job. Java, Spring Boot, Kafka. You wrote it. The resume does not get to invent new rows. Jev A model from TypeSafe that answers questions. It returns numbers and labels. It does not write a paragraph. Noul Jev's yes-or-no answer. A probability from 0 to 1. 0.95 means "very likely yes." 0.10 means "very likely no." 0.50 means it cannot tell. Choice Pick one option from a list you supply, such as junior, mid, senior, or staff. Score Place the resume on a scale you wrote, from vague to specific. The number only means something next to that scale. Cutoff Your rule, in ordinary Java. In the sample, 0.80 or higher counts as "keep this skill." TypeSafe does not ship that number. LangChain4j A Java library for calling chat models. You declare an interface. The library sends the prompt and returns the text. What JEV does Jev is TypeSafe's System One model. The job, in one sentence: you hand it a document and a list of questions, and it answers every question with a typed field you can branch on. It does not write the recruiter note. It does not invent a skill that was not in the list. If you wanted a paragraph, you called the wrong model. I keep meeting the same confusion. People hear "model" and reach for a chat box. Jev has no chat box. The public how-to is a single POST. You send three things. The model name. jev-latest while you are still rewriting the questions. A pinned version, such as jev-1.13.0 , once a cutoff depends on the answers staying put. The response tells you which version actually ran. jev-latest can come back as a specific build. The state. The thing being judged. A string, a JSON object, or an array of text chunks. For this article the state is the resume. Not the job description, and not a prompt that says "be helpful." The questions. A map. Each entry has a name you chose ( spring_boot , seniority ), a type, and instructions. Every question in the map is scored against that same state, in one HTTP call. You do not pay a round trip per skill. Three types. I use all three on a resume, and they are not interchangeable. A noul is a yes or no with no option list. The instructions are the whole question. "The resume shows production experience with Spring Boot." What comes back is one number, noul , from 0 to 1. Near 1, the state supports the question. Near 0, it does not. Around 0.5, the model cannot tell. There is no hidden essay behind that number. Your Java code decides what "high enough" means. TypeSafe does not ship a hiring cutoff. A choice is a closed label. You send a JSON object: up to 255 keys, each key with a short description of what that option means. Seniority is a choice. Junior, mid, senior, staff. Jev returns the winning key, a probability for every option, and a confidence . The how-to's advice, and I agree with it, is to trust the confident cases and hand the shaky ones to a person. A seniority call at low confidence should not auto-reject anyone. A score is a position on a scale you wrote. The criteria is a JSON array of 2 to 10 descriptions, weakest first. "Skills are named with no setting" through "production scope, duration, or an outcome." The number can be fractional. It only means something next to that array. The response includes a legend that maps positions back to your wording, plus a probability distribution. Rewrite the levels and yesterday's 2.0 is a different fact. Here is the shape TypeSafe documents, from their billing example. These numbers are theirs, for a support ticket, not a score I measured on a resume. I am showing the fields. { "model": "jev-1.13.0", "answers": { "topic": { "type": "choice", "choice": "billing", "confidence": 1.0, "probabilities": { "billing": 1.0, "bug": 0.0, "account": 0.0 } }, "severity": { "type": "score", "score": 3.0, "confidence": 1.0, "legend": { "0": "routine", "3": "critical, about to churn" }, "probabilities": { "0": 0.0, "3": 1.0 } }, "escalate": { "type": "noul", "noul": 0.8 } }, "usage": { "input_tokens": 434, "output_tokens": 75 } } Read it as a form, not as a story. answers is keyed by the names you sent. escalate is a noul, so you read noul . topic is a choice, so you read choice and ignore the idea of a free-text topic. severity is a score, so you read score and check legend before you tell anyone what 3 means. usage is tokens in and tokens out. That is the whole payload. On a resume the same envelope comes back with our names. spring_boot is a noul. seniority is a choice. evidence is a score. I am not filling in live probabilities here. One call is not a calibration set, and I do not want a unit test married to 0.91. A few limits from that same how-to, so you do not discover them in production. State plus every question together is about 64k tokens. State plus the single longest question is about 32k. They publish 250,000 tokens per second and 1,200 requests per minute. I have not load-tested those numbers. Batch the catalog into one request. The questions run together and share the cost of reading the resume. And the part people skip: a probability is not evidence you can paste into a client email. It tells you which question fired. The sentence that supports it still has to be in the resume. If it is not, drop the skill. Jev did not create a quote. What you actually get back Talking to Jev is closer to filling in a form than to chatting. You send the resume, which Jev calls the state: just the text you want judged. You send the questions. You get answers. There is no paragraph to scrape for "the real skill." When you are ready to call it, the request is one HTTP POST. The URL is https://api.typesafe.ai/v1/systemone . The header is Authorization: Bearer plus an API key you keep in the environment variable TYPESAFE_API_KEY . Do not paste that key into source code. The public how-to is the contract: a choice can have up to 255 options, and the resume plus the questions together are about 64k tokens. A token is a chunk of text the model counts. You do not need to count them to try the sample below. All the questions go in that one request. Adding Spring Boot and Kafka does not mean two round trips. While you are still editing the wording, the model name jev-latest is fine. Once you trust a cutoff, pin a version, the same way you pin a library version. If the model moves and your 0.80 stays put, yesterday's "keep" can become today's "drop" with no code change. TypeSafe's number, repeated in LangChain's 17 September 2026 post , is up to 200x faster and 400x cheaper than comparable chat models on classification. That is their figure. I have not timed it on our hiring API. There is no LangChain4j plugin that speaks Jev, as I write this. LangChain's Python side...