new file:   .gitignore
	new file:   README.md
	new file:   requirements.txt
	new file:   static/openapi.yaml
This commit is contained in:
Russell Ballestrini 2025-03-19 19:45:20 -04:00
parent b591798c4b
commit dd9c81eee3
4 changed files with 673 additions and 0 deletions

136
.gitignore vendored Normal file
View file

@ -0,0 +1,136 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
vars.sh
# ignore python virtualenvs
env/
venv/
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

134
README.md Normal file
View file

@ -0,0 +1,134 @@
# SLOP Streamlit Example
Streamlit-based SLOP example with dynamic model endpoints. It explains the purpose, setup, usage, and structure in a clear and concise way.
This is a Python implementation of the [SLOP pattern](https://github.com/agnt-gg/slop) using Flask as a backend server and Streamlit as a frontend interface. It dynamically discovers and utilizes language models from OpenAI-compatible endpoints (e.g., vLLM, Ollama, etc.) specified via environment variables.
## Features
- **Chat**: Send messages to dynamically discovered AI models.
- **Tools**: Use simple tools like a calculator and greeter. (broken, please help fix this)
- **Memory**: Store and retrieve key-value pairs.
- **Resources**: Access predefined static content.
- **Pay**: Simulate a payment transaction.
## Prerequisites
- Python 3.8+
- A terminal to run commands
- Optional: Access to OpenAI-compatible model endpoints (e.g., `https://hermes.ai.unturf.com/v1`)
## Setup
1. **Clone the Repository**:
```bash
git clone https://github.com/agnt-gg/slop
cd slop/examples/streamlit
```
2. **Set Up Virtual Environment**:
```bash
make setup
```
This creates a virtual environment (`venv`) and installs dependencies from `requirements.txt`.
3. **Configure Model Endpoints**:
Edit `vars.sh` to specify your model endpoints:
```bash
# vars.sh
export MODEL_ENDPOINT_0=https://hermes.ai.unturf.com/v1
export MODEL_ENDPOINT_1=https://node2.naptha.ai/inference
export MODEL_ENDPOINT_2=https://node3.naptha.ai/inference
```
- Gaps in numbering (e.g., skipping `MODEL_ENDPOINT_1`) are supported.
- API keys are optional; defaults to `"not-needed"` if unset (e.g., `export MODEL_API_KEY_0=your-key`).
## Usage
1. **Run the Flask Server**:
Open a terminal and start the backend:
```bash
make slop-flask
```
- This sources `vars.sh` and runs `slop_with_models.py` on `http://localhost:31337`.
- Logs will show model discovery (e.g., `Loaded models: [model1, endpoint_7:default]`).
2. **Run the Streamlit App**:
Open a second terminal and start the frontend:
```bash
make slop-streamlit
```
- Opens in your browser at `http://localhost:8501`.
- Displays a UI with Chat, Tools, Memory, Resources, and Pay sections.
3. **Interact**:
- **Chat**: Select a model from the dropdown and send a message.
- **Tools**: Use the calculator or greeter.
- **Memory**: Store/retrieve values.
- **Resources**: View static content.
- **Pay**: Simulate a transaction.
4. **Clean Up** (optional):
```bash
make clean
```
Removes the virtual environment.
## Files
- **`slop_with_models.py`**: Flask server implementing the SLOP pattern with dynamic model discovery.
- **`streamlit_slop_with_models.py`**: Streamlit frontend for user interaction.
- **`Makefile`**: Simplifies ``make setup`` and running with ``make slop-flask`` and ``make slop-streamlit``.
- **`vars.sh`**: Environment variables for model endpoints. Feel free to start with ``vars.sh.sample``!
- **`requirements.txt`**: Dependencies
## How It Works
1. **Model Discovery**:
- The Flask server scans `MODEL_ENDPOINT_0` to `MODEL_ENDPOINT_999` from `vars.sh`.
- Queries each endpoints `/v1/models` using the OpenAI client.
- Maps model IDs to their respective clients
2. **API Endpoints**:
- `/models`: Returns the list of discovered models.
- `/chat`: Handles chat completions with the selected model.
- `/tools`, `/memory`, `/resources`, `/pay`: Implement SLOP pattern features.
3. **Frontend**:
- Streamlit fetches the model list from `/models` and provides a dropdown.
- Sends requests to Flask for chat and other functionalities.
## Troubleshooting
- **No Models in Dropdown**:
- Check Flask logs (`make slop-flask`) for errors (e.g., `Failed to list models for endpoint_X`).
- Test endpoints with `curl <endpoint>/v1/models` to ensure theyre OpenAI-compatible.
- **Server Not Responding**:
- Ensure Flask is running (`make slop-flask`) before starting Streamlit.
- **Environment Variables**:
- Verify `vars.sh` is correct and sourced (`source vars.sh; echo $MODEL_ENDPOINT_0`).
## Dependencies
Listed in `requirements.txt`:
- `flask`: Backend server
- `streamlit`: Frontend UI
- `openai`: Client for model endpoints
- `requests`: HTTP requests in Streamlit
## Learn More
- [SLOP Specification](https://github.com/agnt-gg/slop)
This example demonstrates a flexible, extensible SLOP implementation with a modern UI. Contributions and feedback are welcome!
---
This is research into the genesis of of the future https://slop.unturf.com/
The code in this example is Public Domain.

5
requirements.txt Normal file
View file

@ -0,0 +1,5 @@
flask
streamlit
openai
requests
flask_swagger_ui

398
static/openapi.yaml Normal file
View file

@ -0,0 +1,398 @@
openapi: 3.0.0
info:
title: SLOP API
description: A SLOP pattern implementation with dynamic model endpoints
version: 1.0.0
servers:
- url: http://localhost:31337
description: Local development server
paths:
/chat:
post:
summary: Send a message to an AI model
tags:
- Chat
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChatRequest'
responses:
'200':
description: Successful response with AI message
content:
application/json:
schema:
$ref: '#/components/schemas/ChatResponse'
'404':
description: Model not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/models:
get:
summary: List available models
tags:
- Models
responses:
'200':
description: List of model IDs
content:
application/json:
schema:
$ref: '#/components/schemas/ModelsResponse'
/tools:
get:
summary: List available tools
tags:
- Tools
responses:
'200':
description: List of tools
content:
application/json:
schema:
$ref: '#/components/schemas/ToolsResponse'
/tools/{tool_id}:
post:
summary: Use a specific tool
tags:
- Tools
parameters:
- name: tool_id
in: path
required: true
schema:
type: string
enum: [calculator, greet]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ToolRequest'
responses:
'200':
description: Tool execution result
content:
application/json:
schema:
$ref: '#/components/schemas/ToolResponse'
'400':
description: Missing required parameter
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tool not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/memory:
get:
summary: List all memory keys
tags:
- Memory
responses:
'200':
description: List of memory keys
content:
application/json:
schema:
$ref: '#/components/schemas/MemoryListResponse'
post:
summary: Store a key-value pair
tags:
- Memory
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MemoryStoreRequest'
responses:
'200':
description: Successfully stored
content:
application/json:
schema:
$ref: '#/components/schemas/MemoryStoreResponse'
/memory/{key}:
get:
summary: Retrieve a value by key
tags:
- Memory
parameters:
- name: key
in: path
required: true
schema:
type: string
responses:
'200':
description: Retrieved value
content:
application/json:
schema:
$ref: '#/components/schemas/MemoryGetResponse'
delete:
summary: Delete a memory key
tags:
- Memory
parameters:
- name: key
in: path
required: true
schema:
type: string
responses:
'200':
description: Successfully deleted
content:
application/json:
schema:
$ref: '#/components/schemas/MemoryStoreResponse'
'404':
description: Key not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/resources:
get:
summary: List available resources
tags:
- Resources
responses:
'200':
description: List of resources
content:
application/json:
schema:
$ref: '#/components/schemas/ResourcesResponse'
/resources/{resource_id}:
get:
summary: Get a specific resource
tags:
- Resources
parameters:
- name: resource_id
in: path
required: true
schema:
type: string
responses:
'200':
description: Resource content
content:
application/json:
schema:
$ref: '#/components/schemas/ResourceResponse'
'404':
description: Resource not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/pay:
post:
summary: Simulate a payment
tags:
- Pay
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PayRequest'
responses:
'200':
description: Payment simulation result
content:
application/json:
schema:
$ref: '#/components/schemas/PayResponse'
components:
schemas:
ChatRequest:
type: object
properties:
messages:
type: array
items:
$ref: '#/components/schemas/Message'
model:
type: string
nullable: true
required:
- messages
Message:
type: object
properties:
role:
type: string
enum: [user, assistant, system]
content:
type: string
required:
- role
- content
ChatResponse:
type: object
properties:
choices:
type: array
items:
type: object
properties:
message:
type: object
properties:
content:
type: string
required:
- message
required:
- choices
ModelsResponse:
type: object
properties:
models:
type: array
items:
type: string
required:
- models
ToolsResponse:
type: object
properties:
tools:
type: array
items:
type: object
properties:
id:
type: string
description:
type: string
required:
- id
- description
required:
- tools
ToolRequest:
type: object
properties:
expression:
type: string
nullable: true
name:
type: string
nullable: true
ToolResponse:
type: object
properties:
result:
oneOf:
- type: string
- type: integer
required:
- result
MemoryStoreRequest:
type: object
properties:
key:
type: string
value:
type: string
required:
- key
- value
MemoryStoreResponse:
type: object
properties:
status:
type: string
enum: [stored, deleted]
required:
- status
MemoryGetResponse:
type: object
properties:
value:
type: string
nullable: true
required:
- value
MemoryListResponse:
type: object
properties:
keys:
type: array
items:
type: string
required:
- keys
ResourcesResponse:
type: object
properties:
resources:
type: array
items:
type: object
properties:
id:
type: string
content:
type: string
required:
- id
- content
required:
- resources
ResourceResponse:
type: object
properties:
id:
type: string
content:
type: string
required:
- id
- content
PayRequest:
type: object
properties:
amount:
type: number
format: float
required:
- amount
PayResponse:
type: object
properties:
transaction_id:
type: string
status:
type: string
enum: [success]
required:
- transaction_id
- status
ErrorResponse:
type: object
properties:
error:
type: string
required:
- error