Skip to content

Commit

Permalink
Merge pull request #120 from samchon/feat/length
Browse files Browse the repository at this point in the history
`IHttpLlmFunction.name`'s maximum length limit.
  • Loading branch information
samchon authored Jan 9, 2025
2 parents ba85b68 + b71d16e commit abbb1e9
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 4 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@samchon/openapi",
"version": "2.3.2",
"version": "2.3.3",
"description": "OpenAPI definitions and converters for 'typia' and 'nestia'.",
"main": "./lib/index.js",
"module": "./lib/index.mjs",
Expand Down
3 changes: 2 additions & 1 deletion src/HttpLlm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ export namespace HttpLlm {
options: {
...LlmSchemaComposer.defaultConfig(props.model),
separate: props.options?.separate ?? null,
},
maxLength: props.options?.maxLength ?? null,
} as any as IHttpLlmApplication.IOptions<Model>,
});
};

Expand Down
52 changes: 51 additions & 1 deletion src/composers/HttpLlmApplicationComposer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,15 @@ export namespace HttpLlmComposer {
return func;
})
.filter((v): v is IHttpLlmFunction<Model> => v !== null);
return {

const app: IHttpLlmApplication<Model> = {
model: props.model,
options: props.options,
functions,
errors,
};
shorten(app, props.options?.maxLength ?? 64);
return app;
};

const composeFunction = <Model extends ILlmSchema.Model>(props: {
Expand Down Expand Up @@ -230,10 +233,57 @@ export namespace HttpLlmComposer {
operation: () => props.route.operation(),
};
};

export const shorten = <Model extends ILlmSchema.Model>(
app: IHttpLlmApplication<Model>,
limit: number = 64,
): void => {
const dictionary: Set<string> = new Set();
const longFunctions: IHttpLlmFunction<Model>[] = [];
for (const func of app.functions) {
dictionary.add(func.name);
if (func.name.length > limit) {
longFunctions.push(func);
}
}
if (longFunctions.length === 0) return;

let index: number = 0;
for (const func of longFunctions) {
let success: boolean = false;
let rename = (str: string) => {
dictionary.delete(func.name);
dictionary.add(str);
func.name = str;
success = true;
};
for (let i: number = 1; i < func.route().accessor.length; ++i) {
const shortName: string = func.route().accessor.slice(i).join("_");
if (shortName.length > limit - 8) continue;
else if (dictionary.has(shortName) === false) rename(shortName);
else {
const newName: string = `_${index}_${shortName}`;
if (dictionary.has(newName) === true) continue;
rename(newName);
++index;
}
break;
}
if (success === false) rename(randomFormatUuid());
}
};
}

const randomFormatUuid = (): string =>
"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0;
const v = c === "x" ? r : (r & 0x3) | 0x8;
return v.toString(16);
});

const emend = (str: string): string => {
for (const ch of FORBIDDEN) str = str.split(ch).join("_");
return str;
};

const FORBIDDEN = ["$", "%", "."];
18 changes: 17 additions & 1 deletion src/structures/IHttpLlmApplication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,23 @@ export interface IHttpLlmApplication<Model extends ILlmSchema.Model> {
options: IHttpLlmApplication.IOptions<Model>;
}
export namespace IHttpLlmApplication {
export import IOptions = ILlmApplication.IOptions;
/**
* Options for the HTTP LLM application schema composition.
*/
export type IOptions<Model extends ILlmSchema.Model> =
ILlmApplication.IOptions<Model> & {
/**
* Maximum length of function name.
*
* When a function name is longer than this value, it will be truncated.
*
* If not possible to truncate due to the duplication, the function name
* would be modified to randomly generated (UUID v4).
*
* @default 64
*/
maxLength?: number;
};

/**
* Error occurred in the composition.
Expand Down
2 changes: 2 additions & 0 deletions src/structures/IHttpLlmFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ export interface IHttpLlmFunction<Model extends ILlmSchema.Model> {
* > - Example 2
* > - endpoint: `GET /shoppings/sellers/sales/:saleId/reviews/:reviewId/comments/:id
* > - accessor: `shoppings.sellers.sales.reviews.getBySaleIdAndReviewIdAndCommentId`
*
* @maxLength 64
*/
name: string;

Expand Down
2 changes: 2 additions & 0 deletions src/structures/ILlmFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import { ILlmSchema } from "./ILlmSchema";
export interface ILlmFunction<Model extends ILlmSchema.Model> {
/**
* Representative name of the function.
*
* @maxLength 64
*/
name: string;

Expand Down
25 changes: 25 additions & 0 deletions test/features/llm/test_http_llm_application_funtion_name_length.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { TestValidator } from "@nestia/e2e";
import { HttpLlm, IHttpLlmApplication, OpenApi } from "@samchon/openapi";

export const test_http_llm_application_funtion_name_length =
async (): Promise<void> => {
const document: OpenApi.IDocument = OpenApi.convert(
await fetch(
"https://wrtnio.github.io/connectors/swagger/swagger.json",
).then((res) => res.json()),
);
const application: IHttpLlmApplication<"chatgpt"> = HttpLlm.application({
model: "chatgpt",
document,
});

TestValidator.predicate("overflow")(() =>
application.functions.some(
(f) => f.route().accessor.join("_").length > 64,
),
);

const names: string[] = application.functions.map((f) => f.name);
TestValidator.predicate("length")(() => names.every((s) => s.length <= 64));
TestValidator.equals("unique")(true)(new Set(names).size === names.length);
};

0 comments on commit abbb1e9

Please sign in to comment.