بهروزرسانی: دریافت زندهٔ کاتالوگ مدلها و افورتهای استدلال پشتیبانیشده بر اساس اکانت انتخابی
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
effortLabel,
|
||||
type AdminModel,
|
||||
type AgyAccount,
|
||||
type AgyAccountModel,
|
||||
type Capability,
|
||||
type ReasoningEffort,
|
||||
} from "@agy/contracts";
|
||||
@@ -29,8 +30,8 @@ import { ApiError, api } from "@/lib/api";
|
||||
*
|
||||
* agy is the only provider, and nothing about a model is typed by hand: the
|
||||
* console asks the selected *account* for its live catalogue, the owner picks a
|
||||
* model and a reasoning effort, and the rest is metadata. The model id itself
|
||||
* never leaves the console — a customer only ever sees routing choices.
|
||||
* model and a reasoning effort supported by that model, and the rest is metadata.
|
||||
* The model id itself never leaves the console — a customer only ever sees routing choices.
|
||||
*/
|
||||
|
||||
const CAPABILITIES: Capability[] = ["text", "vision", "tools", "reasoning", "long_context", "code"];
|
||||
@@ -47,7 +48,7 @@ export default function AdminModelsPage() {
|
||||
// The add-model cascade: provider -> account -> model -> effort.
|
||||
const [providerId, setProviderId] = React.useState("agy");
|
||||
const [accountId, setAccountId] = React.useState("");
|
||||
const [catalog, setCatalog] = React.useState<string[] | null>(null);
|
||||
const [catalog, setCatalog] = React.useState<AgyAccountModel[] | null>(null);
|
||||
const [catalogLoading, setCatalogLoading] = React.useState(false);
|
||||
const [catalogError, setCatalogError] = React.useState<string | null>(null);
|
||||
const [modelId, setModelId] = React.useState("");
|
||||
@@ -135,14 +136,27 @@ export default function AdminModelsPage() {
|
||||
|
||||
const onModelChange = (value: string) => {
|
||||
setModelId(value);
|
||||
setEffort("");
|
||||
// Sensible defaults the owner can still adjust: everything answers text,
|
||||
// and a thinking-capable model is a reasoning model.
|
||||
setCaps(
|
||||
effortsForModel(value).length > 0
|
||||
? ["text", "reasoning"]
|
||||
: ["text"],
|
||||
);
|
||||
const selected = (catalog ?? []).find((m) => m.id === value);
|
||||
const supported = selected ? selected.supported_efforts : effortsForModel(value);
|
||||
|
||||
// Pick default effort if supported by this model
|
||||
if (selected?.default_effort && supported.includes(selected.default_effort)) {
|
||||
setEffort(selected.default_effort);
|
||||
} else if (supported.length > 0) {
|
||||
setEffort(supported.includes("high") ? "high" : supported[0]);
|
||||
} else {
|
||||
setEffort("");
|
||||
}
|
||||
|
||||
// Auto-detect capabilities based on agy model metadata
|
||||
const nextCaps: Capability[] = ["text"];
|
||||
if (selected?.supports_thinking || supported.length > 0) {
|
||||
nextCaps.push("reasoning");
|
||||
}
|
||||
if (selected?.supports_images) {
|
||||
nextCaps.push("vision");
|
||||
}
|
||||
setCaps(nextCaps);
|
||||
};
|
||||
|
||||
const toggleCap = (cap: Capability) => {
|
||||
@@ -162,10 +176,12 @@ export default function AdminModelsPage() {
|
||||
setFormError("حداقل یک توانایی انتخاب کنید.");
|
||||
return;
|
||||
}
|
||||
const selectedModel = (catalog ?? []).find((m) => m.id === modelId);
|
||||
setCreating(true);
|
||||
try {
|
||||
const created = await api.adminCreateModel({
|
||||
internal_name: modelId,
|
||||
display_name_for_admin: selectedModel?.display_name || modelId,
|
||||
capabilities: caps,
|
||||
input_price_per_1m: Number(inputPrice) || 0,
|
||||
output_price_per_1m: Number(outputPrice) || 0,
|
||||
@@ -184,13 +200,24 @@ export default function AdminModelsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const efforts: ReasoningEffort[] = modelId ? effortsForModel(modelId) : [];
|
||||
const selectedModel = (catalog ?? []).find((m) => m.id === modelId);
|
||||
const efforts: ReasoningEffort[] = selectedModel
|
||||
? selectedModel.supported_efforts
|
||||
: modelId
|
||||
? effortsForModel(modelId)
|
||||
: [];
|
||||
const accountOptions = accounts.map((a) => ({
|
||||
value: a.id,
|
||||
label: a.email || a.name || a.id,
|
||||
}));
|
||||
const modelOptions = (catalog ?? []).map((id) => ({ value: id, label: id }));
|
||||
const effortOptions = efforts.map((e) => ({ value: e, label: effortLabel(e) }));
|
||||
const modelOptions = (catalog ?? []).map((m) => ({
|
||||
value: m.id,
|
||||
label: m.display_name && m.display_name !== m.id ? `${m.display_name} (${m.id})` : m.id,
|
||||
}));
|
||||
const effortOptions = [
|
||||
{ value: "", label: "پیشفرض سامانه" },
|
||||
...efforts.map((e) => ({ value: e, label: effortLabel(e) })),
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="anim-stagger flex flex-col gap-5">
|
||||
@@ -251,12 +278,18 @@ export default function AdminModelsPage() {
|
||||
label="افورت استدلال"
|
||||
value={effort}
|
||||
onChange={(e) => setEffort(e.target.value)}
|
||||
options={effortOptions}
|
||||
disabled={efforts.length === 0}
|
||||
options={
|
||||
!modelId
|
||||
? [{ value: "", label: "ابتدا یک مدل انتخاب کنید" }]
|
||||
: efforts.length === 0
|
||||
? [{ value: "", label: "این مدل از افورت استدلال پشتیبانی نمیکند" }]
|
||||
: effortOptions
|
||||
}
|
||||
disabled={!modelId || efforts.length === 0}
|
||||
hint={
|
||||
efforts.length === 0
|
||||
? "این مدل افورت استدلال ندارد."
|
||||
: "بودجهٔ تفکر مدل؛ روی مدلهای غیراستدلالی نادیده گرفته میشود."
|
||||
? "این مدل افورت استدلال ندارد (مدل غیراستدلالی یا با استدلال ثابت)."
|
||||
: "افورتهای استدلال پشتیبانیشدهٔ همین مدل در agy."
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user