Skip to content

refactor(js): introduced @genkit-ai/shared package that will contain shared type, plugin and action framework #3250

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions genkit-tools/common/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const config: Config = {

// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
transformIgnorePatterns: ['/node_modules/'],

moduleNameMapper: {
'^(\\.{1,2}/.*)\\.js$': '$1',
},
};

export default config;
55 changes: 27 additions & 28 deletions genkit-tools/common/src/types/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,47 +14,46 @@
* limitations under the License.
*/

import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
import { z } from 'zod';

extendZodWithOpenApi(z);
import * as z from 'zod';

// `z.any()` generates `{ nullable: true }` with no type set which is not valid OpenAPI spec.
// There's no way around this without defining a custom type. `z.array()` needs an inner type which runs into the same issue.

export const SingularAnySchema = z
.union([z.string(), z.number(), z.bigint(), z.boolean(), z.object({})])
.openapi('SingularAny');
export const SingularAnySchema = z.union([
z.string(),
z.number(),
z.bigint(),
z.boolean(),
z.object({}),
]);

export const CustomAnySchema = z
.union([SingularAnySchema, z.array(SingularAnySchema)])
.openapi('CustomAny');
export const CustomAnySchema = z.union([
SingularAnySchema,
z.array(SingularAnySchema),
]);

// TODO: Figure out a way to do z.custom<JSONSchema7>() and have it generate a nullable object correctly.
export const JSONSchema7Schema = z
.object({})
.describe(
'A JSON Schema Draft 7 (http://json-schema.org/draft-07/schema) object.'
)
.nullish()
.openapi('JSONSchema7');
.nullish();

export const ActionSchema = z
.object({
key: z.string().describe('Action key consisting of action type and ID.'),
name: z.string().describe('Action name.'),
description: z
.string()
.describe('A description of what the action does.')
.nullish(),
inputSchema: JSONSchema7Schema,
outputSchema: JSONSchema7Schema,
metadata: z
.record(z.string(), CustomAnySchema)
.describe('Metadata about the action (e.g. supported model features).')
.nullish(),
})
.openapi('Action');
export const ActionSchema = z.object({
key: z.string().describe('Action key consisting of action type and ID.'),
name: z.string().describe('Action name.'),
description: z
.string()
.describe('A description of what the action does.')
.nullish(),
inputSchema: JSONSchema7Schema,
outputSchema: JSONSchema7Schema,
metadata: z
.record(z.string(), CustomAnySchema)
.describe('Metadata about the action (e.g. supported model features).')
.nullish(),
});

export type Action = z.infer<typeof ActionSchema>;

Expand Down
10 changes: 10 additions & 0 deletions genkit-tools/common/src/types/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const EmptyPartSchema = z.object({
metadata: z.record(z.unknown()).optional(),
custom: z.record(z.unknown()).optional(),
reasoning: z.never().optional(),
resource: z.never().optional(),
});

/**
Expand Down Expand Up @@ -147,6 +148,15 @@ export const CustomPartSchema = EmptyPartSchema.extend({
*/
export type CustomPart = z.infer<typeof CustomPartSchema>;

/**
* Zod schema of a resource part.
*/
export const ResourcePartSchema = EmptyPartSchema.extend({
resource: z.object({
uri: z.string(),
}),
});

// Disclaimer: genkit/js/ai/document.ts defines the following schema, type pair
// as PartSchema and Part, respectively. genkit-tools cannot retain those names
// due to it clashing with similar schema in model.ts, and genkit-tools
Expand Down
63 changes: 53 additions & 10 deletions genkit-tools/common/src/types/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
DocumentDataSchema,
MediaPartSchema,
ReasoningPartSchema,
ResourcePartSchema,
TextPartSchema,
ToolRequestPartSchema,
ToolResponsePartSchema,
Expand All @@ -29,7 +30,7 @@ import {
type TextPart,
type ToolRequestPart,
type ToolResponsePart,
} from './document';
} from './document.js';
export {
CustomPartSchema,
DataPartSchema,
Expand Down Expand Up @@ -77,6 +78,7 @@ export const PartSchema = z.union([
DataPartSchema,
CustomPartSchema,
ReasoningPartSchema,
ResourcePartSchema,
]);

/**
Expand Down Expand Up @@ -183,18 +185,59 @@ export const ToolDefinitionSchema = z.object({
*/
export type ToolDefinition = z.infer<typeof ToolDefinitionSchema>;

/**
* Configuration parameter descriptions.
*/
export const GenerationCommonConfigDescriptions = {
temperature:
'Controls the degree of randomness in token selection. A lower value is ' +
'good for a more predictable response. A higher value leads to more ' +
'diverse or unexpected results.',
maxOutputTokens: 'The maximum number of tokens to include in the response.',
topK: 'The maximum number of tokens to consider when sampling.',
topP:
'Decides how many possible words to consider. A higher value means ' +
'that the model looks at more possible words, even the less likely ' +
'ones, which makes the generated text more diverse.',
};

/**
* Zod schema of a common config object.
*/
export const GenerationCommonConfigSchema = z.object({
/** A specific version of a model family, e.g. `gemini-1.0-pro-001` for the `gemini-1.0-pro` family. */
version: z.string().optional(),
temperature: z.number().optional(),
maxOutputTokens: z.number().optional(),
topK: z.number().optional(),
topP: z.number().optional(),
stopSequences: z.array(z.string()).optional(),
});
export const GenerationCommonConfigSchema = z
.object({
version: z
.string()
.describe(
'A specific version of a model family, e.g. `gemini-2.0-flash` ' +
'for the `googleai` family.'
)
.optional(),
temperature: z
.number()
.describe(GenerationCommonConfigDescriptions.temperature)
.optional(),
maxOutputTokens: z
.number()
.describe(GenerationCommonConfigDescriptions.maxOutputTokens)
.optional(),
topK: z
.number()
.describe(GenerationCommonConfigDescriptions.topK)
.optional(),
topP: z
.number()
.describe(GenerationCommonConfigDescriptions.topP)
.optional(),
stopSequences: z
.array(z.string())
.max(5)
.describe(
'Set of character sequences (up to 5) that will stop output generation.'
)
.optional(),
})
.passthrough();

/**
* Common config object.
Expand Down
73 changes: 33 additions & 40 deletions genkit-tools/common/src/types/trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@
* limitations under the License.
*/

import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
import * as z from 'zod';

extendZodWithOpenApi(z);

// NOTE: Keep this file in sync with js/core/src/tracing/types.ts!
// Eventually tools will be source of truth for these types (by generating a
// JSON schema) but until then this file must be manually kept in sync
Expand Down Expand Up @@ -108,48 +105,44 @@ export const InstrumentationLibrarySchema = z.object({
/**
* Zod schema for span data.
*/
export const SpanDataSchema = z
.object({
spanId: z.string(),
traceId: z.string(),
parentSpanId: z.string().optional(),
startTime: z.number(),
endTime: z.number(),
attributes: z.record(z.string(), z.unknown()),
displayName: z.string(),
links: z.array(LinkSchema).optional(),
instrumentationLibrary: InstrumentationLibrarySchema,
spanKind: z.string(),
sameProcessAsParentSpan: z.object({ value: z.boolean() }).optional(),
status: SpanStatusSchema.optional(),
timeEvents: z
.object({
timeEvent: z.array(TimeEventSchema).optional(),
})
.optional(),
truncated: z.boolean().optional(),
})
.openapi('SpanData');
export const SpanDataSchema = z.object({
spanId: z.string(),
traceId: z.string(),
parentSpanId: z.string().optional(),
startTime: z.number(),
endTime: z.number(),
attributes: z.record(z.string(), z.unknown()),
displayName: z.string(),
links: z.array(LinkSchema).optional(),
instrumentationLibrary: InstrumentationLibrarySchema,
spanKind: z.string(),
sameProcessAsParentSpan: z.object({ value: z.boolean() }).optional(),
status: SpanStatusSchema.optional(),
timeEvents: z
.object({
timeEvent: z.array(TimeEventSchema).optional(),
})
.optional(),
truncated: z.boolean().optional(),
});
export type SpanData = z.infer<typeof SpanDataSchema>;

/**
* Zod schema for trace metadata.
*/
export const TraceDataSchema = z
.object({
traceId: z.string(),
displayName: z.string().optional(),
startTime: z
.number()
.optional()
.describe('trace start time in milliseconds since the epoch'),
endTime: z
.number()
.optional()
.describe('end time in milliseconds since the epoch'),
spans: z.record(z.string(), SpanDataSchema),
})
.openapi('TraceData');
export const TraceDataSchema = z.object({
traceId: z.string(),
displayName: z.string().optional(),
startTime: z
.number()
.optional()
.describe('trace start time in milliseconds since the epoch'),
endTime: z
.number()
.optional()
.describe('end time in milliseconds since the epoch'),
spans: z.record(z.string(), SpanDataSchema),
});
export type TraceData = z.infer<typeof TraceDataSchema>;

export const NestedSpanDataSchema = SpanDataSchema.extend({
Expand Down
Loading