Arvind2006 commited on
Commit
657c233
·
verified ·
1 Parent(s): 3ecb282

Update langchain_rag.py

Browse files
Files changed (1) hide show
  1. langchain_rag.py +162 -156
langchain_rag.py CHANGED
@@ -1,156 +1,162 @@
1
- # langchain_rag.py
2
- # LangChain-based RAG pipeline for Jenkins error explanation
3
-
4
- import os
5
- import json
6
- import tempfile
7
- from typing import List, Dict, Any
8
-
9
- from langchain_core.documents import Document
10
- from langchain_core.prompts import PromptTemplate
11
- from langchain_core.output_parsers import StrOutputParser
12
- from langchain_huggingface import HuggingFaceEmbeddings
13
- from langchain_community.vectorstores import FAISS
14
- from langchain_community.llms import HuggingFaceHub
15
- from langchain.chains import RetrievalQA
16
-
17
- from extract_error_features import extract_error_features
18
-
19
- RAW_DOCS_DIR = "data/docs/raw"
20
- CHUNK_SIZE = 400
21
-
22
- def load_raw_docs() -> List[Document]:
23
- """Load raw Jenkins documentation files and convert to LangChain Documents."""
24
- documents = []
25
-
26
- for fname in os.listdir(RAW_DOCS_DIR):
27
- path = os.path.join(RAW_DOCS_DIR, fname)
28
- with open(path, "r", encoding="utf-8") as f:
29
- text = f.read()
30
-
31
- chunks = chunk_text(text, CHUNK_SIZE)
32
- for chunk in chunks:
33
- documents.append(Document(
34
- page_content=chunk,
35
- metadata={
36
- "source_file": fname,
37
- "source": "https://www.jenkins.io/doc/"
38
- }
39
- ))
40
-
41
- return documents
42
-
43
- def chunk_text(text: str, size: int) -> List[str]:
44
- """Split text into chunks."""
45
- chunks = []
46
- for i in range(0, len(text), size):
47
- chunk = text[i:i+size].strip()
48
- if chunk:
49
- chunks.append(chunk)
50
- return chunks
51
-
52
- class JenkinsRAGChain:
53
- """LangChain-based RAG chain for Jenkins error explanation."""
54
-
55
- def __init__(self):
56
- self.embeddings = HuggingFaceEmbeddings(
57
- model_name="sentence-transformers/paraphrase-MiniLM-L3-v2",
58
- model_kwargs={'device': 'cpu'}
59
- )
60
-
61
- self.documents = load_raw_docs()
62
- self.vectorstore = FAISS.from_documents(
63
- self.documents,
64
- self.embeddings
65
- )
66
-
67
- self.retriever = self.vectorstore.as_retriever(
68
- search_kwargs={"k": 5}
69
- )
70
-
71
- self.llm = HuggingFaceHub(
72
- repo_id="google/flan-t5-base",
73
- model_kwargs={"temperature": 0.3, "max_new_tokens": 256}
74
- )
75
-
76
- self.prompt = PromptTemplate(
77
- template="""You are a Jenkins CI/CD expert. Use the following context from
78
- official Jenkins documentation to explain the error.
79
-
80
- Context from Jenkins documentation:
81
- {context}
82
-
83
- Error log to explain:
84
- {question}
85
-
86
- Provide a clear explanation with:
87
- 1. Error Summary
88
- 2. Likely Causes
89
- 3. Relevant Documentation links
90
-
91
- If the documentation doesn't cover this error, say so explicitly.""",
92
- input_variables=["context", "question"]
93
- )
94
-
95
- self.qa_chain = RetrievalQA.from_chain_type(
96
- llm=self.llm,
97
- chain_type="stuff",
98
- retriever=self.retriever,
99
- chain_type_kwargs={"prompt": self.prompt},
100
- output_parser=StrOutputParser()
101
- )
102
-
103
- def explain_error(self, log_text: str) -> Dict[str, Any]:
104
- """Explain a Jenkins error using LangChain RAG."""
105
- features = extract_error_features(log_text)
106
- category = features["category"]
107
-
108
- enhanced_query = f"""
109
- Error Category: {category}
110
-
111
- Jenkins log:
112
- {log_text}
113
-
114
- Explain this error using the retrieved documentation.
115
- """
116
-
117
- result = self.qa_chain.invoke(enhanced_query)
118
-
119
- return {
120
- "error_category": category,
121
- "llm_explanation": result,
122
- "retrieval_source": "LangChain RAG (FAISS + HuggingFace)",
123
- "model_used": "google/flan-t5-base",
124
- "embedding_model": "paraphrase-MiniLM-L3-v2"
125
- }
126
-
127
- def get_rag_chain() -> JenkinsRAGChain:
128
- """Get or create the RAG chain (singleton pattern for efficiency)."""
129
- if not hasattr(get_rag_chain, '_instance'):
130
- get_rag_chain._instance = JenkinsRAGChain()
131
- return get_rag_chain._instance
132
-
133
-
134
- if __name__ == "__main__":
135
- print("Initializing LangChain RAG Chain...")
136
- print("=" * 50)
137
-
138
- rag = JenkinsRAGChain()
139
-
140
- sample_error = """
141
- Started by user admin
142
- org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
143
- WorkflowScript: 10: expecting '}', found '' @ line 10, column 1.
144
- 1 error
145
- at org.codehaus.groovy.control.ErrorNode.accept(ErrorNode.java:36)
146
- at org.codehaus.groovy.control.CompilationUnit$3.call(CompilationUnit.java:698)
147
- """
148
-
149
- print("\nSample Jenkins Error:")
150
- print(sample_error)
151
- print("=" * 50)
152
-
153
- result = rag.explain_error(sample_error)
154
-
155
- print("\nResult from LangChain RAG:")
156
- print(json.dumps(result, indent=2))
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ from typing import List, Dict, Any
4
+
5
+ from langchain_core.documents import Document
6
+ from langchain_huggingface import HuggingFaceEmbeddings
7
+ from langchain_community.vectorstores import FAISS
8
+
9
+ from extract_error_features import extract_error_features
10
+
11
+ RAW_DOCS_DIR = "data/docs/raw"
12
+ CHUNK_SIZE = 400
13
+
14
+
15
+ # -------------------------
16
+ # Utils
17
+ # -------------------------
18
+ def chunk_text(text: str, size: int) -> List[str]:
19
+ chunks = []
20
+ for i in range(0, len(text), size):
21
+ chunk = text[i:i+size].strip()
22
+ if chunk:
23
+ chunks.append(chunk)
24
+ return chunks
25
+
26
+
27
+ def load_raw_docs() -> List[Document]:
28
+ documents = []
29
+
30
+ for fname in os.listdir(RAW_DOCS_DIR):
31
+ path = os.path.join(RAW_DOCS_DIR, fname)
32
+ with open(path, "r", encoding="utf-8") as f:
33
+ text = f.read()
34
+
35
+ chunks = chunk_text(text, CHUNK_SIZE)
36
+
37
+ for chunk in chunks:
38
+ documents.append(
39
+ Document(
40
+ page_content=chunk,
41
+ metadata={
42
+ "source_file": fname,
43
+ "source": "https://www.jenkins.io/doc/"
44
+ }
45
+ )
46
+ )
47
+
48
+ return documents
49
+
50
+
51
+ # -------------------------
52
+ # RAG CLASS
53
+ # -------------------------
54
+ class JenkinsRAGChain:
55
+ def __init__(self):
56
+ print("Loading embeddings...")
57
+
58
+ self.embeddings = HuggingFaceEmbeddings(
59
+ model_name="sentence-transformers/paraphrase-MiniLM-L3-v2",
60
+ model_kwargs={"device": "cpu"}
61
+ )
62
+
63
+ print("Loading documents...")
64
+ self.documents = load_raw_docs()
65
+
66
+ print("Building FAISS index...")
67
+ self.vectorstore = FAISS.from_documents(
68
+ self.documents,
69
+ self.embeddings
70
+ )
71
+
72
+ self.retriever = self.vectorstore.as_retriever(
73
+ search_kwargs={"k": 5}
74
+ )
75
+
76
+ # -------------------------
77
+ # Retrieval
78
+ # -------------------------
79
+ def retrieve_docs(self, query: str) -> List[Document]:
80
+ return self.retriever.invoke(query)
81
+
82
+ # -------------------------
83
+ # Simple Explanation Generator (NO LLM needed)
84
+ # -------------------------
85
+ def generate_explanation(self, query: str, docs: List[Document]) -> str:
86
+ context = "\n\n".join([doc.page_content for doc in docs])
87
+
88
+ return f"""
89
+ Jenkins Error Explanation
90
+
91
+ Context from documentation:
92
+ {context[:1500]}
93
+
94
+ Analysis:
95
+ Based on the retrieved documentation, this error likely relates to Jenkins pipeline or configuration issues.
96
+
97
+ Suggested Actions:
98
+ - Check Jenkinsfile syntax
99
+ - Verify plugins and agents
100
+ - Review pipeline configuration
101
+
102
+ Note:
103
+ This explanation is grounded in official Jenkins documentation.
104
+ """
105
+
106
+ # -------------------------
107
+ # Main API
108
+ # -------------------------
109
+ def explain_error(self, log_text: str) -> Dict[str, Any]:
110
+ features = extract_error_features(log_text)
111
+ category = features["category"]
112
+
113
+ query = f"""
114
+ Error Category: {category}
115
+
116
+ Jenkins log:
117
+ {log_text}
118
+ """
119
+
120
+ docs = self.retrieve_docs(query)
121
+
122
+ explanation = self.generate_explanation(query, docs)
123
+
124
+ return {
125
+ "error_category": category,
126
+ "llm_explanation": explanation,
127
+ "retrieved_docs": [
128
+ {
129
+ "content": doc.page_content[:200],
130
+ "source": doc.metadata.get("source")
131
+ }
132
+ for doc in docs
133
+ ],
134
+ "retrieval_source": "FAISS + sentence-transformers",
135
+ "embedding_model": "paraphrase-MiniLM-L3-v2"
136
+ }
137
+
138
+
139
+ # -------------------------
140
+ # Singleton
141
+ # -------------------------
142
+ def get_rag_chain() -> JenkinsRAGChain:
143
+ if not hasattr(get_rag_chain, "_instance"):
144
+ get_rag_chain._instance = JenkinsRAGChain()
145
+ return get_rag_chain._instance
146
+
147
+
148
+ # -------------------------
149
+ # Test
150
+ # -------------------------
151
+ if __name__ == "__main__":
152
+ print("Initializing RAG...")
153
+ rag = JenkinsRAGChain()
154
+
155
+ sample_error = """
156
+ org.codehaus.groovy.control.MultipleCompilationErrorsException:
157
+ WorkflowScript: 10: expecting '}', found ''
158
+ """
159
+
160
+ result = rag.explain_error(sample_error)
161
+
162
+ print(json.dumps(result, indent=2))