mirror of
https://github.com/msoedov/agentic_security.git
synced 2026-09-30 19:59:34 +02:00
feat(add new spec samples):
This commit is contained in:
1 parent
9189b52453
commit
59c45d2281
6 files changed
+77
-10
No files matched your search
@@ -1,9 +1,17 @@
|
|||||||
|
import base64
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
class InvalidHTTPSpecError(Exception):
|
def encode_image_base64_by_url(url: str = "https://github.com/fluidicon.png") -> str:
|
||||||
...
|
"""Encode image data to base64 from a URL"""
|
||||||
|
response = httpx.get(url)
|
||||||
|
encoded_content = base64.b64encode(response.content).decode("utf-8")
|
||||||
|
return "data:image/jpeg;base64," + encoded_content
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidHTTPSpecError(Exception): ...
|
||||||
|
|
||||||
|
|
||||||
class LLMSpec(BaseModel):
|
class LLMSpec(BaseModel):
|
||||||
@@ -72,6 +80,15 @@ class LLMSpec(BaseModel):
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
async def verify(self) -> httpx.Response:
|
||||||
|
match self:
|
||||||
|
case LLMSpec(has_image=True):
|
||||||
|
return await self.probe("test", encode_image_base64_by_url())
|
||||||
|
case LLMSpec(has_files=True):
|
||||||
|
return await self._probe_with_files({})
|
||||||
|
case _:
|
||||||
|
return await self.probe("test prompt")
|
||||||
|
|
||||||
fn = probe
|
fn = probe
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ router = APIRouter()
|
|||||||
@router.post("/verify")
|
@router.post("/verify")
|
||||||
async def verify(info: LLMInfo):
|
async def verify(info: LLMInfo):
|
||||||
spec = LLMSpec.from_string(info.spec)
|
spec = LLMSpec.from_string(info.spec)
|
||||||
r = await spec.probe("test")
|
r = await spec.verify()
|
||||||
if r.status_code >= 400:
|
if r.status_code >= 400:
|
||||||
raise HTTPException(status_code=r.status_code, detail=r.text)
|
raise HTTPException(status_code=r.status_code, detail=r.text)
|
||||||
return dict(
|
return dict(
|
||||||
|
|||||||
@@ -64,5 +64,36 @@ Content-Type: application/json
|
|||||||
{"role": "user", "content": "<<PROMPT>>"}
|
{"role": "user", "content": "<<PROMPT>>"}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
`,
|
||||||
|
`POST ${URL}/v1/self-probe-image
|
||||||
|
Authorization: Bearer XXXXX
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"role": "user",
|
||||||
|
"content": [
|
||||||
|
{
|
||||||
|
"type": "text",
|
||||||
|
"text": "What is in this image?",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "image_url",
|
||||||
|
"image_url": {
|
||||||
|
"url": f"data:image/jpeg;base64,{<<BASE64_IMAGE>>}"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
`,
|
||||||
|
`POST ${URL}/v1/self-probe-file
|
||||||
|
Authorization: Bearer $GROQ_API_KEY
|
||||||
|
Content-Type: multipart/form-data
|
||||||
|
|
||||||
|
{
|
||||||
|
"file": "@./sample_audio.m4a",
|
||||||
|
"model": "whisper-large-v3"
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
]
|
]
|
||||||
@@ -34,17 +34,23 @@
|
|||||||
[[% include "partials/concent.html" %]]
|
[[% include "partials/concent.html" %]]
|
||||||
|
|
||||||
<main class="max-w-6xl mx-auto space-y-8">
|
<main class="max-w-6xl mx-auto space-y-8">
|
||||||
<!-- Config Selection -->
|
|
||||||
<section class="bg-dark-card rounded-lg p-6 shadow-lg">
|
<section class="bg-dark-card rounded-lg p-6 shadow-lg">
|
||||||
<h2 class="text-2xl font-bold mb-4">Select a Config</h2>
|
<h2 class="text-2xl font-bold mb-4">Select a Config</h2>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
|
||||||
<div v-for="(config, index) in configs" :key="index"
|
<div class="flex space-x-4 overflow-x-auto scrollbar-hide">
|
||||||
|
<div
|
||||||
|
v-for="(config, index) in configs"
|
||||||
|
:key="index"
|
||||||
@click="selectConfig(index)"
|
@click="selectConfig(index)"
|
||||||
class="border-2 rounded-lg p-4 flex flex-col items-start transition-all hover:shadow-md cursor-pointer"
|
class="flex-none w-1/2 sm:w-1/3 md:w-1/4 lg:w-1/5 border-2 rounded-lg p-4 flex flex-col items-start transition-all hover:shadow-md cursor-pointer"
|
||||||
:class="{'border-dark-accent-green': selectedConfig === index, 'border-gray-600': selectedConfig !== index}">
|
:class="{
|
||||||
|
'border-dark-accent-green': selectedConfig === index,
|
||||||
|
'border-gray-600': selectedConfig !== index
|
||||||
|
}">
|
||||||
<div class="font-medium mb-2">{{ config.name }}</div>
|
<div class="font-medium mb-2">{{ config.name }}</div>
|
||||||
<div class="text-sm text-gray-400">{{config.customInstructions ||
|
<div class="text-sm text-gray-400">
|
||||||
'Requires API key'}}</div>
|
{{ config.customInstructions || 'Requires API key' }}
|
||||||
|
</div>
|
||||||
<div class="mt-2 text-dark-accent-green font-semibold">API</div>
|
<div class="mt-2 text-dark-accent-green font-semibold">API</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ var app = new Vue({
|
|||||||
{ name: 'Replicate', prompts: 40000 },
|
{ name: 'Replicate', prompts: 40000 },
|
||||||
{ name: 'Groq', prompts: 40000 },
|
{ name: 'Groq', prompts: 40000 },
|
||||||
{ name: 'Together.ai', prompts: 40000 },
|
{ name: 'Together.ai', prompts: 40000 },
|
||||||
|
{ name: 'Custom API Image', prompts: 40000, customInstructions: 'Requires api spec' },
|
||||||
|
{ name: 'Custom API Files', prompts: 40000, customInstructions: 'Requires api spec' },
|
||||||
|
|
||||||
],
|
],
|
||||||
dataConfig: [],
|
dataConfig: [],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -38,4 +38,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
.scrollbar-hide::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.scrollbar-hide {
|
||||||
|
-ms-overflow-style: none; /* IE and Edge */
|
||||||
|
scrollbar-width: none; /* Firefox */
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
Reference in new issue
Block a user