mirror of
https://github.com/run-llama/auto_rfp.git
synced 2026-07-01 21:54:05 -04:00
allow setting up an internal organization which accesses a separate llamacloud project
This commit is contained in:
@@ -80,6 +80,9 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY="your-supabase-anon-key"
|
||||
# AI Services
|
||||
OPENAI_API_KEY="your-openai-api-key"
|
||||
LLAMACLOUD_API_KEY="your-llamacloud-api-key"
|
||||
# Optional: Internal API key and domain for internal users
|
||||
# LLAMACLOUD_API_KEY_INTERNAL="your-internal-llamacloud-api-key"
|
||||
# INTERNAL_EMAIL_DOMAIN="@yourdomain.com" # Defaults to @runllama.ai
|
||||
|
||||
# App
|
||||
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
||||
|
||||
@@ -82,6 +82,9 @@ OPENAI_API_KEY="your-openai-api-key"
|
||||
|
||||
# LlamaCloud
|
||||
LLAMACLOUD_API_KEY="your-llamacloud-api-key"
|
||||
# Optional: Internal API key and domain for internal users
|
||||
# LLAMACLOUD_API_KEY_INTERNAL="your-internal-llamacloud-api-key"
|
||||
# INTERNAL_EMAIL_DOMAIN="@yourdomain.com" # Defaults to @runllama.ai
|
||||
|
||||
# App Configuration
|
||||
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
||||
@@ -217,6 +220,8 @@ NEXT_PUBLIC_SUPABASE_URL="your-supabase-url"
|
||||
NEXT_PUBLIC_SUPABASE_ANON_KEY="your-supabase-anon-key"
|
||||
OPENAI_API_KEY="your-openai-api-key"
|
||||
LLAMACLOUD_API_KEY="your-llamacloud-api-key"
|
||||
# LLAMACLOUD_API_KEY_INTERNAL="your-internal-llamacloud-api-key" # Optional: for internal users
|
||||
# INTERNAL_EMAIL_DOMAIN="@yourdomain.com" # Optional: defaults to @runllama.ai
|
||||
NEXT_PUBLIC_APP_URL="https://your-domain.com"
|
||||
```
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { NextRequest } from 'next/server';
|
||||
import { organizationService } from '@/lib/organization-service';
|
||||
import { db } from '@/lib/db';
|
||||
import { LlamaIndexService } from '@/lib/llama-index-service';
|
||||
import { getLlamaCloudApiKey } from '@/lib/env';
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
console.log('🎯 Multi-step API route called');
|
||||
@@ -117,8 +118,9 @@ export async function POST(request: NextRequest) {
|
||||
} else {
|
||||
console.log(`📋 Using index names: ${indexNames.join(', ')}`);
|
||||
|
||||
const apiKey = getLlamaCloudApiKey(currentUser.email);
|
||||
const llamaIndexService = new LlamaIndexService({
|
||||
apiKey: process.env.LLAMACLOUD_API_KEY!,
|
||||
apiKey: apiKey,
|
||||
projectName: project.organization.llamaCloudProjectName || 'Default',
|
||||
indexNames: indexNames,
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
import { apiHandler } from '@/lib/middleware/api-handler';
|
||||
import { env, validateEnv } from '@/lib/env';
|
||||
import { env, validateEnv, getLlamaCloudApiKey } from '@/lib/env';
|
||||
import { organizationService } from '@/lib/organization-service';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
return apiHandler(async () => {
|
||||
@@ -13,19 +14,23 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
// Get current user to determine which API key to use
|
||||
const currentUser = await organizationService.getCurrentUser();
|
||||
const apiKey = getLlamaCloudApiKey(currentUser?.email);
|
||||
|
||||
// Fetch projects and organizations from LlamaCloud
|
||||
const [projectsResponse, organizationsResponse] = await Promise.all([
|
||||
fetch('https://api.cloud.llamaindex.ai/api/v1/projects', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${env.LLAMACLOUD_API_KEY}`,
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}),
|
||||
fetch('https://api.cloud.llamaindex.ai/api/v1/organizations', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${env.LLAMACLOUD_API_KEY}`,
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -2,7 +2,7 @@ import { NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { organizationService } from '@/lib/organization-service';
|
||||
import { llamaCloudConnectionService } from '@/lib/services/llamacloud-connection-service';
|
||||
import { env, validateEnv } from '@/lib/env';
|
||||
import { env, validateEnv, getLlamaCloudApiKey } from '@/lib/env';
|
||||
|
||||
export async function GET() {
|
||||
|
||||
@@ -76,24 +76,27 @@ export async function GET() {
|
||||
}
|
||||
|
||||
// Helper function to fetch available LlamaCloud projects
|
||||
async function fetchLlamaCloudProjects() {
|
||||
async function fetchLlamaCloudProjects(userEmail?: string) {
|
||||
try {
|
||||
if (!validateEnv()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Get the appropriate API key based on user's email
|
||||
const apiKey = getLlamaCloudApiKey(userEmail);
|
||||
|
||||
const [projectsResponse, organizationsResponse] = await Promise.all([
|
||||
fetch('https://api.cloud.llamaindex.ai/api/v1/projects', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${env.LLAMACLOUD_API_KEY}`,
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}),
|
||||
fetch('https://api.cloud.llamaindex.ai/api/v1/organizations', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${env.LLAMACLOUD_API_KEY}`,
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
@@ -164,7 +167,7 @@ export async function POST(request: Request) {
|
||||
// Attempt automatic LlamaCloud connection if there's exactly one project
|
||||
let llamaCloudConnectionResult = null;
|
||||
try {
|
||||
const availableProjects = await fetchLlamaCloudProjects();
|
||||
const availableProjects = await fetchLlamaCloudProjects(currentUser.email);
|
||||
|
||||
if (availableProjects.length === 1) {
|
||||
const project = availableProjects[0];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { organizationService } from '@/lib/organization-service';
|
||||
import { env } from '@/lib/env';
|
||||
import { env, getLlamaCloudApiKey } from '@/lib/env';
|
||||
|
||||
// GET /api/projects/[projectId]/indexes - Get project indexes and available indexes
|
||||
export async function GET(
|
||||
@@ -71,11 +71,13 @@ export async function GET(
|
||||
|
||||
// Fetch available indexes from LlamaCloud
|
||||
try {
|
||||
// Get the appropriate API key based on user's email
|
||||
const apiKey = getLlamaCloudApiKey(currentUser.email);
|
||||
|
||||
const pipelinesResponse = await fetch('https://api.cloud.llamaindex.ai/api/v1/pipelines', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${env.LLAMACLOUD_API_KEY}`,
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
@@ -240,10 +242,13 @@ export async function POST(
|
||||
|
||||
// Fetch index names from LlamaCloud to validate and get names
|
||||
try {
|
||||
// Get the appropriate API key based on user's email
|
||||
const apiKey = getLlamaCloudApiKey(currentUser.email);
|
||||
|
||||
const pipelinesResponse = await fetch('https://api.cloud.llamaindex.ai/api/v1/pipelines', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${env.LLAMACLOUD_API_KEY}`,
|
||||
'Authorization': `Bearer ${apiKey}`,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
+13
@@ -1,6 +1,8 @@
|
||||
// Environment variables configuration
|
||||
export const env = {
|
||||
LLAMACLOUD_API_KEY: process.env.LLAMACLOUD_API_KEY || '',
|
||||
LLAMACLOUD_API_KEY_INTERNAL: process.env.LLAMACLOUD_API_KEY_INTERNAL || '',
|
||||
INTERNAL_EMAIL_DOMAIN: process.env.INTERNAL_EMAIL_DOMAIN || '@runllama.ai',
|
||||
};
|
||||
|
||||
// Function to validate required environment variables
|
||||
@@ -22,4 +24,15 @@ export function validateEnv() {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function to get the appropriate LlamaCloud API key based on user email
|
||||
export function getLlamaCloudApiKey(userEmail?: string | null): string {
|
||||
// If user has internal email domain and internal key is configured, use internal key
|
||||
if (userEmail?.endsWith(env.INTERNAL_EMAIL_DOMAIN) && env.LLAMACLOUD_API_KEY_INTERNAL) {
|
||||
return env.LLAMACLOUD_API_KEY_INTERNAL;
|
||||
}
|
||||
|
||||
// Otherwise, use the regular API key
|
||||
return env.LLAMACLOUD_API_KEY;
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { llamaCloudClient } from './llamacloud-client';
|
||||
import { organizationAuth } from './organization-auth';
|
||||
import { db } from '@/lib/db';
|
||||
import { DatabaseError, LlamaCloudConnectionError } from '@/lib/errors/api-errors';
|
||||
import { env, validateEnv } from '@/lib/env';
|
||||
import { env, validateEnv, getLlamaCloudApiKey } from '@/lib/env';
|
||||
|
||||
/**
|
||||
* Main LlamaCloud connection management service
|
||||
@@ -28,9 +28,16 @@ export class LlamaCloudConnectionService implements ILlamaCloudConnectionService
|
||||
throw new LlamaCloudConnectionError('LlamaCloud API key not configured in environment variables');
|
||||
}
|
||||
|
||||
// Step 3: Verify project access using environment API key
|
||||
// Get user's email to determine which API key to use
|
||||
const user = await db.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: { email: true }
|
||||
});
|
||||
|
||||
// Step 3: Verify project access using appropriate API key based on user
|
||||
const apiKey = getLlamaCloudApiKey(user?.email);
|
||||
const verifiedProject = await llamaCloudClient.verifyProjectAccess(
|
||||
env.LLAMACLOUD_API_KEY,
|
||||
apiKey,
|
||||
request.projectId
|
||||
);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { llamaCloudClient } from './llamacloud-client';
|
||||
import { organizationAuth } from './organization-auth';
|
||||
import { db } from '@/lib/db';
|
||||
import { DatabaseError, LlamaCloudConnectionError, NotFoundError } from '@/lib/errors/api-errors';
|
||||
import { env, validateEnv } from '@/lib/env';
|
||||
import { env, validateEnv, getLlamaCloudApiKey } from '@/lib/env';
|
||||
|
||||
/**
|
||||
* LlamaCloud documents management service
|
||||
@@ -27,12 +27,19 @@ export class LlamaCloudDocumentsService implements ILlamaCloudDocumentsService {
|
||||
throw new LlamaCloudConnectionError('LlamaCloud API key not configured in environment variables');
|
||||
}
|
||||
|
||||
// Get user's email to determine which API key to use
|
||||
const user = await db.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: { email: true }
|
||||
});
|
||||
const apiKey = getLlamaCloudApiKey(user?.email);
|
||||
|
||||
// Step 3: Get connected organization
|
||||
const organization = await this.getConnectedOrganization(request.organizationId);
|
||||
|
||||
// Step 4: Fetch pipelines for the project
|
||||
const pipelines = await llamaCloudClient.fetchPipelinesForProject(
|
||||
env.LLAMACLOUD_API_KEY,
|
||||
apiKey,
|
||||
organization.llamaCloudProjectId!
|
||||
);
|
||||
|
||||
@@ -41,7 +48,7 @@ export class LlamaCloudDocumentsService implements ILlamaCloudDocumentsService {
|
||||
const documentFetchPromises = pipelines.map(async (pipeline) => {
|
||||
try {
|
||||
const documents = await llamaCloudClient.fetchFilesForPipeline(
|
||||
env.LLAMACLOUD_API_KEY,
|
||||
apiKey,
|
||||
pipeline.id
|
||||
);
|
||||
return documents.map((doc: any) => ({
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { db } from '@/lib/db';
|
||||
import { organizationService } from '@/lib/organization-service';
|
||||
import { LlamaIndexService } from '@/lib/llama-index-service';
|
||||
import { getLlamaCloudApiKey } from '@/lib/env';
|
||||
import {
|
||||
GenerateResponseRequest,
|
||||
GenerateResponseResponse,
|
||||
@@ -44,7 +45,7 @@ export class ResponseGenerationService {
|
||||
return this.generateDefaultResponse(request.question, 'No valid indexes found');
|
||||
}
|
||||
|
||||
return this.generateLlamaIndexResponse(request, project, selectedIndexNames);
|
||||
return this.generateLlamaIndexResponse(request, project, selectedIndexNames, currentUser.email);
|
||||
}
|
||||
|
||||
private async getCurrentUser() {
|
||||
@@ -136,10 +137,12 @@ export class ResponseGenerationService {
|
||||
private async generateLlamaIndexResponse(
|
||||
request: GenerateResponseRequest,
|
||||
project: ProjectWithOrganization,
|
||||
selectedIndexNames: string[]
|
||||
selectedIndexNames: string[],
|
||||
userEmail: string
|
||||
): Promise<GenerateResponseResponse> {
|
||||
const apiKey = getLlamaCloudApiKey(userEmail);
|
||||
const llamaIndexService = new LlamaIndexService({
|
||||
apiKey: process.env.LLAMACLOUD_API_KEY!,
|
||||
apiKey: apiKey,
|
||||
projectName: project.organization.llamaCloudProjectName || 'Default',
|
||||
indexNames: request.useAllIndexes ? undefined : selectedIndexNames,
|
||||
});
|
||||
|
||||
@@ -5,6 +5,10 @@ const nextConfig = {
|
||||
// You will need to set LLAMACLOUD_API_KEY in your deployment environment
|
||||
// or in a .env.local file that's not committed to version control
|
||||
LLAMACLOUD_API_KEY: process.env.LLAMACLOUD_API_KEY,
|
||||
// Internal API key for internal users
|
||||
LLAMACLOUD_API_KEY_INTERNAL: process.env.LLAMACLOUD_API_KEY_INTERNAL,
|
||||
// Internal email domain (defaults to @runllama.ai)
|
||||
INTERNAL_EMAIL_DOMAIN: process.env.INTERNAL_EMAIL_DOMAIN,
|
||||
},
|
||||
// Other Next.js config options
|
||||
reactStrictMode: true,
|
||||
|
||||
Reference in New Issue
Block a user