|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<meta charset="UTF-8"> |
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
<title>Al Ghazali RAG API Documentation</title> |
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.29.0/themes/prism-tomorrow.min.css" rel="stylesheet" /> |
|
<link href="style.css" rel="stylesheet" /> |
|
</head> |
|
<body> |
|
<div class="container"> |
|
<nav class="sidebar"> |
|
<div class="logo"> |
|
🔗 Al Ghazali RAG API |
|
</div> |
|
<div class="nav-items"> |
|
|
|
</div> |
|
</nav> |
|
<main class="content"> |
|
<h1>Al Ghazali RAG Retrieval API</h1> |
|
|
|
<section id="endpoints"> |
|
<h2>Endpoints</h2> |
|
|
|
<div class="endpoint" id="login"> |
|
<h3>1. Login Endpoint</h3> |
|
<p><span class="method">POST</span><span class="endpoint-url">/login</span></p> |
|
<p>This endpoint is used to authenticate the user and issue an access token and a refresh token.</p> |
|
|
|
<h4>cURL Request:</h4> |
|
<pre><code class="language-bash">curl -X POST https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/login \ |
|
-H "Content-Type: application/x-www-form-urlencoded" \ |
|
-d 'username=user123&password=password123'</code></pre> |
|
|
|
<h4>Flutter Implementation:</h4> |
|
<pre><code class="language-dart">Future<LoginResponse> login(String username, String password) async { |
|
final url = Uri.parse('https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/login'); |
|
|
|
try { |
|
final response = await http.post( |
|
url, |
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'}, |
|
body: { |
|
'username': username, |
|
'password': password, |
|
}, |
|
); |
|
|
|
if (response.statusCode == 200) { |
|
return LoginResponse.fromJson(jsonDecode(response.body)); |
|
} else { |
|
throw Exception('Failed to login: ${response.body}'); |
|
} |
|
} catch (e) { |
|
throw Exception('Network error: $e'); |
|
} |
|
} |
|
|
|
// Model class |
|
class LoginResponse { |
|
final String accessToken; |
|
final String refreshToken; |
|
final String tokenType; |
|
final int expiresIn; |
|
|
|
LoginResponse({ |
|
required this.accessToken, |
|
required this.refreshToken, |
|
required this.tokenType, |
|
required this.expiresIn, |
|
}); |
|
|
|
factory LoginResponse.fromJson(Map<String, dynamic> json) { |
|
return LoginResponse( |
|
accessToken: json['access_token'], |
|
refreshToken: json['refresh_token'], |
|
tokenType: json['token_type'], |
|
expiresIn: json['expires_in'], |
|
); |
|
} |
|
}</code></pre> |
|
|
|
<h4>Response:</h4> |
|
<pre><code class="language-json">{ |
|
"access_token": "your-access-token", |
|
"refresh_token": "your-refresh-token", |
|
"token_type": "bearer", |
|
"expires_in": 1800 |
|
}</code></pre> |
|
</div> |
|
|
|
<div class="endpoint" id="refresh"> |
|
<h3>2. Refresh Token Endpoint</h3> |
|
<p><span class="method">POST</span><span class="endpoint-url">/refresh</span></p> |
|
<p>This endpoint is used to refresh the access token using a valid refresh token.</p> |
|
|
|
<h4>cURL Request:</h4> |
|
<pre><code class="language-bash">curl -X POST https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/refresh \ |
|
-H "Content-Type: application/json" \ |
|
-d '{"refresh_token": "your-refresh-token"}'</code></pre> |
|
|
|
<h4>Flutter Implementation:</h4> |
|
<pre><code class="language-dart">Future<LoginResponse> refreshToken(String refreshToken) async { |
|
final url = Uri.parse('https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/refresh'); |
|
|
|
try { |
|
final response = await http.post( |
|
url, |
|
headers: {'Content-Type': 'application/json'}, |
|
body: jsonEncode({ |
|
'refresh_token': refreshToken, |
|
}), |
|
); |
|
|
|
if (response.statusCode == 200) { |
|
return LoginResponse.fromJson(jsonDecode(response.body)); |
|
} else { |
|
throw Exception('Failed to refresh token: ${response.body}'); |
|
} |
|
} catch (e) { |
|
throw Exception('Network error: $e'); |
|
} |
|
}</code></pre> |
|
|
|
<h4>Response:</h4> |
|
<pre><code class="language-json">{ |
|
"access_token": "new-access-token", |
|
"refresh_token": "your-refresh-token", |
|
"token_type": "bearer", |
|
"expires_in": 1800 |
|
}</code></pre> |
|
</div> |
|
|
|
<div class="endpoint" id="search"> |
|
<h3>3. Search Endpoint</h3> |
|
<p><span class="method">POST</span><span class="endpoint-url">/search</span></p> |
|
<p>This endpoint is used to send a search query and retrieve results. It requires a valid access token.</p> |
|
|
|
<h4>cURL Request:</h4> |
|
<pre><code class="language-bash">curl -X POST https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/search \ |
|
-H "Content-Type: application/json" \ |
|
-H "Authorization: Bearer your-access-token" \ |
|
-d '{"query": "test query"}'</code></pre> |
|
|
|
<h4>Flutter Implementation:</h4> |
|
<pre><code class="language-dart">class SearchResult { |
|
final String text; |
|
final double similarity; |
|
|
|
SearchResult({ |
|
required this.text, |
|
required this.similarity, |
|
}); |
|
|
|
factory SearchResult.fromJson(Map<String, dynamic> json) { |
|
return SearchResult( |
|
text: json['text'], |
|
similarity: json['similarity'].toDouble(), |
|
); |
|
} |
|
} |
|
|
|
Future<List<SearchResult>> search(String query, String accessToken) async { |
|
final url = Uri.parse('https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/search'); |
|
|
|
try { |
|
final response = await http.post( |
|
url, |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'Authorization': 'Bearer $accessToken', |
|
}, |
|
body: jsonEncode({ |
|
'query': query, |
|
}), |
|
); |
|
|
|
if (response.statusCode == 200) { |
|
List<dynamic> jsonList = jsonDecode(response.body); |
|
return jsonList.map((json) => SearchResult.fromJson(json)).toList(); |
|
} else { |
|
throw Exception('Search failed: ${response.body}'); |
|
} |
|
} catch (e) { |
|
throw Exception('Network error: $e'); |
|
} |
|
}</code></pre> |
|
|
|
<h4>Response:</h4> |
|
<pre><code class="language-json">[ |
|
{ |
|
"text": "Result 1 text", |
|
"similarity": 0.95 |
|
}, |
|
{ |
|
"text": "Result 2 text", |
|
"similarity": 0.92 |
|
}, |
|
{ |
|
"text": "Result 3 text", |
|
"similarity": 0.89 |
|
} |
|
]</code></pre> |
|
</div> |
|
</section> |
|
|
|
<section id="workflow"> |
|
<h2>Workflow Example</h2> |
|
<p>Here's a complete workflow demonstrating how to use the API:</p> |
|
|
|
<h3>cURL Implementation</h3> |
|
<div class="endpoint"> |
|
<h3>Step 1: Login</h3> |
|
<pre><code class="language-bash">curl -X POST https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/login \ |
|
-H "Content-Type: application/x-www-form-urlencoded" \ |
|
-d 'username=user123&password=password123'</code></pre> |
|
</div> |
|
|
|
<div class="endpoint"> |
|
<h3>Step 2: Search</h3> |
|
<pre><code class="language-bash">curl -X POST https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/search \ |
|
-H "Content-Type: application/json" \ |
|
-H "Authorization: Bearer your-access-token" \ |
|
-d '{"query": "test query"}'</code></pre> |
|
</div> |
|
|
|
<div class="endpoint"> |
|
<h3>Step 3: Refresh Token</h3> |
|
<pre><code class="language-bash">curl -X POST https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/refresh \ |
|
-H "Content-Type: application/json" \ |
|
-d '{"refresh_token": "your-refresh-token"}'</code></pre> |
|
</div> |
|
|
|
<h3>Flutter Implementation</h3> |
|
<div class="endpoint"> |
|
<h4>Complete Flutter Example</h4> |
|
<pre><code class="language-dart">import 'dart:convert'; |
|
import 'package:flutter/material.dart'; |
|
import 'package:http/http.dart' as http; |
|
|
|
void main() { |
|
runApp(MyApp()); |
|
} |
|
|
|
class MyApp extends StatelessWidget { |
|
@override |
|
Widget build(BuildContext context) { |
|
return MaterialApp( |
|
title: 'Al Ghazali RAG API Example', |
|
home: ApiWorkflowExample(), |
|
); |
|
} |
|
} |
|
|
|
class ApiWorkflowExample extends StatefulWidget { |
|
@override |
|
_ApiWorkflowExampleState createState() => _ApiWorkflowExampleState(); |
|
} |
|
|
|
class _ApiWorkflowExampleState extends State<ApiWorkflowExample> { |
|
String _accessToken = ''; |
|
String _refreshToken = ''; |
|
List<SearchResult> _searchResults = []; |
|
|
|
Future<void> _login() async { |
|
final username = 'user123'; |
|
final password = 'password123'; |
|
|
|
try { |
|
final loginResponse = await login(username, password); |
|
setState(() { |
|
_accessToken = loginResponse.accessToken; |
|
_refreshToken = loginResponse.refreshToken; |
|
}); |
|
ScaffoldMessenger.of(context).showSnackBar( |
|
SnackBar(content: Text('Login successful!')), |
|
); |
|
} catch (e) { |
|
ScaffoldMessenger.of(context).showSnackBar( |
|
SnackBar(content: Text('Login failed: $e')), |
|
); |
|
} |
|
} |
|
|
|
Future<void> _search() async { |
|
final query = 'test query'; |
|
|
|
try { |
|
final results = await search(query, _accessToken); |
|
setState(() { |
|
_searchResults = results; |
|
}); |
|
ScaffoldMessenger.of(context).showSnackBar( |
|
SnackBar(content: Text('Search successful!')), |
|
); |
|
} catch (e) { |
|
ScaffoldMessenger.of(context).showSnackBar( |
|
SnackBar(content: Text('Search failed: $e')), |
|
); |
|
} |
|
} |
|
|
|
Future<void> _refreshToken() async { |
|
try { |
|
final loginResponse = await refreshToken(_refreshToken); |
|
setState(() { |
|
_accessToken = loginResponse.accessToken; |
|
}); |
|
ScaffoldMessenger.of(context).showSnackBar( |
|
SnackBar(content: Text('Token refreshed successfully!')), |
|
); |
|
} catch (e) { |
|
ScaffoldMessenger.of(context).showSnackBar( |
|
SnackBar(content: Text('Token refresh failed: $e')), |
|
); |
|
} |
|
} |
|
|
|
@override |
|
Widget build(BuildContext context) { |
|
return Scaffold( |
|
appBar: AppBar( |
|
title: Text('Al Ghazali RAG API Workflow'), |
|
), |
|
body: Padding( |
|
padding: const EdgeInsets.all(16.0), |
|
child: Column( |
|
crossAxisAlignment: CrossAxisAlignment.stretch, |
|
children: [ |
|
ElevatedButton( |
|
onPressed: _login, |
|
child: Text('Login'), |
|
), |
|
ElevatedButton( |
|
onPressed: _search, |
|
child: Text('Search'), |
|
), |
|
ElevatedButton( |
|
onPressed: _refreshToken, |
|
child: Text('Refresh Token'), |
|
), |
|
Expanded( |
|
child: ListView.builder( |
|
itemCount: _searchResults.length, |
|
itemBuilder: (context, index) { |
|
final result = _searchResults[index]; |
|
return ListTile( |
|
title: Text(result.text), |
|
subtitle: Text('Similarity: ${result.similarity}'), |
|
); |
|
}, |
|
), |
|
), |
|
], |
|
), |
|
), |
|
); |
|
} |
|
} |
|
|
|
Future<LoginResponse> login(String username, String password) async { |
|
final url = Uri.parse('https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/login'); |
|
|
|
try { |
|
final response = await http.post( |
|
url, |
|
headers: {'Content-Type': 'application/x-www-form-urlencoded'}, |
|
body: { |
|
'username': username, |
|
'password': password, |
|
}, |
|
); |
|
|
|
if (response.statusCode == 200) { |
|
return LoginResponse.fromJson(jsonDecode(response.body)); |
|
} else { |
|
throw Exception('Failed to login: ${response.body}'); |
|
} |
|
} catch (e) { |
|
throw Exception('Network error: $e'); |
|
} |
|
} |
|
|
|
Future<LoginResponse> refreshToken(String refreshToken) async { |
|
final url = Uri.parse('https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/refresh'); |
|
|
|
try { |
|
final response = await http.post( |
|
url, |
|
headers: {'Content-Type': 'application/json'}, |
|
body: jsonEncode({ |
|
'refresh_token': refreshToken, |
|
}), |
|
); |
|
|
|
if (response.statusCode == 200) { |
|
return LoginResponse.fromJson(jsonDecode(response.body)); |
|
} else { |
|
throw Exception('Failed to refresh token: ${response.body}'); |
|
} |
|
} catch (e) { |
|
throw Exception('Network error: $e'); |
|
} |
|
} |
|
|
|
Future<List<SearchResult>> search(String query, String accessToken) async { |
|
final url = Uri.parse('https://humblebeeai-al-ghazali-rag-retrieval-api.hf.space/search'); |
|
|
|
try { |
|
final response = await http.post( |
|
url, |
|
headers: { |
|
'Content-Type': 'application/json', |
|
'Authorization': 'Bearer $accessToken', |
|
}, |
|
body: jsonEncode({ |
|
'query': query, |
|
}), |
|
); |
|
|
|
if (response.statusCode == 200) { |
|
List<dynamic> jsonList = jsonDecode(response.body); |
|
return jsonList.map((json) => SearchResult.fromJson(json)).toList(); |
|
} else { |
|
throw Exception('Search failed: ${response.body}'); |
|
} |
|
} catch (e) { |
|
throw Exception('Network error: $e'); |
|
} |
|
} |
|
|
|
class LoginResponse { |
|
final String accessToken; |
|
final String refreshToken; |
|
final String tokenType; |
|
final int expiresIn; |
|
|
|
LoginResponse({ |
|
required this.accessToken, |
|
required this.refreshToken, |
|
required this.tokenType, |
|
required this.expiresIn, |
|
}); |
|
|
|
factory LoginResponse.fromJson(Map<String, dynamic> json) { |
|
return LoginResponse( |
|
accessToken: json['access_token'], |
|
refreshToken: json['refresh_token'], |
|
tokenType: json['token_type'], |
|
expiresIn: json['expires_in'], |
|
); |
|
} |
|
} |
|
|
|
class SearchResult { |
|
final String text; |
|
final double similarity; |
|
|
|
SearchResult({ |
|
required this.text, |
|
required this.similarity, |
|
}); |
|
|
|
factory SearchResult.fromJson(Map<String, dynamic> json) { |
|
return SearchResult( |
|
text: json['text'], |
|
similarity: json['similarity'].toDouble(), |
|
); |
|
} |
|
} |
|
</main> |
|
</div> |
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.29.0/prism.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.29.0/components/prism-bash.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/prismjs/1.29.0/components/prism-json.min.js"></script> |
|
<script src="script.js"></script> |
|
</body> |
|
</html> |