Skip to content
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

Generate-code and big models update #168

Merged
merged 4 commits into from
Oct 14, 2024
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion cloudapi
Submodule cloudapi updated 403 files
2 changes: 1 addition & 1 deletion examples/ai-translate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { serviceClients, Session, cloudApi } from '@yandex-cloud/nodejs-sdk';
import { getEnv } from './utils/get-env';
import { log } from './utils/logger';

const { ai: { translate_translation_service: { TranslateRequest, TranslateRequest_Format: Format } } } = cloudApi;
const { ai: { translate_v2_translation_service: { TranslateRequest, TranslateRequest_Format: Format } } } = cloudApi;

const TEXTS = ['NodeJS SDK examples', 'Powerful, but easy to use library'];
const AUTH_TOKEN = getEnv('YC_OAUTH_TOKEN');
Expand Down
102 changes: 102 additions & 0 deletions examples/chat-with-assistant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { serviceClients, Session, cloudApi } from '@yandex-cloud/nodejs-sdk';
import path from 'path';
import dotenv from 'dotenv';

dotenv.config({ path: path.resolve(__dirname, '.env') });

const getEnv = (envName: string, defaultValue?: string): string => {
const envValue = process.env[envName] || defaultValue;

console.log(process.env);

if (!envValue) {
throw new Error(`Env variable ${envName} is not defined`);
}

return envValue;
};

const iamToken = getEnv('YC_IAM_TOKEN');
const folderId = getEnv('YC_FOLDER_ID');

(async () => {
const session = new Session({ iamToken });

const assistantApi = cloudApi.ai.assistants_assistant_service;
const messageApi = cloudApi.ai.assistants_threads_message_service;
const threadApi = cloudApi.ai.assistants_threads_thread_service;
const runApi = cloudApi.ai.assistants_runs_run_service;

// const assistantClient = session.client(assistantApi.AssistantServiceClient);
const assistantClient = session.client(
serviceClients.AssistantServiceClient,
);

// const messageClient = session.client(messageApi.MessageServiceClient);
const messageClient = session.client(
serviceClients.AssistantMessageServiceClient,
);

// const threadClient = session.client(threadApi.ThreadServiceClient);
const threadClient = session.client(
serviceClients.AssistantThreadServiceClient,
);

// const runClient = session.client(runApi.RunServiceClient);
const runClient = session.client(serviceClients.AssistantRunServiceClient);

const thread = await threadClient.create(
threadApi.CreateThreadRequest.fromPartial({
name: 'qwerty',
folderId,
}),
);

console.log({ thread });

const assistant = await assistantClient.create(
assistantApi.CreateAssistantRequest.fromPartial({
name: 'qwerty',
folderId,
modelUri: `gpt://${folderId}/yandexgpt/latest`,
}),
);

console.log({ assistant });

const assistantId = assistant.id;
const threadId = thread.id;

const message = await messageClient.create(
messageApi.CreateMessageRequest.fromPartial({
threadId,
content: {
content: [{ text: { content: 'qwerty' } }],
},
}),
);

console.log({ message });

const run = await runClient.create(
runApi.CreateRunRequest.fromPartial({
threadId,
assistantId,
}),
);

console.log({ run });

const asyncIterableForStreamEvent = runClient.listen(
runApi.ListenRunRequest.fromPartial({ runId: run.id }),
);

let lastStreamEvent: cloudApi.ai.assistants_runs_run_service.StreamEvent | null = null;

for await (const streamEvent of asyncIterableForStreamEvent) {
lastStreamEvent = streamEvent;
}

console.dir({ lastStreamEvent });
console.dir(lastStreamEvent.completedMessage.content.content);
})();
4 changes: 4 additions & 0 deletions scripts/exceptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const exportAliasExceptions: Record<string, string | undefined> = {
'v1/metering/usage_record': 'v1_metering_usage_record',
'v1/metering/image_product_usage_service': 'v1_metering_image_product_usage_service',
};
120 changes: 85 additions & 35 deletions scripts/generate-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import * as _ from 'lodash';
import { logger } from '../src/utils/logger';
import { servicesConfig } from './services';

import { exportAliasExceptions } from './exceptions';

const GENERATED_CODE_DIR = path.resolve('./src/generated');
const GENERATED_PROJECTS_DIR = path.join(GENERATED_CODE_DIR, 'yandex', 'cloud');
const PROTO_DIR = path.resolve('./cloudapi');
Expand All @@ -19,7 +21,9 @@ fs.mkdirSync(GENERATED_CODE_DIR);

const protoFiles = fg.sync('**/*.proto', { cwd: YA_PROTO_DIR, absolute: true });

logger.debug(`Found ${protoFiles.length} proto files in ${YA_PROTO_DIR} directory`);
logger.debug(
`Found ${protoFiles.length} proto files in ${YA_PROTO_DIR} directory`,
);

