mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-03 20:41:07 +02:00
Add data source ids to copilot request
This commit is contained in:
parent
9c712250fb
commit
462a2fb651
5 changed files with 70 additions and 13 deletions
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue