ship it.
new file: .gitignore new file: README.md new file: requirements.txt new file: static/openapi.yaml
This commit is contained in:
parent
b591798c4b
commit
dd9c81eee3
4 changed files with 673 additions and 0 deletions
136
.gitignore
vendored
Normal file
136
.gitignore
vendored
Normal 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
134
README.md
Normal 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 endpoint’s `/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 they’re 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
5
requirements.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
flask
|
||||
streamlit
|
||||
openai
|
||||
requests
|
||||
flask_swagger_ui
|
||||
398
static/openapi.yaml
Normal file
398
static/openapi.yaml
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue