mirror of
				https://github.com/deepset-ai/haystack.git
				synced 2025-10-31 01:39:45 +00:00 
			
		
		
		
	 be8f50c9e3
			
		
	
	
		be8f50c9e3
		
			
		
	
	
	
	
		
			
			* Add DELETE /feedback for testing and make the ID generate server-side * Make sure to delete only user generated labels * Reduce fixture scope, was too broad * Make test a bit more generic Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
		
			
				
	
	
		
			123 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from typing import List, Dict, Any, Tuple, Optional
 | |
| 
 | |
| import os
 | |
| import logging
 | |
| import requests
 | |
| from time import sleep
 | |
| from uuid import uuid4
 | |
| import streamlit as st
 | |
| 
 | |
| 
 | |
| API_ENDPOINT = os.getenv("API_ENDPOINT", "http://localhost:8000")
 | |
| STATUS = "initialized"
 | |
| HS_VERSION = "hs_version"
 | |
| DOC_REQUEST = "query"
 | |
| DOC_FEEDBACK = "feedback"
 | |
| DOC_UPLOAD = "file-upload"
 | |
| 
 | |
| 
 | |
| def haystack_is_ready():
 | |
|     """
 | |
|     Used to show the "Haystack is loading..." message
 | |
|     """
 | |
|     url = f"{API_ENDPOINT}/{STATUS}"
 | |
|     try:
 | |
|         if requests.get(url).status_code < 400:
 | |
|             return True
 | |
|     except Exception as e:
 | |
|         logging.exception(e)
 | |
|         sleep(1)  # To avoid spamming a non-existing endpoint at startup
 | |
|     return False
 | |
| 
 | |
| 
 | |
| @st.cache
 | |
| def haystack_version():
 | |
|     """
 | |
|     Get the Haystack version from the REST API
 | |
|     """
 | |
|     url = f"{API_ENDPOINT}/{HS_VERSION}"
 | |
|     return requests.get(url, timeout=0.1).json()["hs_version"]
 | |
| 
 | |
| 
 | |
| def query(query, filters={}, top_k_reader=5, top_k_retriever=5) -> Tuple[List[Dict[str, Any]], Dict[str, str]]:
 | |
|     """
 | |
|     Send a query to the REST API and parse the answer.
 | |
|     Returns both a ready-to-use representation of the results and the raw JSON.
 | |
|     """
 | |
| 
 | |
|     url = f"{API_ENDPOINT}/{DOC_REQUEST}"
 | |
|     params = {"filters": filters, "Retriever": {"top_k": top_k_retriever}, "Reader": {"top_k": top_k_reader}}
 | |
|     req = {"query": query, "params": params}
 | |
|     response_raw = requests.post(url, json=req)
 | |
| 
 | |
|     if response_raw.status_code >= 400 and response_raw.status_code != 503:
 | |
|         raise Exception(f"{vars(response_raw)}")
 | |
| 
 | |
|     response = response_raw.json()
 | |
|     if "errors" in response:
 | |
|         raise Exception(", ".join(response["errors"]))
 | |
| 
 | |
|     # Format response
 | |
|     results = []
 | |
|     answers = response["answers"]
 | |
|     for answer in answers:
 | |
|         if answer.get("answer", None):
 | |
|             results.append(
 | |
|                 {
 | |
|                     "context": "..." + answer["context"] + "...",
 | |
|                     "answer": answer.get("answer", None),
 | |
|                     "source": answer["meta"]["name"],
 | |
|                     "relevance": round(answer["score"] * 100, 2),
 | |
|                     "document": [doc for doc in response["documents"] if doc["id"] == answer["document_id"]][0],
 | |
|                     "offset_start_in_doc": answer["offsets_in_document"][0]["start"],
 | |
|                     "_raw": answer,
 | |
|                 }
 | |
|             )
 | |
|         else:
 | |
|             results.append(
 | |
|                 {
 | |
|                     "context": None,
 | |
|                     "answer": None,
 | |
|                     "document": None,
 | |
|                     "relevance": round(answer["score"] * 100, 2),
 | |
|                     "_raw": answer,
 | |
|                 }
 | |
|             )
 | |
|     return results, response
 | |
| 
 | |
| 
 | |
| def send_feedback(query, answer_obj, is_correct_answer, is_correct_document, document) -> None:
 | |
|     """
 | |
|     Send a feedback (label) to the REST API
 | |
|     """
 | |
|     url = f"{API_ENDPOINT}/{DOC_FEEDBACK}"
 | |
|     req = {
 | |
|         "query": query,
 | |
|         "document": document,
 | |
|         "is_correct_answer": is_correct_answer,
 | |
|         "is_correct_document": is_correct_document,
 | |
|         "origin": "user-feedback",
 | |
|         "answer": answer_obj,
 | |
|     }
 | |
|     response_raw = requests.post(url, json=req)
 | |
|     if response_raw.status_code >= 400:
 | |
|         raise ValueError(f"An error was returned [code {response_raw.status_code}]: {response_raw.json()}")
 | |
| 
 | |
| 
 | |
| def upload_doc(file):
 | |
|     url = f"{API_ENDPOINT}/{DOC_UPLOAD}"
 | |
|     files = [("files", file)]
 | |
|     response = requests.post(url, files=files).json()
 | |
|     return response
 | |
| 
 | |
| 
 | |
| def get_backlink(result) -> Tuple[Optional[str], Optional[str]]:
 | |
|     if result.get("document", None):
 | |
|         doc = result["document"]
 | |
|         if isinstance(doc, dict):
 | |
|             if doc.get("meta", None):
 | |
|                 if isinstance(doc["meta"], dict):
 | |
|                     if doc["meta"].get("url", None) and doc["meta"].get("title", None):
 | |
|                         return doc["meta"]["url"], doc["meta"]["title"]
 | |
|     return None, None
 |