1+ """
2+ Naas GPT-4 Agent - Working implementation using reverse-engineered API
3+ Consolidates all working code from capture_naas_requests.py, chat_gpt4.py, chat_naas.py
4+ """
5+
6+ import os
7+ import json
8+ import httpx
9+ from typing import Dict , Any
10+ from dotenv import load_dotenv
11+
12+ load_dotenv ()
13+
14+ class NaasGPT4Agent :
15+ """Working Naas GPT-4 agent using reverse-engineered API"""
16+
17+ def __init__ (self ):
18+ # Working configuration from reverse engineering
19+ self .base_url = "https://api.naas.ai"
20+ self .chat_id = int (os .getenv ("NAAS_CHAT_ID" , "15349" )) # Configurable chat ID
21+ self .model_id = "507dbbc5-88a1-4bd7-8c35-28cea3faaf1f" # GPT-4 model ID
22+
23+ # Get token from environment
24+ self .token = os .getenv ("NAAS_TOKEN" )
25+ if not self .token :
26+ raise ValueError ("NAAS_TOKEN not found in .env - add your JWT token" )
27+
28+ # Exact working headers from reverse engineering
29+ self .headers = {
30+ "accept" : "*/*" ,
31+ "accept-language" : "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7" ,
32+ "authorization" : f"Bearer { self .token } " ,
33+ "content-type" : "application/json" ,
34+ "origin" : "https://naas.ai" ,
35+ "referer" : "https://naas.ai/" ,
36+ "sec-ch-ua" : '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"' ,
37+ "sec-ch-ua-mobile" : "?0" ,
38+ "sec-ch-ua-platform" : '"Windows"' ,
39+ "sec-fetch-dest" : "empty" ,
40+ "sec-fetch-mode" : "cors" ,
41+ "sec-fetch-site" : "same-site" ,
42+ "user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
43+ }
44+
45+ # HTTP client with SSL bypass for corporate environments
46+ self .client = httpx .Client (
47+ verify = False ,
48+ headers = self .headers ,
49+ timeout = 60.0
50+ )
51+
52+ # Conversation history
53+ self .conversation_history = []
54+
55+ def chat (self , message : str ) -> Dict [str , Any ]:
56+ """Send message to GPT-4 using working reverse-engineered format"""
57+
58+ try :
59+ # Add to conversation history
60+ self .conversation_history .append ({"role" : "user" , "content" : message })
61+
62+ # Build context-aware prompt
63+ context_prompt = self ._build_context_prompt (message )
64+
65+ # Exact working format from reverse engineering
66+ prompt = f"@[openai/gpt-4]{{MODEL::{ self .model_id } }} { context_prompt } "
67+
68+ # Working payload structure
69+ payload = {
70+ "id" : self .chat_id ,
71+ "model_id" : self .model_id ,
72+ "payload" : json .dumps ({
73+ "prompt" : prompt ,
74+ "temperature" : 0.7
75+ })
76+ }
77+
78+ endpoint = f"{ self .base_url } /chat/{ self .chat_id } /completion"
79+
80+ response = self .client .post (endpoint , json = payload )
81+
82+ if response .status_code == 200 :
83+ data = response .json ()
84+
85+ # Extract response content
86+ content = self ._extract_response_content (data )
87+
88+ # Add to conversation history
89+ self .conversation_history .append ({"role" : "assistant" , "content" : content })
90+
91+ return {
92+ "success" : True ,
93+ "content" : content ,
94+ "tokens" : {
95+ "input" : data .get ("input_tokens" , 0 ),
96+ "output" : data .get ("output_tokens" , 0 )
97+ }
98+ }
99+ else :
100+ return {
101+ "success" : False ,
102+ "error" : f"API returned { response .status_code } : { response .text } "
103+ }
104+
105+ except Exception as e :
106+ return {
107+ "success" : False ,
108+ "error" : f"Request failed: { str (e )} "
109+ }
110+
111+ def _build_context_prompt (self , current_message : str ) -> str :
112+ """Build context-aware prompt with conversation history"""
113+
114+ # Keep last 6 messages for context
115+ recent_history = self .conversation_history [- 6 :] if len (self .conversation_history ) > 6 else self .conversation_history
116+
117+ if not recent_history :
118+ return current_message
119+
120+ # Build context
121+ context_parts = []
122+ for msg in recent_history :
123+ role = "User" if msg ["role" ] == "user" else "Assistant"
124+ context_parts .append (f"{ role } : { msg ['content' ]} " )
125+
126+ context_parts .append (f"User: { current_message } " )
127+ context_parts .append ("Assistant:" )
128+
129+ return "\\ n" .join (context_parts )
130+
131+ def _extract_response_content (self , api_response : Dict [str , Any ]) -> str :
132+ """Extract GPT-4 response from API response"""
133+
134+ try :
135+ # Extract from Naas API response structure
136+ if "completion" in api_response and "messages" in api_response ["completion" ]:
137+ messages = api_response ["completion" ]["messages" ]
138+ # Find the last message from the assistant (from_user: false)
139+ for message in reversed (messages ):
140+ if not message .get ("from_user" , True ): # Assistant message
141+ return message .get ("message" , "" ).strip ()
142+
143+ # Try standard OpenAI format
144+ if "choices" in api_response and api_response ["choices" ]:
145+ choice = api_response ["choices" ][0 ]
146+ if "message" in choice and "content" in choice ["message" ]:
147+ return choice ["message" ]["content" ].strip ()
148+ elif "text" in choice :
149+ return choice ["text" ].strip ()
150+
151+ if "response" in api_response :
152+ return api_response ["response" ].strip ()
153+
154+ if "content" in api_response :
155+ return api_response ["content" ].strip ()
156+
157+ if "text" in api_response :
158+ return api_response ["text" ].strip ()
159+
160+ # Fallback - return formatted response
161+ return f"Response received: { json .dumps (api_response , indent = 2 )} "
162+
163+ except Exception as e :
164+ return f"Error extracting response: { str (e )} "
165+
166+ def clear_conversation (self ):
167+ """Clear conversation history"""
168+ self .conversation_history = []
169+ return {"success" : True , "message" : "Conversation cleared" }
170+
171+ def get_conversation_summary (self ):
172+ """Get conversation summary"""
173+ return {
174+ "success" : True ,
175+ "message_count" : len (self .conversation_history ),
176+ "recent_messages" : self .conversation_history [- 4 :] if self .conversation_history else []
177+ }
178+
179+
180+ def create_agent ():
181+ """Factory function for ABI module system"""
182+ return NaasGPT4Agent ()
0 commit comments