Add data source ids to copilot request

This commit is contained in:
akhisud3195 2025-05-12 20:40:02 +05:30
parent 9c712250fb
commit 462a2fb651
5 changed files with 70 additions and 13 deletions

View file

@ -1,5 +1,5 @@
from flask import Flask, request, jsonify, Response, stream_with_context from flask import Flask, request, jsonify, Response, stream_with_context
from pydantic import BaseModel, ValidationError from pydantic import BaseModel, ValidationError, Field
from typing import List, Optional from typing import List, Optional
from copilot import UserMessage, AssistantMessage, get_response from copilot import UserMessage, AssistantMessage, get_response
from streaming import get_streaming_response from streaming import get_streaming_response
@ -10,6 +10,7 @@ from copilot import copilot_instructions_edit_agent
import json import json
class DataSource(BaseModel): class DataSource(BaseModel):
id: str = Field(alias='_id')
name: str name: str
description: Optional[str] = None description: Optional[str] = None
active: bool = True active: bool = True
@ -17,6 +18,9 @@ class DataSource(BaseModel):
error: Optional[str] = None error: Optional[str] = None
data: dict # The discriminated union based on type data: dict # The discriminated union based on type
class Config:
populate_by_name = True
class ApiRequest(BaseModel): class ApiRequest(BaseModel):
messages: List[UserMessage | AssistantMessage] messages: List[UserMessage | AssistantMessage]
workflow_schema: str workflow_schema: str
@ -61,7 +65,10 @@ def health():
@require_api_key @require_api_key
def chat_stream(): def chat_stream():
try: try:
request_data = ApiRequest(**request.json) raw_data = request.json
print(f"Raw request JSON: {json.dumps(raw_data)}")
request_data = ApiRequest(**raw_data)
print(f"received /chat_stream request: {request_data}") print(f"received /chat_stream request: {request_data}")
validate_request(request_data) validate_request(request_data)

View file

@ -16,6 +16,7 @@ class AssistantMessage(BaseModel):
content: str content: str
class DataSource(BaseModel): class DataSource(BaseModel):
_id: str
name: str name: str
description: Optional[str] = None description: Optional[str] = None
active: bool = True active: bool = True

View file

