Skip to content

Commit 951ebc1

Browse files
committed
Experiment #140: DeepSeek Function Calling Test
1 parent 3135ef0 commit 951ebc1

16 files changed

+1232
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
{
2+
"section_code": "general",
3+
"status": null,
4+
"opened_at": null,
5+
"closed_at": null,
6+
"content": {
7+
"title": "Surface Pro 9",
8+
"format": "md",
9+
"body": "> The Surface Pro 9 is a versatile 2-in-1 device that combines the power of a laptop with the flexibility of a tablet. It features advanced technology, making it suitable for both professional and personal use.\n> - \"Unleash Your Creativity Anywhere\": The Surface Pro 9 is designed for those who need power and portability, making it perfect for creative professionals and students alike.\n> - \"The Ultimate 2-in-1 Experience\": With its detachable keyboard and touchscreen capabilities, the Surface Pro 9 adapts to your needs, whether you're working, studying, or relaxing.\n> - \"Stay Connected with 5G\": Experience lightning-fast internet speeds and seamless connectivity, no matter where you are.\n> - \"Power Meets Flexibility\": The Surface Pro 9 combines the performance of a laptop with the convenience of a tablet, making it the ideal device for multitasking.\n> \n> In summary, the Surface Pro 9 stands out as a powerful and flexible device, perfect for users who require both performance and portability. With its advanced features and sleek design, it is an excellent choice for anyone looking to enhance their productivity and creativity. Whether for work or play, the Surface Pro 9 is ready to meet your needs.",
10+
"files": [],
11+
"thumbnails": [
12+
{
13+
"name": "microsoft-surface-pro-9-thumbnail-1",
14+
"extension": "jpeg",
15+
"url": "https://serpapi.com/searches/673d3a37e45f3316ecd8ab3e/images/1be25e6e2b1fb7509f1af89c326cb41749301b94375eb5680b9bddcdf88fabcb.jpeg"
16+
},
17+
{
18+
"name": "microsoft-surface-pro-9-thumbnail-2",
19+
"extension": "jpeg",
20+
"url": "https://serpapi.com/searches/673d3a37e45f3316ecd8ab3e/images/1be25e6e2b1fb750d6c1bc749467f5aba0340886f4f4943fe72302c5e658b15a.jpeg"
21+
},
22+
{
23+
"name": "microsoft-surface-pro-9-thumbnail-3",
24+
"extension": "jpeg",
25+
"url": "https://serpapi.com/searches/673d3a37e45f3316ecd8ab3e/images/1be25e6e2b1fb7505946d975aac683f8826bcb8c509672de4a5f8c71f149fdef.jpeg"
26+
}
27+
]
28+
},
29+
"channels": [
30+
{
31+
"code": "samchon",
32+
"category_codes": [
33+
"electronics",
34+
"laptops",
35+
"2in1_laptops"
36+
]
37+
}
38+
],
39+
"units": [
40+
{
41+
"options": [
42+
{
43+
"type": "select",
44+
"name": "CPU",
45+
"variable": true,
46+
"candidates": [
47+
{
48+
"name": "Intel Core i3"
49+
},
50+
{
51+
"name": "Intel Core i5"
52+
},
53+
{
54+
"name": "Intel Core i7"
55+
}
56+
]
57+
}
58+
],
59+
"stocks": [
60+
{
61+
"name": "Surface Pro 9 Entity",
62+
"price": {
63+
"nominal": 1000000,
64+
"real": 899000
65+
},
66+
"quantity": 1000,
67+
"choices": [
68+
{
69+
"option_index": 0,
70+
"candidate_index": 0
71+
}
72+
]
73+
}
74+
],
75+
"name": "Surface Pro 9 Entity",
76+
"required": true,
77+
"primary": true
78+
},
79+
{
80+
"options": [],
81+
"stocks": [
82+
{
83+
"name": "Warranty Program",
84+
"price": {
85+
"nominal": 100000,
86+
"real": 89000
87+
},
88+
"quantity": 10000,
89+
"choices": []
90+
}
91+
],
92+
"name": "Warranty Program",
93+
"required": false,
94+
"primary": false
95+
},
96+
{
97+
"options": [],
98+
"stocks": [
99+
{
100+
"name": "Magnetic Keyboard",
101+
"price": {
102+
"nominal": 200000,
103+
"real": 169000
104+
},
105+
"quantity": 8000,
106+
"choices": []
107+
}
108+
],
109+
"name": "Magnetic Keyboard",
110+
"required": false,
111+
"primary": false
112+
}
113+
],
114+
"tags": [
115+
"Surface Pro 9",
116+
"2-in-1 device",
117+
"laptop",
118+
"tablet"
119+
]
120+
}

