mirror of
https://github.com/fsecada01/Pygentic-AI.git
synced 2025-06-22 14:36:04 +00:00
WIP: adding pygentic.css
for css spinner element; patching other components. Result objects not loading correctly and messages not stacking
This commit is contained in:
parent
07e7fa09a5
commit
05d8baffb1
@ -1,4 +1,6 @@
|
|||||||
AI_MODEL = "gpt-4o"
|
from backend.utils import get_val
|
||||||
|
|
||||||
|
AI_MODEL = get_val("OPENAI_MODEL", "gpt-4o")
|
||||||
default_system_prompt = """
|
default_system_prompt = """
|
||||||
You are an advanced and intelligent AI assistant specializing in generating
|
You are an advanced and intelligent AI assistant specializing in generating
|
||||||
comprehensive and detailed SWOT analyses for a variety of scenarios, topics,
|
comprehensive and detailed SWOT analyses for a variety of scenarios, topics,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from pprint import pformat
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from bs4 import BeautifulSoup as soup
|
from bs4 import BeautifulSoup as soup
|
||||||
from pydantic_ai import RunContext
|
from pydantic_ai import RunContext
|
||||||
@ -117,7 +119,7 @@ async def run_agent(
|
|||||||
f"Perform a comprehensive SWOT analysis for this product: {url}",
|
f"Perform a comprehensive SWOT analysis for this product: {url}",
|
||||||
deps=deps,
|
deps=deps,
|
||||||
)
|
)
|
||||||
logger.info(f"Agent Result: {result}")
|
logger.info(f"Agent Result: {pformat(result.data)}")
|
||||||
|
|
||||||
if deps.update_status_func:
|
if deps.update_status_func:
|
||||||
await deps.update_status_func(deps.request, "Analysis Complete")
|
await deps.update_status_func(deps.request, "Analysis Complete")
|
||||||
|
31
src/frontend/static/css/pygentic_ai.css
Normal file
31
src/frontend/static/css/pygentic_ai.css
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/* Spinner Wrapper with Overlay Effect */
|
||||||
|
.spinner-wrapper {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(255, 255, 255, 0.7); /* Light overlay effect */
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
border: 4px solid rgba(0, 0, 0, 0.1); /* Light gray */
|
||||||
|
border-top: 4px solid #3273dc; /* Bulma primary color */
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
animation: spin 0.8s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
from {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
BIN
src/frontend/static/favicon.ico
Normal file
BIN
src/frontend/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
@ -2,6 +2,10 @@
|
|||||||
<meta name="viewport"
|
<meta name="viewport"
|
||||||
content="width=device-width, initial-scale=1.0">
|
content="width=device-width, initial-scale=1.0">
|
||||||
<title>{% block title %}Pygentic AI{% endblock title %}</title>
|
<title>{% block title %}Pygentic AI{% endblock title %}</title>
|
||||||
|
<link rel="icon"
|
||||||
|
href="{{ url_for('static', path='favicon.ico') }}"
|
||||||
|
id="favicon"
|
||||||
|
type='image/x-icon'>
|
||||||
{% block head_content %}
|
{% block head_content %}
|
||||||
{% endblock head_content %}
|
{% endblock head_content %}
|
||||||
{% include 'components/main/style_sheets.html' %}
|
{% include 'components/main/style_sheets.html' %}
|
@ -1,5 +1,7 @@
|
|||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="{{ url_for('static', path='css/bulma.min.css') }}">
|
href="{{ url_for('static', path='css/bulma.min.css') }}">
|
||||||
|
<link rel="stylesheet"
|
||||||
|
href="{{ url_for('static', path='css/pygentic_ai.css') }}">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
href="{{ url_for('static', path='css/bulma.css.map') }}">
|
href="{{ url_for('static', path='css/bulma.css.map') }}">
|
||||||
<link rel="stylesheet"
|
<link rel="stylesheet"
|
||||||
|
4
src/frontend/templates/components/snippets/Spinner.jinja
Normal file
4
src/frontend/templates/components/snippets/Spinner.jinja
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div class="spinner-wrapper is-overlay is-hidden"
|
||||||
|
id="spinner">
|
||||||
|
<div class="loader"></div>
|
||||||
|
</div>
|
@ -1,11 +1,12 @@
|
|||||||
{# def
|
{# def
|
||||||
div_class: str,
|
div_class: str,
|
||||||
|
header_content: str = ''
|
||||||
|
|
||||||
#}
|
#}
|
||||||
|
|
||||||
<article class="message is-{{ div_class }}">
|
<article class="message is-{{ div_class }}">
|
||||||
<div class="message-header">
|
<div class="message-header">
|
||||||
<p></p>
|
<p>{{ header_content }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-body">
|
<div class="message-body">
|
||||||
{{ content }}
|
{{ content }}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section class="section">
|
<section class="section">
|
||||||
|
<Spinner></Spinner>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="title">Search Here</h1>
|
<h1 class="title">Search Here</h1>
|
||||||
<Search form_id="swotSearch"
|
<Search form_id="swotSearch"
|
||||||
@ -17,14 +18,13 @@
|
|||||||
method="post">
|
method="post">
|
||||||
<div class="field mt-1 pt-1">
|
<div class="field mt-1 pt-1">
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<button type="button"
|
<button type="submit"
|
||||||
class="button is-success"
|
class="button is-success"
|
||||||
|
hx-indicator='#spinner'
|
||||||
hx-on:click="
|
hx-on:click="
|
||||||
const [status, result] = ['#status', '#result'].map(id => document.querySelector(id));
|
const [status, result] = ['#status', '#result'].map(id => document.querySelector(id));
|
||||||
status.style.display = 'block';
|
status.style.display = 'block';
|
||||||
result.style.display = 'none';
|
result.style.display = 'none';
|
||||||
|
|
||||||
htmx.trigger('#swotSearch', 'submit')
|
|
||||||
">Analyze</button>
|
">Analyze</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -36,14 +36,14 @@
|
|||||||
id="status">
|
id="status">
|
||||||
<div class="box"
|
<div class="box"
|
||||||
id="status"
|
id="status"
|
||||||
hx-get='/status'
|
hx-get={{ url_for('get_status') }}
|
||||||
hx-trigger='load, every 1s'
|
hx-trigger='load, every 1s'
|
||||||
hx-swap='innerHTML'
|
hx-swap='innerHTML'
|
||||||
style="display: none">
|
style="display: none">
|
||||||
</div>
|
</div>
|
||||||
<div class="box"
|
<div class="box"
|
||||||
id="result"
|
id="result"
|
||||||
hx-get='/result'
|
hx-get={{ url_for('get_result') }}
|
||||||
hx-trigger="load, every 1s[!this.querySelector('#result-container') || this.style.display === 'none']"
|
hx-trigger="load, every 1s[!this.querySelector('#result-container') || this.style.display === 'none']"
|
||||||
hx-swap='innerHTML'
|
hx-swap='innerHTML'
|
||||||
hx-on:after-request="
|
hx-on:after-request="
|
||||||
@ -56,12 +56,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
{% block js_content %}
|
|
||||||
<script>
|
|
||||||
document.body.addEventListener("htmx:configRequest", function(evt) {
|
|
||||||
console.log("HTMX Request Configured:", evt.detail);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% endblock js_content %}
|
|
@ -1,12 +1,12 @@
|
|||||||
{% if result %}
|
{% if result %}
|
||||||
|
<section class="section"
|
||||||
<section class="section">
|
id="result-container">
|
||||||
<div class="container"
|
<div class="container"
|
||||||
id="result-container">
|
id="result-container">
|
||||||
<h2 class="subtitle is-2">Analysis Complete</h2>
|
<h2 class="subtitle is-2">Analysis Complete</h2>
|
||||||
<div class="fixed-grid">
|
<div class="fixed-grid">
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{% for cat in results %}
|
{% for cat in result %}
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -1,21 +1,30 @@
|
|||||||
{% if messages %}
|
{% if messages %}
|
||||||
<div id="status-container"
|
<section class="section"
|
||||||
class="container">
|
id="status-container">
|
||||||
{% for message in messages %}
|
<div class="container">
|
||||||
{% set is_error = message.startswith('Error:') %}
|
{% for message in messages %}
|
||||||
{% set is_loading = loop.last and not result %}
|
{% set is_error = message.startswith('Error:') %}
|
||||||
{% set is_tool_message = message.startswith('Using tool') %}
|
{% set is_loading = loop.last and not result %}
|
||||||
<div class="box">
|
{% set is_tool_message = message.startswith('Using tool') %}
|
||||||
{% set bg_color = 'danger' if is_error else ('dark' if is_loading else "info") %}
|
<div class="box">
|
||||||
{% if is_error %}
|
{% set bg_color = 'danger' if is_error else ('dark' if is_loading else
|
||||||
{% set content = message.split('body:', 1)[1] %}
|
"info") %}
|
||||||
{% elif is_tool_message %}
|
{% if is_error %}
|
||||||
{% set content = message.split('', 2)[2].split('...', 1)[1] %}
|
{% set header_content, content = message.split('body:', 1) %}
|
||||||
{% else %}
|
{% elif is_tool_message %}
|
||||||
{% set content = message %}
|
{% set header_content, content = message.split(' ', 2)[2].split('...', 1) %}
|
||||||
{% endif %}
|
{% elif is_loading %}
|
||||||
<StatusResult div_class={{ bg_color }}>{{ message }}</StatusResult>
|
{% set content = message %}
|
||||||
|
{% set header_content = 'In Progress' %}
|
||||||
|
{% else %}
|
||||||
|
{% set content = message %}
|
||||||
|
{% set header_content = 'Complete' %}
|
||||||
|
{% endif %}
|
||||||
|
<StatusResult div_class={{ bg_color }}
|
||||||
|
header_content={{ header_content }}>{{ message }}
|
||||||
|
</StatusResult>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
</section>
|
||||||
</div>
|
|
||||||
{% endif %}
|
{% endif %}
|
Loading…
x
Reference in New Issue
Block a user