File size: 2,835 Bytes
b15194a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

import streamlit as st
import pandas as pd
from sentence_transformers import SentenceTransformer
import numpy as np
import faiss

# Load data
df = pd.read_csv("frameworks.csv")

# Embed the scope column
model = SentenceTransformer("all-MiniLM-L6-v2")
scope_embeddings = model.encode(df["scope"].tolist())
index = faiss.IndexFlatL2(scope_embeddings.shape[1])
index.add(np.array(scope_embeddings))

st.set_page_config(page_title="AI Framework/DPS Finder", layout="centered")
st.title("πŸ€– AI-Powered Framework & DPS Finder")

st.markdown("""Fill in your procurement details and our AI will recommend suitable frameworks or DPS options.""")

with st.form("proc_form"):
    authority_type = st.selectbox("1. What type of contracting authority are you?", ["Local authority", "NHS", "Central government", "Utility"])
    award_method = st.selectbox("2. Would you prefer to direct award or run a mini-competition?", ["Direct award", "Mini-competition", "Either"])
    contract_value = st.number_input("3. Expected contract value (incl. VAT)", min_value=0)
    duration = st.text_input("4. Expected contract duration (incl. extensions)")
    description = st.text_area("5. Briefly describe the type of service needed and main deliverables")
    submit = st.form_submit_button("πŸ” Find Frameworks")

if submit:
    if description.strip() == "":
        st.warning("Please enter a service description.")
    else:
        query_vec = model.encode([description])
        D, I = index.search(np.array(query_vec), k=5)
        candidates = df.iloc[I[0]]

        # Filter based on authority, value cap, and award method
        matches = candidates[
            (candidates["authority_types"].str.contains(authority_type, case=False)) &
            (candidates["value_cap"] >= contract_value) &
            (
                (award_method == "Either") |
                ((award_method == "Direct award") & (candidates["direct_award"] == "Yes")) |
                ((award_method == "Mini-competition") & (candidates["direct_award"] == "No"))
            )
        ]

        st.subheader("πŸ”Ž Recommended Frameworks")
        if matches.empty:
            st.error("No suitable frameworks found. You may need to consider running a new procurement competition or expanding your criteria.")
        else:
            top_n = min(len(matches), 3)
            for i in range(top_n):
                row = matches.iloc[i]
                st.success(f"βœ… {row['name']}")
                st.markdown(f"- **Provider:** {row['provider']}")
                st.markdown(f"- **Scope:** {row['scope']}")
                st.markdown(f"- **Direct Award:** {row['direct_award']}")
                st.markdown(f"- **Value Cap:** Β£{row['value_cap']:,}")
                st.markdown(f"- [πŸ”— View Framework]({row['link']})")
                st.markdown("---")