const commandArgs = [
'npx --no-install grpc_tools_node_protoc',
Expand All @@ -34,7 +38,11 @@ logger.debug(`Code generation command: \n ${command}`);

cp.execSync(command);

const projectsDirs = fg.sync('*', { cwd: GENERATED_PROJECTS_DIR, onlyDirectories: true, absolute: true });
const projectsDirs = fg.sync('*', {
cwd: GENERATED_PROJECTS_DIR,
onlyDirectories: true,
absolute: true,
});

logger.debug(`Found ${projectsDirs.length} project directories`, projectsDirs);

Expand All @@ -50,6 +58,12 @@ interface ProjectMeta {

const projectsMeta: Record<string, ProjectMeta> = {};

const getExportAlias = (relativePath: string) => exportAliasExceptions[relativePath]
|| relativePath
.split(path.sep)
.filter((str) => str !== 'v1')
.join('_');

for (const projectDir of projectsDirs) {
logger.debug(`Processing project directory ${projectDir}`);

Expand All @@ -72,36 +86,30 @@ for (const projectDir of projectsDirs) {
};

const exportStatements = projectModules.map((modulePath) => {
const relativePath = path.relative(projectDir, modulePath);
const relativePathSegments = relativePath.split(path.sep);
const firstPathSegment = relativePathSegments[0];
const moduleName = path.basename(modulePath).replace('.ts', '');
const serviceName = moduleName.replace('_service', '');
// Do not use 'vX' as prefixes
const usePathSegmentAsPrefix = relativePathSegments.length > 1
&& firstPathSegment.length > 2
&& firstPathSegment !== serviceName;
const moduleAlias = [
usePathSegmentAsPrefix ? firstPathSegment : undefined,
moduleName,
].filter(Boolean).join('_');

const { ext } = path.parse(modulePath);
const moduleWithoutExt = relativePath.replace(ext, '');

if (moduleWithoutExt.endsWith('_service')) {
const relativePath = path
.relative(projectDir, modulePath)
.replace('.ts', '');

const exportAlias = getExportAlias(relativePath);

if (relativePath.endsWith('_service')) {
const name = path.basename(modulePath);

projectsMeta[indexModulePath].services.push({
name: moduleName,
exportAlias: moduleAlias,
name,
exportAlias,
});
}

return `export * as ${moduleAlias} from './${moduleWithoutExt}'`;
return `export * as ${exportAlias} from './${relativePath}'`;
});

const indexModuleContent = exportStatements.join('\n');

logger.debug(`Writing export statements to ${indexModulePath} module`, indexModuleContent);
logger.debug(
`Writing export statements to ${indexModulePath} module`,
indexModuleContent,
);

fs.writeFileSync(indexModulePath, indexModuleContent, 'utf8');
}
Expand All @@ -110,34 +118,76 @@ for (const projectDir of projectsDirs) {
logger.debug('Generating root index module');

const rootIndexModulePath = path.join(GENERATED_PROJECTS_DIR, 'index.ts');
const serviceClientsModulePath = path.join(GENERATED_PROJECTS_DIR, 'service_clients.ts');
const serviceClientsModulePath = path.join(
GENERATED_PROJECTS_DIR,
'service_clients.ts',
);
const rootModuleContentParts: string[] = [];
const serviceClientsModuleContentParts: string[] = [
'import * as cloudApi from \'.\'',
"import * as cloudApi from '.'",
];

const serviceClientsExportsSet = new Set<string>();

for (const [indexModulePath, projectMeta] of Object.entries(projectsMeta)) {
logger.debug(`Processing ${indexModulePath} module`);
const relativePath = path.relative(GENERATED_PROJECTS_DIR, indexModulePath).replace('index.ts', '');
const relativePath = path
.relative(GENERATED_PROJECTS_DIR, indexModulePath)
.replace('index.ts', '');

rootModuleContentParts.push(`export * as ${projectMeta.name} from './${relativePath}'`);
rootModuleContentParts.push(
`export * as ${projectMeta.name} from './${relativePath}'`,
);

for (const serviceMeta of projectMeta.services) {
const serviceConfig = servicesConfig[projectMeta.name]?.[serviceMeta.exportAlias];

if (serviceConfig) {
serviceClientsModuleContentParts.push(
// eslint-disable-next-line max-len
`export const ${serviceConfig.exportClassName || serviceConfig.importClassName} = cloudApi.${projectMeta.name}.${serviceMeta.exportAlias}.${serviceConfig.importClassName};`,
);
delete servicesConfig[projectMeta.name]?.[serviceMeta.exportAlias];

const exportStr = `export const ${
serviceConfig.exportClassName || serviceConfig.importClassName
} = cloudApi.${projectMeta.name}.${serviceMeta.exportAlias}.${
serviceConfig.importClassName
};`;

if (serviceClientsExportsSet.has(exportStr)) continue;

serviceClientsModuleContentParts.push(exportStr);
serviceClientsExportsSet.add(exportStr);
} else {
logger.warn(`There is no configuration for service ${serviceMeta.exportAlias} in project ${projectMeta.name}`);
logger.warn(
`There is no configuration for service ${serviceMeta.exportAlias} in project ${projectMeta.name}`,
);
}
}
}

logger.debug(`Writing result to ${rootIndexModulePath} module`);
logger.debug(`Writing result to ${serviceClientsModulePath} module`);

fs.writeFileSync(rootIndexModulePath, rootModuleContentParts.join('\n'), 'utf8');
fs.writeFileSync(serviceClientsModulePath, serviceClientsModuleContentParts.join('\n'), 'utf8');
logger.debug('\n\n\n');

for (const serviceName of Object.keys(servicesConfig)) {
const obj = servicesConfig[serviceName];
const keys = Object.keys(obj);

if (keys.length > 0) {
logger.warn(
`There are unused config keys for service ${serviceName}: ${keys.join(
', ',
)}`,
);
}
}

fs.writeFileSync(
rootIndexModulePath,
rootModuleContentParts.join('\n'),
'utf8',
);
fs.writeFileSync(
serviceClientsModulePath,
serviceClientsModuleContentParts.join('\n'),
'utf8',
);
Loading
Loading