Not able to feed custom fine tune on Open AI

The Open AI response is taken from default model, if we point to custom model response is not given as expected

Please post your API code and the full error message returned from the API.

Then, we can help you :+1:

$complete = $open_ai->completion([
** ‘model’ => ‘davinci:ft-personal:infy7latest-2023-02-08-05-24-19’, //custom model name**
** ‘prompt’ => $prompt,**
** ‘temperature’ => 0.7,**
** ‘max_tokens’ => 256,**
** ‘top_p’ => 1,**
** ‘frequency_penalty’ => 0,**
** ‘presence_penalty’ => 0,**
** ‘stream’ => true**
], function($curl_info, $data){
** echo $data;**
** echo PHP_EOL;**
** ob_flush();**
** flush();**
** return strlen($data);**
});

on that custom model, I uploaded some json lines format prompt and completion. If human enter any one of prompt in input, need to fetch data from my custom feed.

Thanks

I don’t use PHP for the OpenAI API.

However, the API does return an full JSON message from the API, even when it fails.

Please post that entire response in it’s entirety.

Thanks

I’m not getting any error response.

data.jsonl
{“prompt”:“Item=handbag, Color=army_green, price=$99, size=S->”, “completion”:" This stylish small green handbag will add a unique touch to your look, without costing you a fortune."}

Text: I want item of handbag and color as army green
Response of my chat:
data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “\n”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “\n”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “The”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Patricia", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Nash", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Ar", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “no”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Leather", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Cross", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “body”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Bag", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " in", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Army", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Green", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " is", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " a", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " great", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " choice", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “.”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " This", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " stylish", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " bag", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " features", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " a", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " top", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " zip", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " closure", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “,”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " a", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " removable", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “,”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " adjustable", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " cross", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “body”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " strap", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “,”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " an", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " interior", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " zip", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " pocket", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “,”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " and", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " an", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " exterior", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " front", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " slip", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " pocket", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “.”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " It", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " is", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " crafted", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " from", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " fine", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " Italian", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " leather", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " and", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " is", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " available", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " in", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " a", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " beautiful", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " army", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " green", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: " hue", “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “.”, “index”: 0, “logprobs”: null, “finish_reason”: null}], “model”: “text-davinci-003”} data: {“id”: “cmpl-6ht5GQcXhhIcHKPflKQYvHegxMhjR”, “object”: “text_completion”, “created”: 1675917866, “choices”: [{“text”: “”, “index”: 0, “logprobs”: null, “finish_reason”: “stop”}], “model”: “text-davinci-003”} data: [DONE]

So, maybe I misunderstood you, @madhangopal500 (have been multitasking two IT coding projects and sanding teak wood floors as well)

You then, are not getting any errors, the issue is that your custom model does not perform as you expect?

Is that right?

@ruby_coder Yes, correct.

OK. Got it.

Please post back the first two lines of your JSONL fine-tuning file you used to fine-tune.

If possible, it would be good if you could wrap your data samples (here in the forum) with Markdown triple back ticks so your data and code is more easy to read.

```
Your data or code here.
```
{"prompt":"Item=handbag, Color=army_green, price=$99, size=S->", "completion":" This stylish small green handbag will add a unique touch to your look, without costing you a fortune."}

Text from Human: I want item of handbag and color as army green.

Expected Response is
This stylish small green handbag will add a unique touch to your look, without costing you a fortune.

$complete = $open_ai->completion([
    'model' => 'davinci:ft-personal:infy7latest-2023-02-08-05-24-19',//custom model name
    'prompt' => $prompt,
    'temperature' => 0.7,
    'max_tokens' => 256,
	'top_p' => 1,
    'frequency_penalty' => 0,
    'presence_penalty' => 0,
    'stream' => true
], function($curl_info, $data){
    echo $data;
    echo PHP_EOL;
    ob_flush();
    flush();
    return strlen($data);
});

Yes, this JSON line entry (above) does not meet the OpenAI fine-tuning guidelines.

It seems almost everyone here skips reading this part of the docs, not only you @madhangopal500 :slight_smile:

1 Like

Entire json line format has taken from Open AI documentation. I’ll re-check all JSON line.

Thanks for your help :slightly_smiling_face:

Yes, that line is early in the document. That’s the problem with beta documentation. You are in the huge majority who stops at that example in the docs and missed the details posted above.

I have a working JSONL and OpenAI API fine-tuning validator and ran your JSONL line, and it passes (obviously) JSONL but fails the OpenAI “fine-tuning format” validator:

Could you share me any valid format which is accepted by Open AI?
That would be helpful for me.

I think something like this might work for you (not tested):

{"prompt":"Item=handbag, Color=army_green, price=$99, size=S-> MY_SEPARATOR", "completion":" This stylish small green handbag will add a unique touch to your look, without costing you a fortune. STOP_STOP"}

You must:

  • Add a separator at the end of your prompt
  • Add a stop at the end of your completion
  • Have a white space at the beginning of your completion.

You must uses your separator and your stop when you query your fine-tuned model.

I think it is pretty clear from the directions below. Just follow the directions :slight_smile:

1 Like

The issue is that you expect to feed the API one of your prompts and are expecting it to find the matching completion.

Unfortunately, it doesn’t work like that.

The fine-tuning changes the bias and establishes patterns for completions. It won’t work as a lookup table.

I also read that it doesn’t like lists of parameters. It prefers things in sentences.

Eg.

“An army green small handbag priced at $99”

will perform much better than

“Item=handbag, Color=army_green, price=$99, size=S”

But even with that change, it is not an exact science.

Essentially, you have to overwhelm the AI with patterns that it can follow. They could be lookup lists, but you will not get the matching completion for a given prompt. You would have to feed lots of examples for it to start to produce something similar.

1 Like

Hi @madhangopal500

@raymonddavey is 100% correct so even when you get all the formatting, separators and stops right, there are the challenges which @raymonddavey mentioned on top of all that.

Personally, I would not use fine-tuning for your application as you have shared; but since you only provided one example line of your JSONL file, I assumed you have many hundreds of training lines. Your choice of tech is different than mine, but you learn by experimenting!

So, go for it as you please. Experts are made my making a lot of mistakes or going down paths which lead to the wrong results; and finally “getting it right”.

How many lines is your JSONL training file, BTW?

@ruby_coder as of now I’m doing R&D so testing with two to three lines of JSON line. I’ll consider @raymonddavey points and work on it.

I’ll keep posted :+1:

You won’t get a fair indication of if it is going to work with only 2 or 3 lines.

You need at least 100. But if you can’t do that, try 20 rows and increase n_epochs

n_epochs tell GPT to process the file multiple times. This reinforces learning.

2 Likes

Yeah, that’s the fun part. Enjoy and report back with results, good and bad.

Hey @madhangopal500

FYI, in case you miss the docs on this, the n_epochs parma defaults to 4. See:

See:

Fine-Tune: Create

I think making sure you have your SEPARATOR and STOP set correctly in the training data and then using these these same strings in your prompts after tuning should help a lot, as the docs instruct.

1 Like

I just tested your JSONL line @madhangopal500 against my validator for both JSONL and the API, as well:

Validated OK and got a ID no problem at all.

I’m still working on adding more params to the fine-tune method, and may move the validator out completely as a separate function, add a second column for API valid?, etc… It’s still a WIP.

HTH