Kabir08 commited on
Commit
45c65f8
·
1 Parent(s): f2c0548

Initial code, download index from Hugging Face Hub

Browse files
Files changed (5) hide show
  1. README.md +78 -9
  2. app.py +16 -60
  3. dify_faiss_index/.gitkeep +0 -0
  4. dify_rag.py +45 -0
  5. requirements.txt +7 -1
README.md CHANGED
@@ -1,12 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- title: Dify Expert
3
- emoji: 💬
4
- colorFrom: yellow
5
- colorTo: purple
6
- sdk: gradio
7
- sdk_version: 5.0.1
8
- app_file: app.py
9
- pinned: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  ---
11
 
12
- An example chatbot using [Gradio](https://gradio.app), [`huggingface_hub`](https://huggingface.co/docs/huggingface_hub/v0.22.2/en/index), and the [Hugging Face Inference API](https://huggingface.co/docs/api-inference/index).
 
 
1
+ `# Dify Documentation Expert (RAG Chatbot)
2
+
3
+ A Retrieval-Augmented Generation (RAG) chatbot for Dify documentation, using MiniLM for semantic search and DistilBERT for answer generation. Built with Python, Flask, LangChain, and FAISS. Deployable on Vercel.
4
+
5
+ ---
6
+
7
+ ## Features
8
+ - Scrapes and processes Dify documentation
9
+ - Builds a FAISS vector store with MiniLM embeddings
10
+ - Uses DistilBERT for question answering
11
+ - Fast API with `/ask` and `/health` endpoints
12
+ - Ready for serverless deployment (Vercel)
13
+
14
+ ---
15
+
16
+ ## Project Structure
17
+ ```
18
+ Dify-Expert/
19
+ ├── api/
20
+ │ └── dify_api.py # Flask API (entry point for Vercel)
21
+ ├── dify_docs_scraper/
22
+ │ ├── dify_rag.py # RAG logic (vector store + QA)
23
+ │ ├── dify_faiss_index/ # FAISS index files
24
+ │ └── ... # Scraper, processing scripts, etc.
25
+ ├── requirements.txt # Python dependencies
26
+ ├── vercel.json # Vercel config
27
+ ├── README.md # This file
28
+ └── futurescope.md # Project roadmap/ideas
29
+ ```
30
+
31
  ---
32
+
33
+ ## Quickstart
34
+
35
+ ### 1. Install dependencies
36
+ ```bash
37
+ pip install -r requirements.txt
38
+ ```
39
+
40
+ ### 2. Build the vector store (if not already built)
41
+ ```bash
42
+ python3 dify_docs_scraper/build_vector_store.py
43
+ ```
44
+
45
+ ### 3. Run locally (API)
46
+ ```bash
47
+ python3 api/dify_api.py
48
+ ```
49
+
50
+ ### 4. Query the API
51
+ ```bash
52
+ curl -X POST http://localhost:8000/ask \
53
+ -H "Content-Type: application/json" \
54
+ -d '{"question": "What is Dify?"}'
55
+ ```
56
+
57
+ ---
58
+
59
+ ## Deployment (Vercel)
60
+ 1. Push to GitHub.
61
+ 2. Connect repo to Vercel.
62
+ 3. Deploy (Vercel auto-detects Python from requirements.txt).
63
+ 4. Endpoints:
64
+ - `/ask` (POST)
65
+ - `/health` (GET)
66
+
67
+ ---
68
+
69
+ ## API Endpoints
70
+ - `POST /ask` — `{ "question": "..." }` → `{ "answer": ..., "score": ..., "sources": [...] }`
71
+ - `GET /health` — `{ "status": "ok" }`
72
+
73
+ ---
74
+
75
+ ## Roadmap
76
+ See [`futurescope.md`](futurescope.md) for planned features and ideas.
77
+
78
  ---
79
 
80
+ ## License
81
+ MIT
app.py CHANGED
@@ -1,64 +1,20 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
-
4
- """
5
- For more information on `huggingface_hub` Inference API support, please check the docs: https://huggingface.co/docs/huggingface_hub/v0.22.2/en/guides/inference
6
- """
7
- client = InferenceClient("HuggingFaceH4/zephyr-7b-beta")
8
-
9
-
10
- def respond(
11
- message,
12
- history: list[tuple[str, str]],
13
- system_message,
14
- max_tokens,
15
- temperature,
16
- top_p,
17
- ):
18
- messages = [{"role": "system", "content": system_message}]
19
-
20
- for val in history:
21
- if val[0]:
22
- messages.append({"role": "user", "content": val[0]})
23
- if val[1]:
24
- messages.append({"role": "assistant", "content": val[1]})
25
-
26
- messages.append({"role": "user", "content": message})
27
-
28
- response = ""
29
-
30
- for message in client.chat_completion(
31
- messages,
32
- max_tokens=max_tokens,
33
- stream=True,
34
- temperature=temperature,
35
- top_p=top_p,
36
- ):
37
- token = message.choices[0].delta.content
38
-
39
- response += token
40
- yield response
41
-
42
-
43
- """
44
- For information on how to customize the ChatInterface, peruse the gradio docs: https://www.gradio.app/docs/chatinterface
45
- """
46
- demo = gr.ChatInterface(
47
- respond,
48
- additional_inputs=[
49
- gr.Textbox(value="You are a friendly Chatbot.", label="System message"),
50
- gr.Slider(minimum=1, maximum=2048, value=512, step=1, label="Max new tokens"),
51
- gr.Slider(minimum=0.1, maximum=4.0, value=0.7, step=0.1, label="Temperature"),
52
- gr.Slider(
53
- minimum=0.1,
54
- maximum=1.0,
55
- value=0.95,
56
- step=0.05,
57
- label="Top-p (nucleus sampling)",
58
- ),
59
- ],
60
  )
61
 
62
-
63
  if __name__ == "__main__":
64
- demo.launch()
 
1
  import gradio as gr
2
+ from dify_rag import answer_question
3
+
4
+ def chat_fn(message, history):
5
+ result = answer_question(message)
6
+ answer = result["answer"]
7
+ sources = result.get("sources", [])
8
+ if sources:
9
+ answer += "\n\nSources:\n" + "\n".join(f"- [{s.get('title', '')}]({s.get('url', '')})" for s in sources if s.get("url"))
10
+ return answer
11
+
12
+ iface = gr.ChatInterface(
13
+ fn=chat_fn,
14
+ title="Dify Documentation Expert",
15
+ description="Ask anything about Dify documentation!",
16
+ examples=["What is Dify?", "How do I use code-based extensions?", "What is LLMOps?"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  )
18
 
 
19
  if __name__ == "__main__":
20
+ iface.launch()
dify_faiss_index/.gitkeep ADDED
File without changes
dify_rag.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from huggingface_hub import hf_hub_download
2
+ import os
3
+
4
+ faiss_dir = os.path.join(os.path.dirname(__file__), "dify_faiss_index")
5
+ os.makedirs(faiss_dir, exist_ok=True)
6
+
7
+ faiss_path = os.path.join(faiss_dir, "index.faiss")
8
+ pkl_path = os.path.join(faiss_dir, "index.pkl")
9
+
10
+ if not os.path.exists(faiss_path):
11
+ hf_hub_download(repo_id="k01010/k01010_dify-faiss-index", filename="index.faiss", local_dir=faiss_dir)
12
+ if not os.path.exists(pkl_path):
13
+ hf_hub_download(repo_id="k01010/k01010_dify-faiss-index", filename="index.pkl", local_dir=faiss_dir)
14
+
15
+ from langchain_community.embeddings import HuggingFaceEmbeddings
16
+ from langchain_community.vectorstores import FAISS
17
+ from transformers import pipeline
18
+
19
+ # Load FAISS vector store and QA pipeline ONCE at module level
20
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/multi-qa-MiniLM-L6-cos-v1")
21
+ index_path = os.path.join(os.path.dirname(__file__), "dify_faiss_index")
22
+ vector_store = FAISS.load_local(index_path, embeddings, allow_dangerous_deserialization=True)
23
+ qa = pipeline("question-answering", model="distilbert-base-uncased-distilled-squad")
24
+
25
+ # Main RAG answer function
26
+ def answer_question(question, top_k=4):
27
+ retriever = vector_store.as_retriever(search_kwargs={"k": top_k})
28
+ docs = retriever.get_relevant_documents(question)
29
+ context = " ".join([doc.page_content for doc in docs])
30
+ result = qa(question=question, context=context)
31
+ return {
32
+ "answer": result["answer"],
33
+ "score": result["score"],
34
+ "context": context,
35
+ "sources": [getattr(doc, "metadata", {}) for doc in docs]
36
+ }
37
+
38
+ if __name__ == "__main__":
39
+ # Simple CLI for testing
40
+ while True:
41
+ q = input("Ask a question (or 'exit'): ")
42
+ if q.lower() == "exit":
43
+ break
44
+ out = answer_question(q)
45
+ print(f"Answer: {out['answer']}\nScore: {out['score']:.2f}\nSources: {out['sources']}")
requirements.txt CHANGED
@@ -1 +1,7 @@
1
- huggingface_hub==0.25.2
 
 
 
 
 
 
 
1
+ flask
2
+ gradio
3
+ langchain-community
4
+ transformers
5
+ faiss-cpu
6
+ torch
7
+ huggingface_hub