Skip to content
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion sdk/agenta/sdk/middleware/config.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In new workflows, there will be a proper place to send references.
In legacy applications, I'd discourage from sending agenta-related information via the body other than ag_config. But since this interface is not meant to live for long, I don't mind.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we use the same interface for the environment, no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is how it looks like for environment

# Add your API key to the Authorization header
curl -X POST "https://cloud.agenta.ai/services/completion/run" \
-H "Content-Type: application/json" \
-H "Authorization: ApiKey V7CDlfpn.4a28e99bf7ef0cc9ebb4692ba9039de74d71ce67138ec411f70cc2651d5bbaf9" \
-d '{
  "environment": "development",
  "app": "prompt"
}'

Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ async def _parse_variant_ref(
baggage.get("ag.refs.variant.slug")
# ALTERNATIVE
or request.query_params.get("variant_slug")
or body.get("variant_slug")
# LEGACY
or baggage.get("variant_slug")
or request.query_params.get("config")
Expand All @@ -234,6 +235,7 @@ async def _parse_variant_ref(
baggage.get("ag.refs.variant.version")
# ALTERNATIVE
or request.query_params.get("variant_version")
or body.get("variant_version")
# LEGACY
or baggage.get("variant_version")
)
Expand All @@ -244,7 +246,7 @@ async def _parse_variant_ref(
return Reference(
id=variant_id,
slug=variant_slug,
version=variant_version,
version=str(variant_version) if variant_version is not None else None,
)

async def _parse_environment_ref(
Expand Down
9 changes: 4 additions & 5 deletions web/oss/src/code_snippets/endpoints/fetch_config/python.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import {getEnv} from "@/oss/lib/helpers/dynamicEnv"

export default function pythonCode(appName: string, env_name: string, apiKey: string): string {
return `
import os
return `import os
import agenta as ag

os.environ["AGENTA_API_KEY"] = "${apiKey}" # Add your API key here
os.environ["AGENTA_API_KEY"] = "${apiKey}"
os.environ["AGENTA_HOST"] = "${getEnv("NEXT_PUBLIC_AGENTA_API_URL")}"

ag.init()
config = ag.ConfigManager.get_from_registry(
app_slug="${appName}",
environment_slug="${env_name}"
)
environment_slug="${env_name}",
)
print(config)
`
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const getConfig = async (appName: string, environmentSlug: string) => {
},
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': "ApiKey ${apiKey}", // Add your API key here
'Content-Type': 'application/json',
'Authorization': "ApiKey ${apiKey}",
},
});

Expand Down
7 changes: 4 additions & 3 deletions web/oss/src/code_snippets/endpoints/fetch_variant/curl.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {getEnv} from "@/oss/lib/helpers/dynamicEnv"

export const buildCurlSnippet = (
appSlug: string,
variantSlug: string,
variantVersion: number,
apiKey: string,
) => {
return `# Fetch configuration by variant
curl -X POST "https://cloud.agenta.ai/api/variants/configs/fetch" \\
return `curl -X POST "${getEnv("NEXT_PUBLIC_AGENTA_API_URL")}/variants/configs/fetch" \\
-H "Content-Type: application/json" \\
-H "Authorization: Bearer ${apiKey}" \\
-H "Authorization: ApiKey ${apiKey}" \\
-d '{
"variant_ref": {
"slug": "${variantSlug}",
Expand Down
5 changes: 2 additions & 3 deletions web/oss/src/code_snippets/endpoints/fetch_variant/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ export const buildPythonSnippet = (
variantSlug: string,
variantVersion: number,
) => {
return `# Fetch configuration by variant
import agenta as ag
return `import agenta as ag
config = ag.ConfigManager.get_from_registry(
app_slug="${appSlug}",
variant_slug="${variantSlug}",
variant_version=${variantVersion} # Optional: If not provided, fetches the latest version
variant_version=${variantVersion},
)
print("Fetched configuration:")
Expand Down
33 changes: 17 additions & 16 deletions web/oss/src/code_snippets/endpoints/fetch_variant/typescript.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import {getEnv} from "@/oss/lib/helpers/dynamicEnv"

export const buildTypescriptSnippet = (
appSlug: string,
variantSlug: string,
variantVersion: number,
apiKey: string,
) => {
return `// Fetch configuration by variant
const fetchResponse = await fetch('https://cloud.agenta.ai/api/variants/configs/fetch', {
return `const fetchResponse = await fetch('${getEnv("NEXT_PUBLIC_AGENTA_API_URL")}/variants/configs/fetch', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${apiKey}'
'Authorization': 'ApiKey ${apiKey}',
},
body: JSON.stringify({
variant_ref: {
slug: '${variantSlug}',
version: ${variantVersion},
id: null
slug: '${variantSlug}',
version: ${variantVersion},
id: null,
},
application_ref: {
slug: '${appSlug}',
version: null,
id: null
}
})
});
slug: '${appSlug}',
version: null,
id: null,
},
}),
});

const config = await fetchResponse.json();
console.log('Fetched configuration:');
console.log(config);
`
const config = await fetchResponse.json();
console.log('Fetched configuration:');
console.log(config);
`
}
5 changes: 2 additions & 3 deletions web/oss/src/code_snippets/endpoints/invoke_llm_app/curl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ export default function cURLCode(uri: string, params: string, apiKey: string): s
const parsedParams = JSON.parse(params)
const isChat = parsedParams.messages !== undefined

return `# Add your API key to the Authorization header
curl -X POST "${uri}" \\
return `curl -X POST "${uri}" \\
-H "Content-Type: application/json" \\
-H "Authorization: ApiKey ${apiKey}" \\${isChat ? '\n-H "Baggage: ag.session.id=your_session_id" \\ # Optional: track chat sessions' : ""}
-H "Authorization: ApiKey ${apiKey}" \\${isChat ? '\n-H "Baggage: ag.session.id=your_session_id" \\' : ""}
-d '${params}'
`
}
4 changes: 2 additions & 2 deletions web/oss/src/code_snippets/endpoints/invoke_llm_app/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import json
url = "${uri}"
params = ${params}
headers = {
"Content-Type": "application/json",
"Authorization": "ApiKey ${apiKey}", # Add your API key here${isChat ? '\n "Baggage": "ag.session.id=your_session_id", # Optional: track chat sessions' : ""}
"Content-Type": "application/json",
"Authorization": "ApiKey ${apiKey}",${isChat ? '\n "Baggage": "ag.session.id=your_session_id",' : ""}
}

response = requests.post(url, json=params, headers=headers)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const generate = async () => {
const data = ${params};
const headers = {
"Content-Type": "application/json",
"Authorization": "ApiKey ${apiKey}", // Add your API key here${isChat ? '\n "Baggage": "ag.session.id=your_session_id" // Optional: track chat sessions' : ""}
"Authorization": "ApiKey ${apiKey}",${isChat ? '\n "Baggage": "ag.session.id=your_session_id",' : ""}
};

const response = await axios.post(url, data, { headers });
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import {useCallback, useEffect, useMemo, useState} from "react"

import {PythonOutlined} from "@ant-design/icons"
import {FileCodeIcon, FileTsIcon} from "@phosphor-icons/react"
import {Tabs, Typography} from "antd"
import {FileCode, FileTs} from "@phosphor-icons/react"
import {Spin, Tabs, Typography} from "antd"
import {useAtomValue} from "jotai"
import dynamic from "next/dynamic"

import {buildCurlSnippet} from "@/oss/code_snippets/endpoints/fetch_variant/curl"
import {buildPythonSnippet} from "@/oss/code_snippets/endpoints/fetch_variant/python"
import {buildTypescriptSnippet} from "@/oss/code_snippets/endpoints/fetch_variant/typescript"
import CopyButton from "@/oss/components/CopyButton/CopyButton"
import CodeBlock from "@/oss/components/DynamicCodeBlock/CodeBlock"
import invokeLlmAppcURLCode from "@/oss/code_snippets/endpoints/invoke_llm_app/curl"
import invokeLlmApppythonCode from "@/oss/code_snippets/endpoints/invoke_llm_app/python"
import invokeLlmApptsCode from "@/oss/code_snippets/endpoints/invoke_llm_app/typescript"
import LanguageCodeBlock from "@/oss/components/pages/overview/deployments/DeploymentDrawer/assets/LanguageCodeBlock"
import SelectVariant from "@/oss/components/Playground/Components/Menus/SelectVariant"
import VariantDetailsWithStatus from "@/oss/components/VariantDetailsWithStatus"
import {currentAppAtom} from "@/oss/state/app"
import {useAppId} from "@/oss/hooks/useAppId"
import {currentAppAtom, useURI} from "@/oss/state/app"
import {stablePromptVariablesAtomFamily} from "@/oss/state/newPlayground/core/prompts"
import {revisionsByVariantIdAtomFamily, variantsAtom} from "@/oss/state/variant/atoms/fetcher"
import {
latestRevisionInfoByVariantIdAtomFamily,
Expand All @@ -29,13 +33,8 @@ interface VariantUseApiContentProps {
initialRevisionId?: string
}

interface CodeSnippets {
python: string
typescript: string
bash: string
}

const VariantUseApiContent = ({initialRevisionId}: VariantUseApiContentProps) => {
const appId = useAppId()
const variants = useAtomValue(variantsAtom)
const revisionList = useAtomValue(revisionListAtom)
const currentApp = useAtomValue(currentAppAtom)
Expand All @@ -45,6 +44,15 @@ const VariantUseApiContent = ({initialRevisionId}: VariantUseApiContentProps) =>
const [selectedLang, setSelectedLang] = useState("python")
const [apiKeyValue, setApiKeyValue] = useState("")

// Get URI for the selected variant
const {data: uri, isLoading: isUriQueryLoading} = useURI(appId, selectedVariantId)
const isLoading = Boolean(selectedVariantId) && isUriQueryLoading

// Get variable names for the selected revision
const variableNames = useAtomValue(
stablePromptVariablesAtomFamily(selectedRevisionId || ""),
) as string[]

const initialRevision = useMemo(
() => revisionList.find((rev) => rev.id === initialRevisionId),
[initialRevisionId, revisionList],
Expand Down Expand Up @@ -120,13 +128,52 @@ const VariantUseApiContent = ({initialRevisionId}: VariantUseApiContentProps) =>
const variantSlug =
(selectedVariant as any)?.variantSlug ||
selectedVariant?.variantName ||
selectedRevision?.variantName ||
(selectedRevision as any)?.variantName ||
"my-variant-slug"
const variantVersion = selectedRevision?.revision ?? latestRevision?.revision ?? 1
const appSlug = (currentApp as any)?.app_slug || currentApp?.app_name || "my-app-slug"
const apiKey = apiKeyValue || "YOUR_API_KEY"

const codeSnippets: CodeSnippets = useMemo(
const invokeLlmUrl = uri ?? ""

// Build params for invoke LLM (with variant refs instead of environment)
const params = useMemo(() => {
const synthesized = variableNames.map((name) => ({name, input: name === "messages"}))

const mainParams: Record<string, any> = {}
const secondaryParams: Record<string, any> = {}

synthesized.forEach((item) => {
if (item.input) {
mainParams[item.name] = "add_a_value"
} else {
secondaryParams[item.name] = "add_a_value"
}
})

const hasMessagesParam = synthesized.some((p) => p?.name === "messages")
const isChat = currentApp?.app_type === "chat" || hasMessagesParam
if (isChat) {
mainParams["messages"] = [
{
role: "user",
content: "",
},
]
mainParams["inputs"] = secondaryParams
} else if (Object.keys(secondaryParams).length > 0) {
mainParams["inputs"] = secondaryParams
}

// Use variant refs instead of environment
mainParams["app"] = appSlug
mainParams["variant_slug"] = variantSlug
mainParams["variant_version"] = variantVersion

return JSON.stringify(mainParams, null, 2)
}, [variableNames, currentApp?.app_type, appSlug, variantSlug, variantVersion])

const fetchConfigCodeSnippet = useMemo(
() => ({
python: buildPythonSnippet(appSlug, variantSlug, variantVersion),
typescript: buildTypescriptSnippet(appSlug, variantSlug, variantVersion, apiKey),
Expand All @@ -135,48 +182,48 @@ const VariantUseApiContent = ({initialRevisionId}: VariantUseApiContentProps) =>
[apiKey, appSlug, variantSlug, variantVersion],
)

const renderTabChildren = useCallback(() => {
const activeSnippet = codeSnippets[selectedLang as keyof CodeSnippets]
const invokeLlmAppCodeSnippet = useMemo(
() => ({
python: invokeLlmApppythonCode(invokeLlmUrl, params, apiKeyValue || "x.xxxxxxxx"),
bash: invokeLlmAppcURLCode(invokeLlmUrl, params, apiKeyValue || "x.xxxxxxxx"),
typescript: invokeLlmApptsCode(invokeLlmUrl, params, apiKeyValue || "x.xxxxxxxx"),
}),
[apiKeyValue, invokeLlmUrl, params],
)

const renderTabChildren = useCallback(() => {
return (
<div className="flex flex-col gap-3">
<div className="flex items-center justify-between">
<Typography.Text className="font-medium">Use API</Typography.Text>
<CopyButton text={activeSnippet} icon={true} buttonText={null} />
</div>
<CodeBlock language={selectedLang} value={activeSnippet} />
</div>
<Spin spinning={isLoading}>
<LanguageCodeBlock
fetchConfigCodeSnippet={fetchConfigCodeSnippet}
invokeLlmAppCodeSnippet={invokeLlmAppCodeSnippet}
selectedLang={selectedLang}
handleOpenSelectDeployVariantModal={() => {}}
invokeLlmUrl={invokeLlmUrl}
/>
</Spin>
)
}, [
apiKeyValue,
codeSnippets,
revisionList,
selectedLang,
selectedRevision?.id,
selectedRevision?.isLatestRevision,
selectedRevision?.revision,
selectedRevisionId,
])
}, [fetchConfigCodeSnippet, invokeLlmAppCodeSnippet, invokeLlmUrl, isLoading, selectedLang])

const tabItems = useMemo(
() => [
{
key: "python",
label: "Python",
icon: <PythonOutlined />,
children: renderTabChildren(),
icon: <PythonOutlined />,
},
{
key: "typescript",
label: "TypeScript",
icon: <FileTsIcon size={14} />,
children: renderTabChildren(),
icon: <FileTs size={14} />,
},
{
key: "bash",
label: "cURL",
icon: <FileCodeIcon size={14} />,
children: renderTabChildren(),
icon: <FileCode size={14} />,
},
],
[renderTabChildren],
Expand Down Expand Up @@ -221,10 +268,10 @@ const VariantUseApiContent = ({initialRevisionId}: VariantUseApiContentProps) =>
<ApiKeyInput apiKeyValue={apiKeyValue} onApiKeyChange={setApiKeyValue} />
</div>
<Tabs
destroyOnHidden
defaultActiveKey={selectedLang}
items={tabItems}
onChange={setSelectedLang}
activeKey={selectedLang}
destroyInactiveTabPane
/>
</div>
)
Expand Down