# Install required packages first: # pip install langchain huggingface_hub pandas faiss-cpu numpy transformers torch accelerate bitsandbytes gradio import pandas as pd import numpy as np import gradio as gr import torch from langchain.vectorstores import FAISS from langchain.embeddings import HuggingFaceEmbeddings from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate from langchain.llms import HuggingFacePipeline from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline from huggingface_hub import InferenceClient # Configuration for both components EMBEDDING_MODEL_NAME = "sentence-transformers/all-mpnet-base-v2" LLM_MODEL_NAME = "EleutherAI/gpt-neo-1.3B" CHAT_MODEL_NAME = "PygmalionAI/pygmalion-1.3b" # ------ Chat Component ------ chat_client = InferenceClient(CHAT_MODEL_NAME) def chat_respond( message: str, history: list[list[str]], system_message: str, max_tokens: int, temperature: float, top_p: float, ): messages = [{"role": "system", "content": system_message}] for human, assistant in history: messages.extend([ {"role": "user", "content": human}, {"role": "assistant", "content": assistant} ]) messages.append({"role": "user", "content": message}) response = "" for chunk in chat_client.chat_completion( messages, max_tokens=max_tokens, stream=True, temperature=temperature, top_p=top_p, ): token = chunk.choices[0].delta.content response += token yield response # ------ RAG Component ------ def load_embeddings(csv_path): df = pd.read_csv(csv_path) if 'Cleaned_Ideas' not in df.columns or 'Embeddings' not in df.columns: raise ValueError("CSV must contain 'Cleaned_Ideas' and 'Embeddings' columns") df['Embeddings'] = df['Embeddings'].apply( lambda x: np.fromstring( x.strip("[]").replace("\n", ""), sep=", ", dtype=np.float32 ) ) expected_dim = 768 valid_embeddings = df['Embeddings'].apply(lambda x: len(x) == expected_dim) if not valid_embeddings.all(): invalid_count = len(df) - valid_embeddings.sum() raise ValueError(f"{invalid_count} entries have invalid embedding dimensions") return df['Cleaned_Ideas'].tolist(), np.array(df['Embeddings'].tolist()) # Fixed here → ↑ def setup_rag_system(): # Load data and create vector store texts, embeddings = load_embeddings("ideas_with_embeddings.csv") embedding_model = HuggingFaceEmbeddings( model_name=EMBEDDING_MODEL_NAME, model_kwargs={'device': 'cpu'}, encode_kwargs={'normalize_embeddings': True} ) vector_store = FAISS.from_embeddings( text_embeddings=list(zip(texts, embeddings)), embedding=embedding_model, normalize_L2=True ) # Load LLM tokenizer = AutoTokenizer.from_pretrained(LLM_MODEL_NAME) model = AutoModelForCausalLM.from_pretrained( LLM_MODEL_NAME, device_map="auto", torch_dtype=torch.float16, trust_remote_code=True ) pipe = pipeline( "text-generation", model=model, tokenizer=tokenizer, max_new_tokens=250, temperature=0.7, top_p=0.9, repetition_penalty=1.1, do_sample=True, return_full_text=False, pad_token_id=tokenizer.eos_token_id ) # Setup QA chain template = """ {context} {question} Analyze the philosophical concept using ONLY the provided context. Follow these steps: 1. Identify key elements from the context 2. Explain relationships between concepts 3. Highlight any mentioned philosophical implications If context is insufficient, state: "This requires deeper analysis beyond current knowledge." Answer:""" qa_chain = RetrievalQA.from_chain_type( llm=HuggingFacePipeline(pipeline=pipe), chain_type="stuff", retriever=vector_store.as_retriever( search_type="similarity_score_threshold", search_kwargs={ "k": 6, "score_threshold": 0.55, "include_metadata": True } ), return_source_documents=True, chain_type_kwargs={ "prompt": PromptTemplate( template=template, input_variables=["context", "question"], template_format="f-string" ) }, verbose=True ) return qa_chain # ------ Unified Interface ------ def create_interface(): qa_chain = setup_rag_system() with gr.Blocks(title="Philosophical AI Assistant") as demo: gr.Markdown("# 🤖 AI Philosophy Assistant") gr.Markdown("Combining conversational AI with philosophical knowledge base") # Chat Tab with gr.Tab("Chat"): gr.ChatInterface( fn=chat_respond, additional_inputs=[ gr.Textbox(value="You are a philosophy expert assistant.", label="System Role"), gr.Slider(1, 2048, value=512, label="Max Tokens"), gr.Slider(0.1, 4.0, value=0.7, label="Temperature"), gr.Slider(0.1, 1.0, value=0.95, label="Top-p") ], chatbot=gr.Chatbot(height=500, avatar_images=("👤", "🤖")), textbox=gr.Textbox(placeholder="Ask me anything about philosophy...", container=False, scale=7), ) # Research Assistant Tab with gr.Tab("Research Assistant"): with gr.Row(): with gr.Column(scale=3): query_input = gr.Textbox(label="Research Query", lines=3) submit_btn = gr.Button("Analyze", variant="primary") with gr.Column(scale=2): sources_output = gr.Markdown(label="Source Context") response_output = gr.Markdown(label="Analysis Results") def process_query(query): try: result = qa_chain({"query": query}) response = result['result'].split("Answer:")[-1].strip() sources = "\n".join( f"**Source {i+1}:** {doc.page_content[:200]}..." for i, doc in enumerate(result['source_documents'][:3]) ) return response, sources except Exception as e: return f"Error: {str(e)}", "" submit_btn.click( process_query, inputs=query_input, outputs=[response_output, sources_output] ) return demo if __name__ == "__main__": demo = create_interface() demo.launch(share=True)