@ -1,6 +1,6 @@
from openai import OpenAI from openai import OpenAI
from flask import Flask, request, jsonify, Response, stream_with_context from flask import Flask, request, jsonify, Response, stream_with_context
from pydantic import BaseModel, ValidationError from pydantic import BaseModel, ValidationError, Field
from typing import List, Dict, Any, Literal, Optional from typing import List, Dict, Any, Literal, Optional
import json import json
from lib import AgentContext, PromptContext, ToolContext, ChatContext from lib import AgentContext, PromptContext, ToolContext, ChatContext
@ -16,6 +16,7 @@ class AssistantMessage(BaseModel):
content: str content: str
class DataSource(BaseModel): class DataSource(BaseModel):
id: str = Field(alias='_id')
name: str name: str
description: Optional[str] = None description: Optional[str] = None
active: bool = True active: bool = True
@ -23,6 +24,9 @@ class DataSource(BaseModel):
error: Optional[str] = None error: Optional[str] = None
data: dict # The discriminated union based on type data: dict # The discriminated union based on type
class Config:
populate_by_name = True
with open('copilot_multi_agent.md', 'r', encoding='utf-8') as file: with open('copilot_multi_agent.md', 'r', encoding='utf-8') as file:
copilot_instructions_multi_agent = file.read() copilot_instructions_multi_agent = file.read()
@ -81,6 +85,7 @@ def get_streaming_response(
data_sources_prompt = "" data_sources_prompt = ""
if dataSources: if dataSources:
print(f"Data sources found at project level: {dataSources}") print(f"Data sources found at project level: {dataSources}")
print(f"Data source IDs: {[ds.id for ds in dataSources]}")
data_sources_prompt = f""" data_sources_prompt = f"""
**NOTE**: The following data sources are available: **NOTE**: The following data sources are available:
```json ```json
@ -136,6 +141,8 @@ def create_app():
if not request_data or 'messages' not in request_data: if not request_data or 'messages' not in request_data:
return jsonify({'error': 'No messages provided'}), 400 return jsonify({'error': 'No messages provided'}), 400
print(f"Raw request data: {request_data}")
messages = [ messages = [
UserMessage(**msg) if msg['role'] == 'user' else AssistantMessage(**msg) UserMessage(**msg) if msg['role'] == 'user' else AssistantMessage(**msg)
for msg in request_data['messages'] for msg in request_data['messages']
@ -144,13 +151,19 @@ def create_app():
workflow_schema = request_data.get('workflow_schema', '') workflow_schema = request_data.get('workflow_schema', '')
current_workflow_config = request_data.get('current_workflow_config', '') current_workflow_config = request_data.get('current_workflow_config', '')
context = None # You can add context handling if needed context = None # You can add context handling if needed
dataSources = None
if 'dataSources' in request_data and request_data['dataSources']:
print(f"Raw dataSources from request: {request_data['dataSources']}")
dataSources = [DataSource(**ds) for ds in request_data['dataSources']]
print(f"Parsed dataSources: {dataSources}")
def generate(): def generate():
stream = get_streaming_response( stream = get_streaming_response(
messages=messages, messages=messages,
workflow_schema=workflow_schema, workflow_schema=workflow_schema,
current_workflow_config=current_workflow_config, current_workflow_config=current_workflow_config,
context=context context=context,
dataSources=dataSources
) )
for chunk in stream: for chunk in stream:

View file

@ -38,7 +38,24 @@ export async function getCopilotResponse(
workflow_schema: JSON.stringify(zodToJsonSchema(CopilotWorkflow)), workflow_schema: JSON.stringify(zodToJsonSchema(CopilotWorkflow)),
current_workflow_config: JSON.stringify(convertToCopilotWorkflow(current_workflow_config)), current_workflow_config: JSON.stringify(convertToCopilotWorkflow(current_workflow_config)),
context: context ? convertToCopilotApiChatContext(context) : null, context: context ? convertToCopilotApiChatContext(context) : null,
dataSources: dataSources ? dataSources.map(ds => CopilotDataSource.parse(ds)) : undefined, dataSources: dataSources ? dataSources.map(ds => {
console.log('Original data source:', JSON.stringify(ds));
// First parse to validate, then ensure _id is included
CopilotDataSource.parse(ds); // validate but don't use the result
// Cast to any to handle the WithStringId type
const withId = ds as any;
const result = {
_id: withId._id,
name: withId.name,
description: withId.description,
active: withId.active,
status: withId.status,
error: withId.error,
data: withId.data
};
console.log('Processed data source:', JSON.stringify(result));
return result;
}) : undefined,
}; };
console.log(`sending copilot request`, JSON.stringify(request)); console.log(`sending copilot request`, JSON.stringify(request));

View file

@ -6,14 +6,33 @@ import { convertToAgenticAPIChatMessages } from "./agents_api_types";
import { DataSource } from "./datasource_types"; import { DataSource } from "./datasource_types";
// Create a filtered version of DataSource for copilot // Create a filtered version of DataSource for copilot
export const CopilotDataSource = DataSource.omit({ export const CopilotDataSource = z.object({
projectId: true, _id: z.string(),
version: true, name: z.string(),
attempts: true, description: z.string().optional(),
createdAt: true, active: z.boolean().default(true),
lastUpdatedAt: true, status: z.union([
pendingRefresh: true, z.literal('pending'),
}); z.literal('ready'),
z.literal('error'),
z.literal('deleted'),
]),
error: z.string().optional(),
data: z.discriminatedUnion('type', [
z.object({
type: z.literal('urls'),
}),
z.object({
type: z.literal('files_local'),
}),
z.object({
type: z.literal('files_s3'),
}),
z.object({
type: z.literal('text'),
})
]),
}).passthrough();
export const CopilotWorkflow = Workflow.omit({ export const CopilotWorkflow = Workflow.omit({
lastUpdatedAt: true, lastUpdatedAt: true,