Refactor schemas and configuration for marketing assistant; add new test endpoints and utility functions for file handling and document processing
This commit is contained in:
@@ -1,91 +1,132 @@
|
||||
from langchain.retrievers import ContextualCompressionRetriever
|
||||
from langchain.retrievers.document_compressors import CrossEncoderReranker
|
||||
from typing import List, Dict
|
||||
import requests
|
||||
from langchain_groq import ChatGroq
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
from langchain_core.output_parsers import StrOutputParser
|
||||
from langchain_core.runnables import RunnablePassthrough
|
||||
from config import settings
|
||||
from utils import CustomEmbeddings, CustomCrossEncoder
|
||||
from langchain_chroma import Chroma
|
||||
from chromadb.api.types import Documents, EmbeddingFunction
|
||||
from config import (
|
||||
MODEL_NAME, RERANKER_NAME, API_KEY,
|
||||
SERVER_URL, GROQ_API_KEY, GROQ_MODEL
|
||||
)
|
||||
|
||||
class RAGSystem:
|
||||
def __init__(self):
|
||||
self.embeddings = CustomEmbeddings(settings.MODEL_NAME)
|
||||
self.reranker = CrossEncoderReranker(
|
||||
model=CustomCrossEncoder(settings.RERANKER_NAME),
|
||||
top_n=5
|
||||
)
|
||||
class CustomEmbeddingFunction(EmbeddingFunction):
|
||||
def __init__(self, model_name: str):
|
||||
self.model_name = model_name
|
||||
self._api_key = API_KEY
|
||||
self._server_url = SERVER_URL
|
||||
|
||||
def __call__(self, input: Documents) -> List[List[float]]:
|
||||
"""Implementation of the embedding function"""
|
||||
if not input:
|
||||
return []
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self._api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
payload = {
|
||||
"model": self.model_name,
|
||||
"input": input
|
||||
}
|
||||
|
||||
self.vector_store = Chroma(
|
||||
collection_name=settings.COLLECTION_NAME,
|
||||
persist_directory=settings.CHROMA_PATH,
|
||||
embedding_function=self.embeddings
|
||||
)
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{self._server_url}/embeddings",
|
||||
json=payload,
|
||||
headers=headers
|
||||
)
|
||||
response.raise_for_status()
|
||||
return [item['embedding'] for item in response.json()['data']]
|
||||
except Exception as e:
|
||||
print(f"Error in embedding: {str(e)}")
|
||||
raise
|
||||
|
||||
class CustomReranker:
|
||||
def __init__(self, model_name: str):
|
||||
self.model_name = model_name
|
||||
self._api_key = API_KEY
|
||||
self._server_url = SERVER_URL
|
||||
|
||||
def rerank(self, query: str, documents: List[Dict], top_k: int = 5) -> List[Dict]:
|
||||
"""
|
||||
Rerank documents using the reranking model
|
||||
"""
|
||||
if not documents:
|
||||
return []
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self._api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
self.retriever = ContextualCompressionRetriever(
|
||||
base_compressor=self.reranker,
|
||||
base_retriever=self.vector_store.as_retriever(search_kwargs={"k": 10})
|
||||
)
|
||||
payload = {
|
||||
"model": self.model_name,
|
||||
"query": query,
|
||||
"documents": [doc['content'] for doc in documents]
|
||||
}
|
||||
|
||||
self.llm = ChatGroq(
|
||||
temperature=0.01,
|
||||
groq_api_key=settings.GROQ_API_KEY,
|
||||
model_name=settings.GROQ_MODEL
|
||||
)
|
||||
|
||||
self.prompt = ChatPromptTemplate.from_template("""
|
||||
Act like you are Adriana James, write marketing copy in her signature style. Just mimic her style and provide the answer to the user's query. Make sure that you are Adriana James, and you are providing the answer to the user's query.
|
||||
try:
|
||||
response = requests.post(
|
||||
f"{self._server_url}/rerank",
|
||||
json=payload,
|
||||
headers=headers
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
# Get reranked results
|
||||
reranked_results = response.json()['results']
|
||||
|
||||
# Sort documents based on reranking scores
|
||||
reranked_docs = []
|
||||
for result in reranked_results[:top_k]:
|
||||
doc_idx = result['index']
|
||||
doc = documents[doc_idx].copy()
|
||||
doc['relevance_score'] = result['relevance_score']
|
||||
reranked_docs.append(doc)
|
||||
|
||||
return reranked_docs
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error in reranking: {str(e)}")
|
||||
return documents # Fall back to original ordering if reranking fails
|
||||
|
||||
Here is some of her past **Email_Templates**:
|
||||
# Initialize global instances
|
||||
EMBED_FUNCTION = CustomEmbeddingFunction(model_name=MODEL_NAME)
|
||||
RERANKER = CustomReranker(model_name=RERANKER_NAME)
|
||||
LLM = ChatGroq(temperature=0.01, groq_api_key=GROQ_API_KEY, model_name=GROQ_MODEL)
|
||||
|
||||
Template - 1:
|
||||
Dear friend,
|
||||
|
||||
As we approach the final days of 2024, I wanted to reach out with a message of hope and possibility for the year ahead. The dawn of 2025 brings with it an opportunity not just for fresh starts, but for transformative growth and achievement.
|
||||
You may have already begun thinking about your aspirations for the coming year. Whether you have or haven't, I'd like to personally invite you to join me for an intimate goal-setting session where we'll work together to crystallize your vision for 2025.
|
||||
I believe that every remarkable success story begins with clarity - knowing exactly what you want and placing it firmly in your future Time Line in a way that makes it inevitable. This isn't just about writing down wishes; it's about crafting the blueprint for your next chapter.
|
||||
Before our session, I encourage you to reflect on three crucial questions:
|
||||
|
||||
1. What is the most important achievement you envision for 2025?
|
||||
2. How can you leverage your unique experiences and skills to create positive change in the world?
|
||||
3. What stepping stones will you need to place along your path to ensure your primary goal becomes reality?
|
||||
|
||||
Here's what makes this journey so powerful: as you pursue specific goals, you naturally develop new skills, strategies, and behaviors. Sometimes, achieving a goal requires you to become an entirely new version of yourself - and that transformation is often the most valuable reward of all.
|
||||
Join me for this complimentary goal-setting session:
|
||||
Date: Thursday 15 January 2025
|
||||
Time: 4pm AEDT
|
||||
Register Today
|
||||
The more attention you invest in this process, the more you'll free yourself from limitations, unleash your creativity, and uncover possibilities you never imagined. This creates a beautiful cycle: greater goals lead to greater successes, which build self-confidence and positive momentum.
|
||||
Register today for this special session. I look forward to helping you lay the foundation for an extraordinary 2025.
|
||||
Be Well!
|
||||
|
||||
Template - 2:
|
||||
Hi [[contact.first_name]],
|
||||
I trust you've been putting the valuable insights from our recent Goal-Setting Masterclass to good use. I hope you've had a chance to dive into the videos and set your sights on exciting goals for 2025 across all areas of your life -career, relationships, finance, health, and beyond.
|
||||
Now, I'm thrilled to invite you to join me for an exclusive live Q&A session on Monday, February 3rd, 2025, at 7PM AEDT. This is your opportunity to delve deeper into the techniques shared and learn more about how to make 2025 truly exceptional.
|
||||
Whether you're looking to fine-tune your objectives, overcome obstacles, or gain more insights into applying these powerful techniques, I'm here to support you. Let's work together to make sure you're fully equipped to create a prosperous and successful year in every aspect of your life.
|
||||
Come prepared with your questions, and let's turn your 2025 goals into reality!
|
||||
Zoom details
|
||||
Be Well!
|
||||
Dr Adriana James and team
|
||||
For more information
|
||||
visit www.nlpcoaching.com or email us via info@nlpcoaching.com | Copyright 2025 The Tad James Company. All rights reserved. Australia/International: 90-96 Bourke Road Alexandria, NSW 2015 United States / International: 1450 W Horizon Ridge Pkway #544, Henderson NV, 89012 Unsubscribe
|
||||
|
||||
|
||||
Query: {question}
|
||||
Adriana James Resource Context: {context}
|
||||
|
||||
Now, write marketing copy in Adriana James' signature style from the context(Adriana James content) above and provide the answer to the user's query.
|
||||
|
||||
Note: Don't provide anything extra. Just give me the response no extra words nothing at all. Just the response to the user's query.
|
||||
""")
|
||||
|
||||
self.rag_chain = (
|
||||
{"context": self.retriever, "question": RunnablePassthrough()}
|
||||
| self.prompt
|
||||
| self.llm
|
||||
| StrOutputParser()
|
||||
)
|
||||
def format_context(documents: List[Dict]) -> str:
|
||||
"""Format retrieved documents into a context string"""
|
||||
context_parts = []
|
||||
for doc in documents:
|
||||
metadata = doc['metadata']
|
||||
category = metadata.get('category', 'unknown')
|
||||
content = doc['content']
|
||||
context_parts.append(f"[{category.upper()}]\n{content}\n")
|
||||
|
||||
def get_response(self, question: str) -> str:
|
||||
return self.rag_chain.invoke(question)
|
||||
return "\n".join(context_parts)
|
||||
|
||||
# Template for marketing copy
|
||||
TEMPLATE = """
|
||||
Act like you are Adriana James, write marketing copy in her signature style. Just mimic her style and provide the answer to the user's query. Make sure that you are Adriana James, and you are providing the answer to the user's query.
|
||||
|
||||
Query: {question}
|
||||
Adriana James Resource Context: {context}
|
||||
|
||||
Note: Don't provide anything extra. Just give me the response no extra words nothing at all.
|
||||
"""
|
||||
|
||||
PROMPT = ChatPromptTemplate.from_template(TEMPLATE)
|
||||
|
||||
def generate_marketing_response(query: str, context: str) -> str:
|
||||
"""Generate marketing response using RAG"""
|
||||
chain = (
|
||||
PROMPT
|
||||
| LLM
|
||||
| StrOutputParser()
|
||||
)
|
||||
|
||||
return chain.invoke({
|
||||
"question": query,
|
||||
"context": context
|
||||
})
|
||||
Reference in New Issue
Block a user