2024-05-26 18:20:51 +02:00

142 lines
4.6 KiB
Python

"""
OpenAPI access via http://localhost:5000/openapi/ on local docker-compose deployment
"""
#import warnings
#warnings.filterwarnings("ignore")
#std lib modules:
import os, sys, json
from typing import Any, Tuple, List, Dict, Any, Callable, Optional
from datetime import datetime, date
from collections import namedtuple
import hashlib, traceback, logging
#llm
from langchain.callbacks.manager import CallbackManager
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
from langchain_community.llms import Ollama
#import openai #even used?
import tiktoken
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
#from langchain.callbacks import get_openai_callback
#from langchain_community.callbacks import get_openai_callback
#from langchain_openai import ChatOpenAI, AzureChatOpenAI
#from langchain_openai import OpenAIEmbeddings, AzureOpenAIEmbeddings
from langchain_community.vectorstores.elasticsearch import ElasticsearchStore
#from langchain.document_loaders import PyPDFLoader, Docx2txtLoader
from langchain_community.document_loaders import PyPDFLoader, Docx2txtLoader
from langchain.callbacks.base import BaseCallbackHandler, BaseCallbackManager
from langchain.prompts import PromptTemplate
#ext libs
from elasticsearch import NotFoundError, Elasticsearch # for normal read/write without vectors
from elasticsearch_dsl import Search, A
from elasticsearch_dsl import Document, Date, Integer, Keyword, Float, Long, Text, connections
from pydantic import BaseModel, Field
#flask, openapi
from flask import Flask, send_from_directory, Response, request, jsonify
import sys, os
from flask_cors import CORS, cross_origin
from werkzeug.utils import secure_filename
from flask_openapi3 import Info, Tag, OpenAPI, Server, FileStorage
from flask_socketio import SocketIO, join_room, leave_room, rooms, send
#home grown
#from scraper import WebScraper
from funcs import group_by
#from elastictools import update_by_id, delete_by_id
#TODO: implement some kind of logging mechanism
#logging.basicConfig(filename='record.log', level=logging.DEBUG)
#logging.basicConfig(level=logging.DEBUG)
logging.basicConfig(level=logging.WARN)
app = Flask(__name__)
from flask_cors import CORS #falls cross-orgin verwendet werden soll
CORS(app)
socket = SocketIO(app, cors_allowed_origins="*")
@socket.on('connect')
def sockcon(data):
"""
put every connection into it's own room
to avoid broadcasting messages
answer in callback only to room with sid
"""
room = request.sid
join_room(room)
socket.emit('backend response', {'msg': f'Connected to room {room} !', "room": room}) # looks like iOS needs an answer
@socket.on('client message')
def handle_message(message):
room = message["room"]
stream_key = "chatbot_stream"
llm = Ollama(
model="llama3",
base_url="http://ollama:11434"
)
#system_prompt = "Answer in the language of the question. Give a short answer. Answer all questions without reservations or advice."
#system_prompt = "Answer in the language of the question. Give a short answer."
#system_prompt = "Always answer in English and give a short answer."
#system_prompt = "Always answer in English and give a short answer. If the answer is a list give it only as a JSON array."
#system_prompt = "Write the answer as Prolog assertions."
#system_prompt = "Write the answer in Japanese."
#system_prompt = "Write the answer in Japanese."
system_prompt = ""
#Write the answer as JSON only.
#If the answer is a geographic position return a JSON-object with the longitude and latitude as attributes.
query = system_prompt + " " + message["data"]
print(message["data"])
for chunks in llm.stream(query):
socket.emit('backend token', {'data': chunks, "done": False}, to=room)
socket.emit('backend token', {'done': True}, to=room)
#==============Routes===============
@app.route("/") #Index Verzeichnis
def index():
return send_from_directory('.', "index.html")
@app.route("/info") #spezielle Nutzer definierte Route
def info():
return sys.version+" "+os.getcwd()
@app.route('/<path:path>') #generische Route (auch Unterordner)
def catchAll(path):
return send_from_directory('.', path)
if __name__ == '__main__':
#Wenn HTTPS benötigt wird (Pfade für RHEL7/können je OS variieren)
#cert = "/etc/pki/tls/certs/cert-payment.pem" #cert
#key = "/etc/pki/tls/private/cert-payment-private.pem" #key
#context = (cert, key)
#app.run(debug=True, host='0.0.0.0', ssl_context=context)
app.run(debug=True, host='0.0.0.0')
#app.run(debug=True)