examples/function-calling/schemas/deepseek.sale.schema.json

+367
Large diffs are not rendered by default.

examples/function-calling/schemas/llama.sale.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@
194194
},
195195
"units": {
196196
"title": "List of units",
197-
"description": "List of units.\n\nRecords about individual product composition informations that are sold\nin the sale. Each {@link IShoppingSaleUnit unit} record has configurable\n{@link IShoppingSaleUnitOption options},\n{@link IShoppingSaleUnitOptionCandidate candidate} values for each\noption, and {@link IShoppingSaleUnitStock final stocks} determined by\nselecting every candidate values of each option.",
197+
"description": "List of units.\n\nRecords about individual product composition information that are sold\nin the sale. Each {@link IShoppingSaleUnit unit} record has configurable\n{@link IShoppingSaleUnitOption options},\n{@link IShoppingSaleUnitOptionCandidate candidate} values for each\noption, and {@link IShoppingSaleUnitStock final stocks} determined by\nselecting every candidate values of each option.",
198198
"type": "array",
199199
"items": {
200200
"description": "Creation information of sale unit.\n\n------------------------------\n\nDescription of the current {@link IShoppingSaleUnit.ICreate} type:\n\n> Creation information of sale unit.\n\n------------------------------\n\nDescription of the parent {@link IShoppingSaleUnit} type:\n\n> Product composition information handled in the sale.\n> \n> `IShoppingSaleUnit` is an entity that embodies the \"individual product\"\n> information handled in the {@link IShoppingSale sale}.\n> \n> For reference, the reason why `IShoppingSaleUnit` is separated from\n> {@link IShoppingSaleSnapshot} by an algebraic relationship of 1: N is because\n> there are some cases where multiple products are sold in one listing. This is\n> the case with so-called \"bundled products\".\n> \n> - Bundle from regular product (Mackbook Set)\n> - Main Body\n> - Keyboard\n> - Mouse\n> - Apple Care (Free A/S Voucher)\n> \n> And again, `IShoppingSaleUnit` does not in itself refer to the\n> {@link IShoppingSaleUnitStock final stock} that the\n> {@link IShoppingCustomer customer} will {@link IShoppingOrder purchase}.\n> The final stock can be found only after selecting all given\n> {@link IShoppingSaleUnitOption options} and their\n> {@link IShoppingSaleUnitOptionCandidate candidate values}.\n> \n> For example, even if you buy a Macbook, the final stocks are determined only\n> after selecting all the options (CPU / RAM / SSD), etc.",

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
"typedoc-github-theme": "^0.2.1",
8080
"typescript": "~5.7.2",
8181
"typescript-transform-paths": "^3.5.2",
82-
"typia": "7.6.0",
82+
"typia": "7.6.4",
8383
"uuid": "^10.0.0"
8484
},
8585
"sideEffects": false,

src/structures/IGeminiSchema.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
* - {@link OpenApi.IJsonSchema.IString.default}
4646
* - {@link OpenApi.IJsonSchema.IArray.minItems}
4747
* - {@link OpenApi.IJsonSchema.IArray.maxItems}
48-
* - {@link OpenApi.IJsonSchema.IArray.unique}
48+
* - {@link OpenApi.IJsonSchema.IArray.uniqueItems}
4949
*
5050
* @reference https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/function-calling
5151
* @reference https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import fs from "fs";
2+
import typia, { tags } from "typia";
3+
4+
import { TestGlobal } from "../../../TestGlobal";
5+
import { DeepSeekFunctionCaller } from "../../../utils/DeepSeekFunctionCaller";
6+
7+
export const test_deepseek_function_calling_additionalProperties =
8+
(): Promise<void> =>
9+
DeepSeekFunctionCaller.test({
10+
model: (TestGlobal.getArguments("model")[0] as any) ?? "chatgpt",
11+
name: "enrollPerson",
12+
description: "Enroll a person to the restaurant reservation list.",
13+
collection: typia.json.schemas<[{ input: IPerson }]>(),
14+
validate: typia.createValidate<{ input: IPerson }>(),
15+
texts: [
16+
{
17+
role: "assistant",
18+
content: SYSTEM_MESSAGE,
19+
},
20+
{
21+
role: "user",
22+
content: USER_MESSAGE,
23+
},
24+
],
25+
handleParameters: async (parameters) => {
26+
if (process.argv.includes("--file"))
27+
await fs.promises.writeFile(
28+
`${TestGlobal.ROOT}/examples/function-calling/schemas/deepseek.additionalProperties.schema.json`,
29+
JSON.stringify(parameters, null, 2),
30+
"utf8",
31+
);
32+
},
33+
handleCompletion: async (input) => {
34+
typia.assert<IPerson>(input);
35+
if (process.argv.includes("--file"))
36+
await fs.promises.writeFile(
37+
`${TestGlobal.ROOT}/examples/function-calling/arguments/deepseek.additionalProperties.input.json`,
38+
JSON.stringify(input, null, 2),
39+
"utf8",
40+
);
41+
},
42+
});
43+
44+
interface IPerson {
45+
/**
46+
* The name of the person.
47+
*/
48+
name: string;
49+
50+
/**
51+
* The age of the person.
52+
*/
53+
age: number & tags.Type<"uint32">;
54+
55+
/**
56+
* Additional informations about the person.
57+
*/
58+
etc: Record<string, string>;
59+
}
60+
61+
const SYSTEM_MESSAGE =
62+
"You are a helpful customer support assistant. Use the supplied tools to assist the user.";
63+
64+
const USER_MESSAGE = `
65+
Just enroll a person with below information:
66+
67+
- name: John Doe
68+
- age: 42
69+
- hobby: Soccer
70+
- job: Scientist
71+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import fs from "fs";
2+
import typia, { tags } from "typia";
3+
4+
import { TestGlobal } from "../../../TestGlobal";
5+
import { DeepSeekFunctionCaller } from "../../../utils/DeepSeekFunctionCaller";
6+
7+
export const test_deepseek_function_calling_default = () =>
8+
DeepSeekFunctionCaller.test({
9+
model: (TestGlobal.getArguments("model")[0] as any) ?? "chatgpt",
10+
name: "enrollPerson",
11+
description: "Enroll a person to the restaurant reservation list.",
12+
collection: typia.json.schemas<[{ input: IPerson }]>(),
13+
validate: typia.createValidate<{ input: IPerson }>(),
14+
texts: [
15+
{
16+
role: "assistant",
17+
content: SYSTEM_MESSAGE,
18+
},
19+
{
20+
role: "user",
21+
content: USER_MESSAGE,
22+
},
23+
],
24+
handleParameters: async (parameters) => {
25+
if (process.argv.includes("--file"))
26+
await fs.promises.writeFile(
27+
`${TestGlobal.ROOT}/examples/function-calling/schemas/deepseek.default.schema.json`,
28+
JSON.stringify(parameters, null, 2),
29+
"utf8",
30+
);
31+
},
32+
handleCompletion: async (input) => {
33+
typia.assert<IPerson>(input);
34+
if (process.argv.includes("--file"))
35+
await fs.promises.writeFile(
36+
`${TestGlobal.ROOT}/examples/function-calling/arguments/deepseek.default.input.json`,
37+
JSON.stringify(input, null, 2),
38+
"utf8",
39+
);
40+
},
41+
});
42+
43+
interface IPerson {
44+
name: string & tags.Default<"John Doe">;
45+
age: number & tags.Default<42>;
46+
}
47+
48+
const SYSTEM_MESSAGE =
49+
"You are a helpful customer support assistant. Use the supplied tools to assist the user.";
50+
51+
const USER_MESSAGE =
52+
"Just enroll a person whose name and age values exactly same with the default values.";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { TestValidator } from "@nestia/e2e";
2+
import OpenAI from "openai";
3+
4+
import { TestGlobal } from "../../../TestGlobal";
5+
6+
export const test_deepseek_function_calling_empty = async (): Promise<void> => {
7+
if (TestGlobal.env.LLAMA_API_KEY === undefined) return;
8+
9+
const client: OpenAI = new OpenAI({
10+
apiKey: TestGlobal.env.LLAMA_API_KEY,
11+
baseURL: "https://api.deepseek-api.com",
12+
});
13+
const completion: OpenAI.ChatCompletion =
14+
await client.chat.completions.create({
15+
model: "deepseek-v3",
16+
messages: [
17+
{
18+
role: "system",
19+
content:
20+
"You are a helpful customer support assistant. Use the supplied tools to assist the user.",
21+
},
22+
{
23+
role: "user",
24+
content: "Call a print function please.",
25+
},
26+
],
27+
tools: [
28+
{
29+
type: "function",
30+
function: {
31+
name: "print",
32+
description: "Print to the screen.",
33+
parameters: {
34+
type: "object",
35+
properties: {},
36+
required: [],
37+
},
38+
},
39+
},
40+
],
41+
tool_choice: "required",
42+
parallel_tool_calls: false,
43+
});
44+
const call = completion.choices[0].message.tool_calls?.[0];
45+
TestValidator.equals("name")(call?.function.name)("print");
46+
TestValidator.equals("arguments")(call?.function.arguments)("{}");
47+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import fs from "fs";
2+
import typia, { tags } from "typia";
3+
4+
import { TestGlobal } from "../../../TestGlobal";
5+
import { DeepSeekFunctionCaller } from "../../../utils/DeepSeekFunctionCaller";
6+
7+
export const test_deepseek_function_calling_example = () =>
8+
DeepSeekFunctionCaller.test({
9+
model: (TestGlobal.getArguments("model")[0] as any) ?? "deepseek",
10+
name: "enrollPerson",
11+
description: "Enroll a person to the restaurant reservation list.",
12+
collection: typia.json.schemas<[{ input: IPerson }]>(),
13+
validate: typia.createValidate<{ input: IPerson }>(),
14+
texts: [
15+
{
16+
role: "assistant",
17+
content: SYSTEM_MESSAGE,
18+
},
19+
{
20+
role: "user",
21+
content: USER_MESSAGE,
22+
},
23+
],
24+
handleParameters: async (parameters) => {
25+
if (process.argv.includes("--file"))
26+
fs.promises.writeFile(
27+
`${TestGlobal.ROOT}/examples/function-calling/schemas/deepseek.example.schema.json`,
28+
JSON.stringify(parameters, null, 2),
29+
"utf8",
30+
);
31+
},
32+
handleCompletion: async (input) => {
33+
typia.assert<IPerson>(input);
34+
if (process.argv.includes("--file"))
35+
await fs.promises.writeFile(
36+
`${TestGlobal.ROOT}/examples/function-calling/arguments/deepseek.example.input.json`,
37+
JSON.stringify(input, null, 2),
38+
"utf8",
39+
);
40+
},
41+
});
42+
43+
interface IPerson {
44+
name: string & tags.Example<"John Doe">;
45+
age: number & tags.Example<42>;
46+
}
47+
48+
const SYSTEM_MESSAGE =
49+
"You are a helpful customer support assistant. Use the supplied tools to assist the user.";
50+
51+
const USER_MESSAGE =
52+
"Just enroll a person whose name and age values exactly same with the example values.";

0 commit comments

Comments
 (0)