// @ts-check
import { execSync } from 'child_process';
import { docsNotebooks } from './docs-notebooks.js';
import { NotebookContentReader } from './notebook-content-reader.js';
/** @typedef {import('./notebook-content-reader.js').INotebookMetadata} INotebookMetadata */
export class NotebookMetadataCollector extends NotebookContentReader {
/**
* @private
* @returns {string}
*/
_getNotebookTitle() {
const { cells } = this._getNotebookJson();
const firstCellContent = cells[0].source.join('');
const titleRegexp = /# (?
.+)/g;
const match = titleRegexp.exec(firstCellContent);
if (!match || !match.groups || !match.groups.title) {
return '';
}
const markdownLinkRegExp = /\[(.+)\]\(.+\)/g;
return match.groups.title.replace(markdownLinkRegExp, (value, group) => `${group || value}`).trim();
}
/**
* @private
* @returns {string | null}
*/
_getImageUrl() {
const imageUrl = this._getMetadataFromNotebookFile('imageUrl');
return imageUrl || null;
}
/**
* @private
* @returns {string}
*/
_getNotebookCreatedDate() {
return execSync(
`git log --follow -1 --pretty=format:"%ad" --date=iso --diff-filter=AC -- ${this._absoluteNotebookPath}`
).toString();
}
/**
* @private
* @returns {string}
*/
_getNotebookModifiedDate() {
return execSync(
`git log -1 --pretty=format:"%ad" --date=iso --diff-filter=a -- ${this._absoluteNotebookPath}`
).toString();
}
/**
* @private
* @returns {string}
*/
_getNotebookGitHubLink() {
return `https://github.com/openvinotoolkit/openvino_notebooks/blob/latest/notebooks/${this._notebookFilePath}`;
}
/**
* @private
* @returns {string | null}
*/
_getDocsLink() {
const { latestDocsNotebooks, latestOVReleaseTag } = docsNotebooks;
const notebookFileName = this._notebookFileName.replace('.ipynb', '');
const docsVersion = latestOVReleaseTag.split('.').slice(0, 2)[0];
const docsUrl = `https://docs.openvino.ai/${docsVersion}/notebooks/${notebookFileName}-with-output.html`;
return latestDocsNotebooks.includes(this._notebookFilePath) ? docsUrl : null;
}
/**
* @private
* @returns {string | null}
*/
_getNotebookColabLink() {
const readmeContent = this._getReadmeContent();
const colabBadgeRegExp = new RegExp(
`\\[!\\[Colab\\]\\(.+\\)\\]\\((?.+(?:${this._notebookFileName}))\\)`,
'g'
);
const match = colabBadgeRegExp.exec(readmeContent);
if (!match || !match.groups || !match.groups.link) {
return null;
}
return match.groups.link;
}
/**
* @private
* @returns {string | null}
*/
_getNotebookBinderLink() {
const readmeContent = this._getReadmeContent();
const binderBadgeRegExp = new RegExp(
`\\[!\\[Binder\\]\\(.+\\)\\]\\((?.+(?:${this._notebookFileName}))\\)`,
'g'
);
const match = binderBadgeRegExp.exec(readmeContent);
if (!match || !match.groups || !match.groups.link) {
return null;
}
return match.groups.link;
}
/**
* @private
* @returns {INotebookMetadata['tags']['libraries']}
*/
_getLibrariesTags() {
const codeCells = this._getCodeCells();
const content = codeCells.map(({ source }) => source.join('\n')).join('\n');
const tags = [];
for (const [tag, patterns] of Object.entries(librariesPatterns)) {
if (patterns.some((pattern) => content.includes(pattern))) {
tags.push(tag);
}
}
return tags;
}
/**
* @private
* @returns {INotebookMetadata['tags']}
*/
_getTags() {
const tags = this._getMetadataFromNotebookFile('tags');
const libraries = this._getLibrariesTags();
return {
categories: [],
tasks: [],
other: [],
...tags,
libraries,
};
}
/**
* Collects and returns new metadata object
*
* @public
* @returns {INotebookMetadata}
*/
getMetadata() {
return {
title: this._getNotebookTitle(),
path: this._notebookFilePath,
imageUrl: this._getImageUrl(),
createdDate: this._getNotebookCreatedDate(),
modifiedDate: this._getNotebookModifiedDate() || this._getNotebookCreatedDate(),
links: {
github: this._getNotebookGitHubLink(),
docs: this._getDocsLink(),
colab: this._getNotebookColabLink(),
binder: this._getNotebookBinderLink(),
},
tags: this._getTags(),
};
}
}
/** @typedef {typeof import('../shared/notebook-tags.js').LIBRARIES_VALUES} LIBRARIES_VALUES */
/** @type {Record} */
const librariesPatterns = {
NNCF: ['import nncf', 'from nncf'],
'Model Converter': ['ov.convert_model(', 'openvino.convert_model(', '! ovc'],
'Model Server': ['import ovmsclient', 'from ovmsclient'],
'Open Model Zoo': ['omz_downloader', 'omz_converter', 'omz_info_dumper'],
'Benchmark Tool': ['benchmark_app'],
'Optimum Intel': ['import optimum.intel', 'from optimum.intel'],
Transformers: ['import transformers', 'from transformers'],
Diffusers: ['import diffusers', 'from diffusers'],
TensorFlow: ['import tensorflow', 'from tensorflow'],
'TF Lite': ['.tflite'],
PyTorch: ['import torch', 'from torch'],
ONNX: ['.onnx'],
PaddlePaddle: ['import paddle', 'from paddle'],
Ultralytics: ['import ultralytics', 'from ultralytics'],
Gradio: ['import gradio', 'from gradio'],
'OpenVINO Tokenizers': ['import openvino_tokenizers', 'from openvino_tokenizers'],
};