chore: import upstream snapshot with attribution
tools_continuous_delivery / Private PyPI non-main branch release (push) Has been skipped
tools_continuous_delivery / Private PyPI main branch release (push) Failing after 2m42s
Publish Promptflow Doc / Build (push) Has been cancelled
Publish Promptflow Doc / Deploy (push) Has been cancelled
Flake8 Lint / flake8 (push) Has been cancelled
Spell check CI / Spell_Check (push) Has been cancelled
tools_continuous_delivery / Private PyPI non-main branch release (push) Has been skipped
tools_continuous_delivery / Private PyPI main branch release (push) Failing after 2m42s
Publish Promptflow Doc / Build (push) Has been cancelled
Publish Promptflow Doc / Deploy (push) Has been cancelled
Flake8 Lint / flake8 (push) Has been cancelled
Spell check CI / Spell_Check (push) Has been cancelled
This commit is contained in:
Vendored
+93
@@ -0,0 +1,93 @@
|
||||
.title {
|
||||
font-weight:700;
|
||||
}
|
||||
|
||||
.sd-card-header {
|
||||
font-weight:700;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
.bd-page-width {
|
||||
max-width: 100rem;
|
||||
}
|
||||
|
||||
.bd-sidebar-primary {
|
||||
flex: 0 0 20%;
|
||||
}
|
||||
|
||||
.bd-main .bd-content .bd-article-container {
|
||||
max-width: 70em;
|
||||
}
|
||||
|
||||
/* Background color for feature announcement */
|
||||
html[data-theme="light"] {
|
||||
--header-announcement-color: #3278e5;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] {
|
||||
--header-announcement-color: #67d6ed;
|
||||
}
|
||||
|
||||
.bd-header-announcement {
|
||||
background: var(--header-announcement-color);
|
||||
}
|
||||
/* Background color for feature announcement */
|
||||
|
||||
/* Background color for warning announcement */
|
||||
/*html[data-theme="light"] {*/
|
||||
/* --header-announcement-color: #fff070;*/
|
||||
/*}*/
|
||||
|
||||
/*html[data-theme="dark"] {*/
|
||||
/* --header-announcement-color: #4d4d00;*/
|
||||
/*}*/
|
||||
|
||||
/*.bd-header-announcement {*/
|
||||
/* background: var(--header-announcement-color);*/
|
||||
/*}*/
|
||||
/* Background color for warning announcement */
|
||||
|
||||
/* (A) LIGHTBOX BACKGROUND */
|
||||
#lightbox {
|
||||
/* (A1) COVERS FULLSCREEN */
|
||||
position: fixed; z-index: 1060;
|
||||
top: 0; left: 0;
|
||||
width: 100%; height: 100%;
|
||||
|
||||
/* (A2) BACKGROUND */
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
|
||||
/* (A3) CENTER IMAGE ON SCREEN */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: center;
|
||||
|
||||
/* (A4) HIDDEN BY DEFAULT */
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
|
||||
/* (A5) SHOW/HIDE ANIMATION */
|
||||
transition: opacity ease 0.4s;
|
||||
}
|
||||
/* (A6) TOGGLE VISIBILITY */
|
||||
#lightbox.show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
/* (B) LIGHTBOX IMAGE */
|
||||
#lightbox img {
|
||||
/* (B1) DIMENSIONS */
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
/* (B2) IMAGE FIT */
|
||||
/* contain | cover | fill | scale-down */
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
border-radius: 50%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
Vendored
+61
@@ -0,0 +1,61 @@
|
||||
// Get the head element
|
||||
let head = document.getElementsByTagName("head")[0];
|
||||
|
||||
// Create the script element
|
||||
let script = document.createElement("script");
|
||||
script.async = true;
|
||||
script.src = "https://www.googletagmanager.com/gtag/js?id=G-KZXK5PFBZY";
|
||||
|
||||
// Create another script element for the gtag code
|
||||
let script2 = document.createElement("script");
|
||||
script2.innerHTML = ` window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', 'G-KZXK5PFBZY'); `;
|
||||
|
||||
// Insert the script elements after the head element
|
||||
head.insertAdjacentElement("afterbegin", script2);
|
||||
head.insertAdjacentElement("afterbegin", script);
|
||||
|
||||
// This is used to zoom in images when clicked on
|
||||
window.onload = () => {
|
||||
if (document.getElementById("lightbox") === null){
|
||||
// Append lightbox div to each page
|
||||
let div = document.createElement('div');
|
||||
div.innerHTML = '<div id="lightbox"></div>';
|
||||
document.body.appendChild(div);
|
||||
}
|
||||
|
||||
// (A) GET LIGHTBOX & ALL .ZOOMD IMAGES
|
||||
let all = document.getElementsByClassName("bd-article")[0].getElementsByTagName("img"),
|
||||
lightbox = document.getElementById("lightbox");
|
||||
|
||||
// (B) CLICK TO SHOW IMAGE IN LIGHTBOX
|
||||
// * SIMPLY CLONE INTO LIGHTBOX & SHOW
|
||||
if (all.length>0) { for (let i of all) {
|
||||
// skip if class contains avatar or img_ev3q(Open on github button)
|
||||
if (i.classList.contains("avatar") || i.classList.contains("img_ev3q")) {
|
||||
continue;
|
||||
}
|
||||
i.onclick = () => {
|
||||
let clone = i.cloneNode();
|
||||
clone.className = "";
|
||||
lightbox.innerHTML = "";
|
||||
lightbox.appendChild(clone);
|
||||
lightbox.className = "show";
|
||||
};
|
||||
}}
|
||||
|
||||
// (C) CLICK TO CLOSE LIGHTBOX
|
||||
lightbox.onclick = () => {
|
||||
lightbox.className = "";
|
||||
};
|
||||
};
|
||||
|
||||
if (window.location.pathname === "/promptflow/" || window.location.pathname === "/promptflow/index.html") {
|
||||
// This is used to control homepage background
|
||||
let observer = new MutationObserver(function(mutations) {
|
||||
const dark = document.documentElement.dataset.theme == 'dark';
|
||||
document.body.style.backgroundSize = "100%";
|
||||
document.body.style.backgroundPositionY = "bottom";
|
||||
document.body.style.backgroundRepeat = "no-repeat"
|
||||
})
|
||||
observer.observe(document.documentElement, {attributes: true, attributeFilter: ['data-theme']});
|
||||
}
|
||||
Vendored
+47
@@ -0,0 +1,47 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_699_15212)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M237 39.0408V461.693C237 469.397 228.655 474.208 221.988 470.346L151.918 429.764C130.306 417.247 117 394.164 117 369.19V148.892C117 123.917 130.306 100.834 151.918 88.3177L237 39.0408Z" fill="url(#paint0_linear_699_15212)"/>
|
||||
<path d="M395.075 127.51L237 39V167.541L283.451 192.041L395.075 127.51Z" fill="url(#paint1_linear_699_15212)"/>
|
||||
<path d="M395.075 127.51L237 39V167.541L283.451 192.041L395.075 127.51Z" fill="url(#paint2_linear_699_15212)"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M255.5 231.426C255.5 217.184 263.073 204.017 275.382 196.854L395 127.248V216.101C395 241.03 381.742 264.078 360.193 276.611L270.528 328.76C263.861 332.637 255.5 327.828 255.5 320.116L255.5 231.426Z" fill="url(#paint3_linear_699_15212)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_699_15212" x1="196.286" y1="183.041" x2="270.786" y2="92.5087" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#3272ED"/>
|
||||
<stop offset="1" stop-color="#AF7BD6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_699_15212" x1="457.98" y1="131.313" x2="260.351" y2="133.014" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#DA7ED0"/>
|
||||
<stop offset="0.05" stop-color="#B77BD4"/>
|
||||
<stop offset="0.11" stop-color="#9079DA"/>
|
||||
<stop offset="0.18" stop-color="#6E77DF"/>
|
||||
<stop offset="0.25" stop-color="#5175E3"/>
|
||||
<stop offset="0.33" stop-color="#3973E7"/>
|
||||
<stop offset="0.42" stop-color="#2772E9"/>
|
||||
<stop offset="0.54" stop-color="#1A71EB"/>
|
||||
<stop offset="0.813361" stop-color="#1371EC"/>
|
||||
<stop offset="1" stop-color="#064495"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_699_15212" x1="210.18" y1="4.19164" x2="307.181" y2="175.949" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#712575"/>
|
||||
<stop offset="0.09" stop-color="#9A2884"/>
|
||||
<stop offset="0.18" stop-color="#BF2C92"/>
|
||||
<stop offset="0.27" stop-color="#DA2E9C"/>
|
||||
<stop offset="0.34" stop-color="#EB30A2"/>
|
||||
<stop offset="0.4" stop-color="#F131A5"/>
|
||||
<stop offset="0.5" stop-color="#EC30A3"/>
|
||||
<stop offset="0.61" stop-color="#DF2F9E"/>
|
||||
<stop offset="0.72" stop-color="#C92D96"/>
|
||||
<stop offset="0.83" stop-color="#AA2A8A"/>
|
||||
<stop offset="0.95" stop-color="#83267C"/>
|
||||
<stop offset="1" stop-color="#712575"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint3_linear_699_15212" x1="308" y1="260.041" x2="307.043" y2="133.204" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#1D5CD6"/>
|
||||
<stop offset="1" stop-color="#787BE5"/>
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_699_15212">
|
||||
<rect width="512" height="512" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 975 B |
@@ -0,0 +1,57 @@
|
||||
{%- macro automodule(modname, options) -%}
|
||||
.. automodule:: {{ modname }}
|
||||
{%- for option in options %}
|
||||
:{{ option }}:
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- macro toctree(docnames) -%}
|
||||
.. toctree::
|
||||
:maxdepth: {{ maxdepth }}
|
||||
{% for docname in docnames %}
|
||||
{{ docname }}
|
||||
{%- endfor %}
|
||||
{%- endmacro %}
|
||||
|
||||
{%- if is_namespace %}
|
||||
{{- [pkgname, "namespace"] | join(" ") | e | heading }}
|
||||
{% else %}
|
||||
{{- [pkgname, "module"] | join(" ") | e | heading }}
|
||||
{% endif %}
|
||||
|
||||
{%- if is_namespace %}
|
||||
.. py:module:: {{ pkgname }}
|
||||
{% endif %}
|
||||
|
||||
{%- if modulefirst and not is_namespace %}
|
||||
{{ automodule(pkgname, automodule_options) }}
|
||||
{% endif %}
|
||||
|
||||
{%- if subpackages %}
|
||||
Subpackages
|
||||
-----------
|
||||
|
||||
{{ toctree(subpackages) }}
|
||||
{% endif %}
|
||||
|
||||
{%- if submodules %}
|
||||
Submodules
|
||||
----------
|
||||
{% if separatemodules %}
|
||||
{{ toctree(submodules) }}
|
||||
{% else %}
|
||||
{%- for submodule in submodules %}
|
||||
{% if show_headings %}
|
||||
{{- [submodule, "module"] | join(" ") | e | heading(2) }}
|
||||
{% endif %}
|
||||
{{ automodule(submodule, automodule_options) }}
|
||||
{% endfor %}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
|
||||
{%- if not modulefirst and not is_namespace %}
|
||||
Module contents
|
||||
---------------
|
||||
|
||||
{{ automodule(pkgname, automodule_options) }}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,164 @@
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
import sys
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = "Prompt flow"
|
||||
copyright = "2024, Microsoft"
|
||||
author = "Microsoft"
|
||||
|
||||
sys.path.append(".")
|
||||
from gallery_directive import GalleryDirective # noqa: E402
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
extensions = [
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.autosummary",
|
||||
"sphinx.ext.todo",
|
||||
"sphinxext.rediraffe",
|
||||
"sphinx_design",
|
||||
"sphinx_copybutton",
|
||||
"matplotlib.sphinxext.plot_directive",
|
||||
"sphinx_togglebutton",
|
||||
"myst_nb",
|
||||
# 'myst_parser',
|
||||
"sphinx.builders.linkcheck",
|
||||
"jupyter_sphinx",
|
||||
]
|
||||
|
||||
# -- Internationalization ------------------------------------------------
|
||||
# specifying the natural language populates some key tags
|
||||
language = "en"
|
||||
|
||||
# specify charset as utf-8 to accept chinese punctuation
|
||||
charset_type = "utf-8"
|
||||
|
||||
autosummary_generate = True
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
# templates_path = ["_templates"]
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
nb_execution_mode = "off"
|
||||
exclude_patterns = [
|
||||
"_build",
|
||||
"Thumbs.db",
|
||||
".DS_Store",
|
||||
"**.ipynb_checkpoints",
|
||||
"**.py",
|
||||
"**.yml",
|
||||
"**.sh",
|
||||
"**.zip",
|
||||
"**.skip",
|
||||
]
|
||||
source_suffix = [".rst", ".md", ".ipynb"]
|
||||
|
||||
# Options for the linkcheck builder
|
||||
linkcheck_ignore = [
|
||||
# openai related sites blocks the IP of the CI server.
|
||||
r"https://openai\.com/",
|
||||
r"https://platform\.openai\.com/",
|
||||
r"https://help\.openai\.com/",
|
||||
# These are used in card links, for example 'xx.html', .md can't be resolved.
|
||||
r"^(?!https?)",
|
||||
"deploy-using-docker.html",
|
||||
"deploy-using-kubernetes.html",
|
||||
"https://portal.azure.com/#create/Microsoft.CognitiveServicesTextAnalytics", # sphinx recognizes #create as an anchor while it's not. # noqa: E501
|
||||
"https://ms.portal.azure.com/#view/Microsoft_Azure_Marketplace/MarketplaceOffersBlade/searchQuery/machine%20learning", # noqa: E501
|
||||
]
|
||||
|
||||
linkcheck_exclude_documents = [
|
||||
"contributing",
|
||||
r".*/tutorials/.*", # ignore link in copied notebooks.
|
||||
]
|
||||
|
||||
# -- Extension options -------------------------------------------------------
|
||||
|
||||
# This allows us to use ::: to denote directives, useful for admonitions
|
||||
myst_enable_extensions = ["colon_fence", "substitution"]
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = "pydata_sphinx_theme"
|
||||
html_logo = "_static/logo.svg"
|
||||
html_favicon = "_static/logo32.ico"
|
||||
html_sourcelink_suffix = ""
|
||||
html_show_sourcelink = False
|
||||
|
||||
# Define the json_url for our version switcher.
|
||||
|
||||
html_theme_options = {
|
||||
"github_url": "https://github.com/microsoft/promptflow",
|
||||
"header_links_before_dropdown": 6,
|
||||
"icon_links": [
|
||||
{
|
||||
"name": "PyPI",
|
||||
"url": "https://pypi.org/project/promptflow/",
|
||||
"icon": "fa-solid fa-box",
|
||||
},
|
||||
],
|
||||
"logo": {
|
||||
"text": "Prompt flow",
|
||||
"alt_text": "Prompt flow",
|
||||
},
|
||||
"use_edit_page_button": True,
|
||||
"show_toc_level": 1,
|
||||
"navbar_align": "left", # [left, content, right] For testing that the navbar items align properly
|
||||
"navbar_center": ["navbar-nav"],
|
||||
"announcement": "🚀<b style='color:black;'>"
|
||||
"Promptflow 1.13.0 has released! Try new feature: "
|
||||
"<a href='https://microsoft.github.io/promptflow/how-to-guides/tracing/index.html' style='color:black;'>"
|
||||
"<u>tracing interaction with LLMs</u></a>."
|
||||
"</b>",
|
||||
"show_nav_level": 1,
|
||||
}
|
||||
|
||||
html_sidebars = {
|
||||
# "quick_start/README.md": ['localtoc.html', 'relations.html', 'searchbox.html'],
|
||||
# "examples/persistent-search-field": ["search-field"],
|
||||
# Blog sidebars
|
||||
# ref: https://ablog.readthedocs.io/manual/ablog-configuration-options/#blog-sidebars
|
||||
"features": ["localtoc.html", "relations.html", "searchbox.html"],
|
||||
# "tutorials": ['localtoc.html', 'relations.html', 'searchbox.html'],
|
||||
}
|
||||
|
||||
html_context = {
|
||||
"default_mode": "light",
|
||||
"github_user": "",
|
||||
"github_repo": "microsoft/promptflow",
|
||||
"github_version": "main",
|
||||
"doc_path": "docs",
|
||||
}
|
||||
|
||||
rediraffe_redirects = {}
|
||||
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
html_css_files = ["custom.css"]
|
||||
html_js_files = ["custom.js"]
|
||||
todo_include_todos = True
|
||||
|
||||
|
||||
# myst reference config
|
||||
myst_heading_anchors = 5
|
||||
|
||||
|
||||
# allow annotation for __call__ methods
|
||||
autodoc_default_options = {
|
||||
'special-members': '__call__',
|
||||
}
|
||||
|
||||
|
||||
def setup(app):
|
||||
# Add the gallery directive
|
||||
app.add_directive("gallery-grid", GalleryDirective)
|
||||
@@ -0,0 +1,262 @@
|
||||
<#
|
||||
.DESCRIPTION
|
||||
Script to build doc site
|
||||
|
||||
.EXAMPLE
|
||||
PS> ./doc_generation.ps1 -SkipInstall # skip pip install
|
||||
PS> ./doc_generation.ps1 -BuildLinkCheck -WarningAsError:$true -SkipInstall
|
||||
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[switch]$SkipInstall,
|
||||
[switch]$WarningAsError = $false,
|
||||
[switch]$BuildLinkCheck = $false,
|
||||
[switch]$WithReferenceDoc = $false
|
||||
)
|
||||
|
||||
[string] $ScriptPath = $PSCommandPath | Split-Path -Parent
|
||||
[string] $RepoRootPath = $ScriptPath | Split-Path -Parent | Split-Path -Parent
|
||||
[string] $DocPath = [System.IO.Path]::Combine($RepoRootPath, "docs")
|
||||
[string] $TempDocPath = New-TemporaryFile | % { Remove-Item $_; New-Item -ItemType Directory -Path $_ }
|
||||
[string] $PkgSrcPath = [System.IO.Path]::Combine($RepoRootPath, "src")
|
||||
[string] $OutPath = [System.IO.Path]::Combine($ScriptPath, "_build")
|
||||
[string] $SphinxApiDoc = [System.IO.Path]::Combine($DocPath, "sphinx_apidoc.log")
|
||||
[string] $SphinxBuildDoc = [System.IO.Path]::Combine($DocPath, "sphinx_build.log")
|
||||
[string] $WarningErrorPattern = "WARNING:|ERROR:|CRITICAL:| broken "
|
||||
[System.Collections.ArrayList]$IncludeList = @("promptflow-tracing", "promptflow-core", "promptflow-devkit", "promptflow-azure", "promptflow-rag", "promptflow-evals")
|
||||
$apidocWarningsAndErrors = $null
|
||||
$buildWarningsAndErrors = $null
|
||||
|
||||
if (-not $SkipInstall){
|
||||
# Prepare doc generation packages
|
||||
pip install pydata-sphinx-theme==0.11.0
|
||||
pip install sphinx==5.1
|
||||
pip install sphinx-copybutton==0.5.0
|
||||
pip install sphinx_design==0.3.0
|
||||
pip install sphinx-sitemap==2.2.0
|
||||
pip install sphinx-togglebutton==0.3.2
|
||||
pip install sphinxext-rediraffe==0.2.7
|
||||
pip install sphinxcontrib-mermaid==0.8.1
|
||||
pip install ipython-genutils==0.2.0
|
||||
pip install myst-nb==0.17.1
|
||||
pip install numpydoc==1.5.0
|
||||
pip install myst-parser==0.18.1
|
||||
pip install "numpy<1.25"
|
||||
pip install matplotlib==3.4.3
|
||||
pip install jinja2==3.0.1
|
||||
pip install jupyter-sphinx==0.4.0
|
||||
Write-Host "===============Finished install requirements==============="
|
||||
}
|
||||
|
||||
|
||||
function ProcessFiles {
|
||||
# Exclude files not mean to be in doc site
|
||||
$exclude_files = "README.md", "dev"
|
||||
foreach ($f in $exclude_files)
|
||||
{
|
||||
$full_path = [System.IO.Path]::Combine($TempDocPath, $f)
|
||||
Remove-Item -Path $full_path -Recurse
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "===============PreProcess Files==============="
|
||||
Write-Host "Copy doc to: $TempDocPath"
|
||||
ROBOCOPY $DocPath $TempDocPath /S /NFL /NDL /XD "*.git" [System.IO.Path]::Combine($DocPath, "_scripts\_build")
|
||||
ProcessFiles
|
||||
|
||||
function Update-Sub-Pkg-Index-Title {
|
||||
param (
|
||||
[string] $SubPkgRefDocPath,
|
||||
[string] $SubPkgName
|
||||
)
|
||||
# This is used to update the title of the promptflow.rst file in the sub package
|
||||
# from 'promptflow namespaces' to package name
|
||||
$IndexRst = [System.IO.Path]::Combine($SubPkgRefDocPath, "promptflow.rst")
|
||||
$IndexContent = Get-Content $IndexRst
|
||||
$IndexContent[0] = ("{0} package" -f $SubPkgName)
|
||||
$IndexContent[1] = "================================="
|
||||
$IndexContent[2] = ".. py:module:: promptflow"
|
||||
$IndexContent[3] = " :noindex:"
|
||||
Set-Content $IndexRst $IndexContent
|
||||
}
|
||||
|
||||
function Add-Changelog {
|
||||
$ChangelogFolder = [System.IO.Path]::Combine($TempDocPath, "reference\changelog")
|
||||
New-Item -ItemType Directory -Path $ChangelogFolder -Force
|
||||
Write-Host "===============Collect Package ChangeLog==============="
|
||||
$TocTreeContent = @("", "``````{toctree}", ":maxdepth: 1", ":hidden:", "")
|
||||
foreach($Item in Get-Childitem -path $PkgSrcPath)
|
||||
{
|
||||
if((-not ($IncludeList -contains $Item.Name)) -and ($Item.Name -ne "promptflow")){
|
||||
continue
|
||||
}
|
||||
# Collect CHANGELOG, name with package.md
|
||||
$ChangelogPath = [System.IO.Path]::Combine($Item.FullName, "CHANGELOG.md")
|
||||
$TargetChangelogPath = [System.IO.Path]::Combine($ChangelogFolder, "{0}.md" -f $Item.Name)
|
||||
if($Item.Name -ne "promptflow"){
|
||||
$TocTreeContent += $Item.name
|
||||
}
|
||||
Copy-Item -Path $ChangelogPath -Destination $TargetChangelogPath
|
||||
}
|
||||
$TocTreeContent += "``````"
|
||||
# Add subpackage index to promptflow changelog
|
||||
$PromptflowChangelog = [System.IO.Path]::Combine($ChangelogFolder, "promptflow.md")
|
||||
$PromptflowChangelogContent = Get-Content $PromptflowChangelog
|
||||
$PromptflowChangelogContent[0] = "# promptflow package"
|
||||
$PromptflowChangelogContent += $TocTreeContent
|
||||
Set-Content $PromptflowChangelog $PromptflowChangelogContent
|
||||
}
|
||||
|
||||
function Add-Api-Reference {
|
||||
$RefDocRelativePath = "reference\python-library-reference"
|
||||
$RefDocPath = [System.IO.Path]::Combine($TempDocPath, $RefDocRelativePath)
|
||||
$PlaceHolderFile = [System.IO.Path]::Combine($RefDocPath, "promptflow.md")
|
||||
if(!(Test-Path $RefDocPath)){
|
||||
throw "Reference doc path not found. Please make sure '$RefDocRelativePath' is under '$DocPath'"
|
||||
}
|
||||
Remove-Item $PlaceHolderFile -Force
|
||||
$ApidocWarningsAndErrors = [System.Collections.ArrayList]::new()
|
||||
foreach($Item in Get-Childitem -path $PkgSrcPath){
|
||||
if(-not ($IncludeList -contains $Item.Name)){
|
||||
continue
|
||||
}
|
||||
# Build API reference doc
|
||||
$SubPkgPath = [System.IO.Path]::Combine($Item.FullName, "promptflow")
|
||||
$SubPkgRefDocPath = [System.IO.Path]::Combine($RefDocPath, $Item.Name)
|
||||
Write-Host "===============Build $Item Reference Doc==============="
|
||||
$TemplatePath = [System.IO.Path]::Combine($RepoRootPath, "scripts\docs\api_doc_templates")
|
||||
sphinx-apidoc --separate --module-first --no-toc --implicit-namespaces "$SubPkgPath" -o "$SubPkgRefDocPath" -t $TemplatePath | Tee-Object -FilePath $SphinxApiDoc
|
||||
$SubPkgWarningsAndErrors = Select-String -Path $SphinxApiDoc -Pattern $WarningErrorPattern
|
||||
if($SubPkgWarningsAndErrors){
|
||||
$ApidocWarningsAndErrors.AddRange($SubPkgWarningsAndErrors)
|
||||
}
|
||||
Update-Sub-Pkg-Index-Title $SubPkgRefDocPath $Item.Name
|
||||
}
|
||||
}
|
||||
|
||||
function Add-Metadata{
|
||||
param (
|
||||
[string] $NotebookPath,
|
||||
[string] $NotebookRepoPath,
|
||||
[System.Collections.ArrayList] $AuthorList
|
||||
)
|
||||
if (-not $AuthorList){
|
||||
# Skip insert if author list not set
|
||||
throw "Skip Add Metadata: $NotebookPath - Author list not set"
|
||||
return
|
||||
}
|
||||
$NotebookContent = Get-Content $NotebookPath -Raw | ConvertFrom-Json
|
||||
# Covert to System.Collections.ArrayList to avoid 'Collection was of a fixed size' error.
|
||||
$NotebookContent.cells = [System.Collections.ArrayList]::new($NotebookContent.cells)
|
||||
if($NotebookContent.cells[0].source.Length -gt 1){
|
||||
# If the first cell length > 1, indicate there are more things than title it self in the first cell
|
||||
throw "Skip Add Metadata: $NotebookPath - First cell length > 1, only leave title to that cell."
|
||||
return
|
||||
}
|
||||
$MetadataFormat = "Authored by: {0}{1}"
|
||||
$SingleAuthor = " <a href='https://github.com/{0}' target='_blank'><img src='https://github.com/{0}.png' alt='Avatar' class='avatar dark-light'></a>"
|
||||
$JumpLink = "<a href='{0}' target='_blank'><img decoding='async' loading='lazy' src='https://img.shields.io/badge/Open%20on%20GitHub-grey?logo=github' alt='Open on GitHub' class='img_ev3q' style='float: right;'></a>" -f $NotebookRepoPath
|
||||
$Authors = $AuthorList | ForEach-Object { $SingleAuthor -f $_.replace("@github.com", "") }
|
||||
$Metadata = $MetadataFormat -f ($Authors -join ""), $JumpLink
|
||||
# Insert metadata to cells
|
||||
$MetadataCell = @{
|
||||
"cell_type" = "markdown";
|
||||
"metadata" = @{};
|
||||
"source" = @($Metadata)
|
||||
}
|
||||
$NotebookContent.cells.Insert(1, $MetadataCell)
|
||||
$NotebookContent | ConvertTo-Json -Depth 100 | Set-Content $NotebookPath
|
||||
}
|
||||
|
||||
function Add-Notebook
|
||||
{
|
||||
Write-Host "===============Collect Package Notebooks==============="
|
||||
$NotebookRootPath = [System.IO.Path]::Combine($RepoRootPath, "examples")
|
||||
$TargetNotebookPath = [System.IO.Path]::Combine($TempDocPath, "tutorials")
|
||||
# Create section list
|
||||
$SectionNames = "Tracing", "Prompty", "Flow", "Rag"
|
||||
$Sections = [ordered]@{
|
||||
Tracing=[System.Collections.ArrayList]::new();
|
||||
Prompty=[System.Collections.ArrayList]::new();
|
||||
Flow=[System.Collections.ArrayList]::new()
|
||||
Rag=[System.Collections.ArrayList]::new()
|
||||
}
|
||||
foreach($Item in Get-Childitem -path $NotebookRootPath -Recurse -Filter "*.ipynb")
|
||||
{
|
||||
# Notebook to build must have metadata: {"build_doc": {"category": "local/azure"}}
|
||||
$NotebookContent = Get-Content $Item.FullName -Raw | ConvertFrom-Json
|
||||
if(-not $NotebookContent.metadata.build_doc){
|
||||
continue
|
||||
}
|
||||
$RepoPath = $Item.FullName.Replace($RepoRootPath, "https://github.com/microsoft/promptflow/tree/main/")
|
||||
$SectionName = $NotebookContent.metadata.build_doc.section
|
||||
[int]$Weight = $NotebookContent.metadata.build_doc.weight
|
||||
$Category = $NotebookContent.metadata.build_doc.category
|
||||
$AuthorList = $NotebookContent.metadata.build_doc.author
|
||||
# If category is 'azure', add 1000 to weight
|
||||
if($Category -eq "azure"){
|
||||
$Weight += 1000
|
||||
}
|
||||
# Add ItemName, Category tuple to sections
|
||||
$Sections[$SectionName].Add([Tuple]::Create($Item.Name.Replace(".ipynb", ""), $Weight))
|
||||
# Copy notebook to doc path
|
||||
Write-Host "Adding Notebook $Item ..."
|
||||
$MediaDir = $Item.FullName + '\..\media'
|
||||
Copy-Item -Path $Item.FullName -Destination $TargetNotebookPath
|
||||
if(Test-Path $MediaDir){
|
||||
# copy image referenced in notebook
|
||||
Write-Host "Copying media files from $MediaDir ..."
|
||||
Copy-Item -Path $MediaDir -Destination $TargetNotebookPath -Recurse -Force
|
||||
}
|
||||
# Append metadata to notebook
|
||||
$CopiedNotebookPath = [System.IO.Path]::Combine($TargetNotebookPath, $Item.Name)
|
||||
Add-Metadata $CopiedNotebookPath $RepoPath $AuthorList
|
||||
}
|
||||
# Reverse sort each section list by Weight
|
||||
foreach($SectionName in $SectionNames){
|
||||
$Sections[$SectionName] = $Sections[$SectionName] | Sort-Object -Property { $_.Item2 }
|
||||
}
|
||||
$TocTreeContent = @("", "``````{{toctree}}", ":caption: {0}", ":hidden:", ":maxdepth: 1", "", "{1}", "``````")
|
||||
# Build toctree content for each section, append to tutorials index.md
|
||||
$TutorialIndex = [System.IO.Path]::Combine($TargetNotebookPath, "index.md")
|
||||
foreach($SectionName in $SectionNames){
|
||||
$SectionTocTree = $TocTreeContent -join "`n"
|
||||
# Join Item1 to a string in list
|
||||
$ExampleList = ($Sections[$SectionName] | ForEach-Object { $_.Item1 }) -join "`n"
|
||||
$SectionTocTree = $SectionTocTree -f $SectionName, $ExampleList
|
||||
Write-Debug $SectionTocTree
|
||||
Add-Content -Path $TutorialIndex -Value $SectionTocTree
|
||||
}
|
||||
}
|
||||
|
||||
if($WithReferenceDoc){
|
||||
Add-Api-Reference
|
||||
}
|
||||
# Build subpackage changelog
|
||||
Add-Changelog
|
||||
# Build notebook examples
|
||||
Add-Notebook
|
||||
|
||||
Write-Host "===============Build Documentation with internal=${Internal}==============="
|
||||
$BuildParams = [System.Collections.ArrayList]::new()
|
||||
if($WarningAsError){
|
||||
$BuildParams.Add("-W")
|
||||
$BuildParams.Add("--keep-going")
|
||||
}
|
||||
if($BuildLinkCheck){
|
||||
$BuildParams.Add("-blinkcheck")
|
||||
}
|
||||
sphinx-build $TempDocPath $OutPath -c $ScriptPath $BuildParams -v | Tee-Object -FilePath $SphinxBuildDoc
|
||||
$buildWarningsAndErrors = Select-String -Path $SphinxBuildDoc -Pattern $WarningErrorPattern
|
||||
|
||||
Write-Host "Clean path: $TempDocPath"
|
||||
Remove-Item $TempDocPath -Recurse -Confirm:$False -Force
|
||||
|
||||
|
||||
if ($buildWarningsAndErrors) {
|
||||
Write-Host "=============== Build warnings and errors ==============="
|
||||
foreach ($line in $buildWarningsAndErrors) {
|
||||
Write-Host $line -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
"""A directive to generate a gallery of images from structured data.
|
||||
Generating a gallery of images that are all the same size is a common
|
||||
pattern in documentation, and this can be cumbersome if the gallery is
|
||||
generated programmatically. This directive wraps this particular use-case
|
||||
in a helper-directive to generate it with a single YAML configuration file.
|
||||
It currently exists for maintainers of the pydata-sphinx-theme,
|
||||
but might be abstracted into a standalone package if it proves useful.
|
||||
"""
|
||||
from yaml import safe_load
|
||||
from typing import List
|
||||
from pathlib import Path
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
TEMPLATE_GRID = """
|
||||
`````{{grid}} {grid_columns}
|
||||
{container_options}
|
||||
{content}
|
||||
`````
|
||||
"""
|
||||
|
||||
GRID_CARD = """
|
||||
````{{grid-item-card}} {title}
|
||||
{card_options}
|
||||
{content}
|
||||
````
|
||||
"""
|
||||
|
||||
|
||||
class GalleryDirective(SphinxDirective):
|
||||
"""A directive to show a gallery of images and links in a grid."""
|
||||
|
||||
name = "gallery-grid"
|
||||
has_content = True
|
||||
required_arguments = 0
|
||||
optional_arguments = 1
|
||||
final_argument_whitespace = True
|
||||
option_spec = {
|
||||
# A class to be added to the resulting container
|
||||
"grid-columns": directives.unchanged,
|
||||
"class-container": directives.unchanged,
|
||||
"class-card": directives.unchanged,
|
||||
}
|
||||
|
||||
def run(self) -> List[nodes.Node]: # noqa: C901
|
||||
if self.arguments:
|
||||
# If an argument is given, assume it's a path to a YAML file
|
||||
# Parse it and load it into the directive content
|
||||
path_data_rel = Path(self.arguments[0])
|
||||
path_doc, _ = self.get_source_info()
|
||||
path_doc = Path(path_doc).parent
|
||||
path_data = (path_doc / path_data_rel).resolve()
|
||||
if not path_data.exists():
|
||||
logger.warn(f"Could not find grid data at {path_data}.")
|
||||
nodes.text("No grid data found at {path_data}.")
|
||||
return
|
||||
yaml_string = path_data.read_text()
|
||||
else:
|
||||
yaml_string = "\n".join(self.content)
|
||||
|
||||
# Read in YAML so we can generate the gallery
|
||||
grid_data = safe_load(yaml_string)
|
||||
|
||||
grid_items = []
|
||||
for item in grid_data:
|
||||
# Grid card parameters
|
||||
options = {}
|
||||
if "website" in item:
|
||||
options["link"] = item["website"]
|
||||
|
||||
if "class-card" in self.options:
|
||||
options["class-card"] = self.options["class-card"]
|
||||
|
||||
if "img-background" in item:
|
||||
options["img-background"] = item["img-background"]
|
||||
|
||||
if "img-top" in item:
|
||||
options["img-top"] = item["img-top"]
|
||||
|
||||
if "img-bottom" in item:
|
||||
options["img-bottom"] = item["img-bottom"]
|
||||
|
||||
options_str = "\n".join(f":{k}: {v}" for k, v in options.items()) + "\n\n"
|
||||
|
||||
# Grid card content
|
||||
content_str = ""
|
||||
if "header" in item:
|
||||
content_str += f"{item['header']}\n\n^^^\n\n"
|
||||
|
||||
if "image" in item:
|
||||
content_str += f"\n\n"
|
||||
|
||||
if "content" in item:
|
||||
content_str += f"{item['content']}\n\n"
|
||||
|
||||
if "footer" in item:
|
||||
content_str += f"+++\n\n{item['footer']}\n\n"
|
||||
|
||||
title = item.get("title", "")
|
||||
content_str += "\n"
|
||||
grid_items.append(
|
||||
GRID_CARD.format(
|
||||
card_options=options_str, content=content_str, title=title
|
||||
)
|
||||
)
|
||||
|
||||
# Parse the template with Sphinx Design to create an output
|
||||
container = nodes.container()
|
||||
# Prep the options for the template grid
|
||||
container_options = {"gutter": 2, "class-container": "gallery-directive"}
|
||||
if "class-container" in self.options:
|
||||
container_options[
|
||||
"class-container"
|
||||
] += f' {self.options["class-container"]}'
|
||||
container_options_str = "\n".join(
|
||||
f":{k}: {v}" for k, v in container_options.items()
|
||||
)
|
||||
|
||||
# Create the directive string for the grid
|
||||
grid_directive = TEMPLATE_GRID.format(
|
||||
grid_columns=self.options.get("grid-columns", "1 2 3 4"),
|
||||
container_options=container_options_str,
|
||||
content="\n".join(grid_items),
|
||||
)
|
||||
# Parse content as a directive so Sphinx Design processes it
|
||||
self.state.nested_parse([grid_directive], 0, container)
|
||||
# Sphinx Design outputs a container too, so just use that
|
||||
container = container.children[0]
|
||||
|
||||
# Add extra classes
|
||||
if self.options.get("container-class", []):
|
||||
container.attributes["classes"] += self.options.get("class", [])
|
||||
return [container]
|
||||
Reference in New Issue
Block a user