API предсказаний
API предсказаний это основной интерфейс для взаимодействия с вашими потоками и помощниками в OSMI-AI. Он позволяет отправлять сообщения выбранному потоку и получать ответы. Этот API обеспечивает основную функциональность чата, включая:
- Взаимодействия в чате: отправляйте вопросы или сообщения в ваш поток и получайте ответы, сгенерированные ИИ.
- Потоковые ответы: получайте ответы в реальном времени для улучшенного пользовательского опыта.
- Память беседы: сохраняйте контекст между несколькими сообщениями в рамках одной сессии.
- Обработка файлов: загружайте и обрабатывайте изображения, аудио и другие файлы как часть ваших запросов.
- Динамическая настройка: переопределяйте параметры чат-потока и передавайте параметры в режиме реального времени.
Подробности смотрите в разделе API справочник по API предсказаний.
Базовый URL и аутентификация
Base URL: http://localhost:3000 (или URL вашей инстанции OSMI-AI) Endpoint: POST /api/v1/prediction/:id Аутентификация: см. раздел Потоки
Формат запроса
Основная структура запроса
{
"question": "Ваше сообщение здесь",
"streaming": false,
"overrideConfig": {},
"history": [],
"uploads": [],
"form": {},
"humanInput": {}
}
Параметры
| Параметр | Тип | Обязательно | Описание |
|---|---|---|---|
question | string | Да | Сообщение или вопрос, который отправляется в поток |
form | object | Либо question, либо form | Объект формы, который отправляется в поток |
streaming | neutral | Нет | Включить потоковую обработку ответов (по умолчанию: false) |
overrideConfig | object | Нет | Переопределить настройки потока |
history | array | Нет | Предыдущие сообщения беседы |
uploads | array | Нет | Файлы для загрузки (изображения, аудио и т. д.) |
humanInput | object | Нет | Обратная связь от человека и продолжение выполнения |
Библиотеки SDK
OSMI-AI предоставляет официальные SDK для Python и TypeScript/JavaScript:
Установка
Python: pip install osmi-ai
TypeScript/JavaScript: npm install osmi-ai-sdk
Использование Python SDK
Базовое использование:
from osmi-ai import osmi-ai, PredictionData
# Initialize client
client = osmi-ai(base_url="http://localhost:3000")
# Non-streaming prediction
try:
response = client.create_prediction(
PredictionData(
agentId="your-agent-id",
question="What is machine learning?",
streaming=False
)
)
# Handle response
for result in response:
print("Response:", result)
except Exception as e:
print(f"Error: {e}")
Потоковая передача:
from osmi-ai import osmi-ai, PredictionData
client = osmi-ai(base_url="http://localhost:3000")
# Streaming prediction
try:
response = client.create_prediction(
PredictionData(
agentId="your-agent-id",
question="Tell me a long story about AI",
streaming=True
)
)
# Process streaming chunks
print("Streaming response:")
for chunk in response:
print(chunk, end="", flush=True)
except Exception as e:
print(f"Error: {e}")
С дополнительными настройками:
from osmi-ai import osmi-ai, PredictionData
client = osmi-ai(base_url="http://localhost:3000")
# Advanced configuration
try:
response = client.create_prediction(
PredictionData(
agentId="your-agent-id",
question="Analyze this data",
streaming=False,
overrideConfig={
"sessionId": "user-session-123",
"temperature": 0.7,
"maxTokens": 500,
"returnSourceDocuments": True
}
)
)
for result in response:
print("Response:", result)
except Exception as e:
print(f"Error: {e}")
Использование SDK для TypeScript/JavaScript
Базовое использование:
import { OSMI-AIClient } from 'osmi-ai-sdk';
// Initialize client
const client = new OSMI-AIClient({
baseUrl: 'http://localhost:3000'
});
// Non-streaming prediction
async function chatWithFlow() {
try {
const response = await client.createPrediction({
agentId: 'your-agent-id',
question: 'What is machine learning?',
streaming: false
});
console.log('Response:', response);
} catch (error) {
console.error('Error:', error);
}
}
chatWithFlow();
Потоковая передача:
import { OSMI-AIClient } from 'OSMI-AI-sdk';
const client = new Osmi_aiClient({
baseUrl: 'http://localhost:3000'
});
// Streaming prediction
async function streamingChat() {
try {
const stream = await client.createPrediction({
agentId: 'your-agent-id',
question: 'Tell me a long story about AI',
streaming: true
});
console.log('Streaming response:');
for await (const chunk of stream) {
process.stdout.write(chunk);
}
} catch (error) {
console.error('Error:', error);
}
}
streamingChat();
С дополнительными настройками:
import { OSMI-AIClient } from '-sdk';
const client = new OSMI-AIClient({
baseUrl: 'http://localhost:3000'
});
// Advanced configuration
async function advancedChat() {
try {
const response = await client.createPrediction({
agentId: 'your-agent-id',
question: 'Analyze this data',
streaming: false,
overrideConfig: {
sessionId: 'user-session-123',
temperature: 0.7,
maxTokens: 500,
returnSourceDocuments: true
}
});
console.log('Response:', response);
} catch (error) {
console.error('Error:', error);
}
}
advancedChat();
Прямое использование HTTP API
Использовать REST API напрямую, без SDK:
Basic Request
import requests
import json
def send_message(agent_id, question, streaming=False):
url = f"http://localhost:3000/api/v1/prediction/{agent_id}"
payload = {
"question": question,
"streaming": streaming
}
headers = {
"Content-Type": "application/json"
}
try:
response = requests.post(url, json=payload, headers=headers)
response.raise_for_status() # Raise exception for bad status codes
return response.json()
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
return None
# Usage
result = send_message(
agent_id="your-agent-id",
question="What is artificial intelligence?",
streaming=False
)
if result:
print("Response:", result)
JavaScript (fetch)
async function sendMessage(agentId, question, streaming = false) {
const url = `http://localhost:3000/api/v1/prediction/${agentId}`;
const payload = {
question: question,
streaming: streaming
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
return result;
} catch (error) {
console.error('Request failed:', error);
return null;
}
}
// Usage
sendMessage(
'your-agent-id',
'What is artificial intelligence?',
false
).then(result => {
if (result) {
console.log('Response:', result);
}
});
cURL:
curl -X POST "http://localhost:3000/api/v1/prediction/your-agent-id" \
-H "Content-Type: application/json" \
-d '{
"question": "What is artificial intelligence?",
"streaming": false
}'
Продвинутые фцнкции
Форма ввода
В Multi_agent V2 вы можете выбрать form в качестве типа входных данных.
Вы можете переопределить значение, указав имя параметра в поле ввода формы.
{
"form": {
"title": "Example",
"count": 1,
...
}
}
Python
import requests
def prediction(flow_id, form):
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
payload = {
"form": form
}
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
result = prediction(
flow_id="your-flow-id",
form={
"title": "ABC",
"choices": "A"
}
)
print(result)
JavaScript:
async function prediction(flowId, form) {
const url = `http://localhost:3000/api/v1/prediction/${flowId}`;
const payload = {
form: form
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
prediction(
'your-flow-id',
{
"title": "ABC",
"choices": "A"
}
).then(result => {
console.log(result);
});
Переопределение конфигурации (Override Config)
Динамически переопределяйте настройки чат-потока.
По умолчанию переопределение конфигурации отключено по соображениям безопасности. Включите его в верхней правой части: Настройки → Конфигурация → Вкладка «Безопасность».
::
Python:
import requests
def query_with_config(flow_id, question, config):
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
payload = {
"question": question,
"overrideConfig": config
}
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Example: Override session and return source documents
result = query_with_config(
flow_id="your-flow-id",
question="How does machine learning work?",
config={
"sessionId": "user-123",
"temperature": 0.5,
"maxTokens": 1000
}
)
print(result)
JavaScript:
async function queryWithConfig(flowId, question, config) {
const url = `http://localhost:3000/api/v1/prediction/${flowId}`;
const payload = {
question: question,
overrideConfig: config
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
// Example: Override session and return source documents
queryWithConfig(
'your-flow-id',
'How does machine learning work?',
{
sessionId: 'user-123',
temperature: 0.5,
maxTokens: 1000
}
).then(result => {
console.log(result);
});
Для типа массива, при наведении на значок информации будет отображаться схема, которую можно переопределить. Значение массива из overrideConfig будет объединяться с существующими значениями массива. Например, если существующий startState имеет:
{
"key": "key1",
"value": "value1"
}
И если мы включим переопределение:
"overrideConfig": {
"startState": [
{
"key": "foo",
"value": "bar"
}
],
"llmMessages": [
{
"role": "system",
"content": "You are helpful assistant"
}
]
}
Итоговый startState будет:
[
{
"key": "key1",
"value": "value1"
},
{
"key": "foo",
"value": "bar"
},
]
Переопределение конкретного узла
По умолчанию, если несколько узлов имеют одинаковый тип и не указан идентификатор узла (node ID), то при переопределении свойства оно обновится для всех соответствующих узлов. Например, если есть 2 узла LLM, в которых нужно изменить системное сообщение, можно переопределить это сообщение для обеих LLM одновременно.
В разделе "Выполнение" можно увидеть переопределённое системное сообщение.
Если же нужно изменить настройки только для конкретного узла, укажите его node ID в свойстве, которое хотите переопределить. Например: (пример с указанием node ID)
"overrideConfig": {
"llmMessages": [
{
"role": "system",
"content": "You are sarcastic"
}
]
}
Вернувшись в "Выполнение", вы убедитесь, что для каждого LLM указано правильное переопределённое значение.
"overrideConfig": {
"llmMessages": {
"llmMulti_agent_0": [
{
"role": "system",
"content": "You are sweet"
}
],
"llmMulti_agent_1": [
{
"role": "system",
"content": "You are smart"
}
]
}
}
История разговора
Обеспечьте контекст диалога, включая предыдущие сообщения в массиве history.
History Message Format
{
"role": "apiMessage" | "userMessage",
"content": "Message content"
}
Python:
import requests
def chat_with_history(flow_id, question, history):
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
payload = {
"question": question,
"history": history
}
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Example conversation with context
conversation_history = [
{
"role": "apiMessage",
"content": "Hello! I'm an AI assistant. How can I help you today?"
},
{
"role": "userMessage",
"content": "Hi, my name is Sarah and I'm learning about AI"
},
{
"role": "apiMessage",
"content": "Nice to meet you, Sarah! I'd be happy to help you learn about AI. What specific aspects interest you?"
}
]
result = chat_with_history(
flow_id="your-flow-id",
question="Can you explain neural networks in simple terms?",
history=conversation_history
)
print(result)
JavaScript:
async function chatWithHistory(flowId, question, history) {
const url = `http://localhost:3000/api/v1/prediction/${flowId}`;
const payload = {
question: question,
history: history
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
// Example conversation with context
const conversationHistory = [
{
role: "apiMessage",
content: "Hello! I'm an AI assistant. How can I help you today?"
},
{
role: "userMessage",
content: "Hi, my name is Sarah and I'm learning about AI"
},
{
role: "apiMessage",
content: "Nice to meet you, Sarah! I'd be happy to help you learn about AI. What specific aspects interest you?"
}
];
chatWithHistory(
'your-flow-id',
'Can you explain neural networks in simple terms?',
conversationHistory
).then(result => {
console.log(result);
});
Управление сессиями
Используйте sessionId для сохранения состояния разговора при нескольких вызовах API. Каждая сессия хранит свой контекст и память диалога.
Python
import requests
class Osmi_aiSession:
def __init__(self, flow_id, session_id, base_url="http://localhost:3000"):
self.flow_id= flow_id
self.session_id = session_id
self.base_url = base_url
self.url = f"{base_url}/api/v1/prediction/{flow_id}"
def send_message(self, question, **kwargs):
payload = {
"question": question,
"overrideConfig": {
"sessionId": self.session_id,
**kwargs.get("overrideConfig", {})
}
}
# Add any additional parameters
for key, value in kwargs.items():
if key != "overrideConfig":
payload[key] = value
try:
response = requests.post(self.url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Usage
session = OSMI-AISession(
flow_id="your-flow-id",
session_id="user-session-123"
)
# First message
response1 = session.send_message("Hello, my name is John")
print("Response 1:", response1)
# Second message - will remember the previous context
response2 = session.send_message("What's my name?")
print("Response 2:", response2)
JavaScript
class OSMI-AISession {
constructor(flowId, sessionId, baseUrl = 'http://localhost:3000') {
this.flowId= flowId;
this.sessionId = sessionId;
this.baseUrl = baseUrl;
this.url = `${baseUrl}/api/v1/prediction/${flowId}`;
}
async sendMessage(question) {
const payload = {
question: question,
overrideConfig: {
sessionId: this.sessionId
}
};
try {
const response = await fetch(this.url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
}
// Usage
const session = new OSMI-AISession(
'your-flow-id',
'user-session-123'
);
async function conversationExample() {
// First message
const response1 = await session.sendMessage("Hello, my name is John");
console.log("Response 1:", response1);
// Second message - will remember the previous context
const response2 = await session.sendMessage("What's my name?");
console.log("Response 2:", response2);
}
conversationExample();
Параметры
Передавайте динамические параметры в ваш поток с помощью свойства vars в overrideConfig. параметры могут использоваться в вашем потоке для внедрения динамического содержимого.
⚠️ Параметры должны быть заранее созданы в разделе Параметры.
Python
import requests
def send_with_variables(flow_id, question, variables):
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
payload = {
"question": question,
"overrideConfig": {
"vars": variables
}
}
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Example: Pass user information and preferences
result = send_with_variables(
flow_id="your-flow-id",
question="Create a personalized workout plan",
variables={
"user_name": "Alice",
"fitness_level": "intermediate",
"preferred_duration": "30 minutes",
"equipment": "dumbbells, resistance bands",
"goals": "strength training, flexibility"
}
)
print(result)
JavaScript
async function sendWithVariables(flowId, question, variables) {
const url = `http://localhost:3000/api/v1/prediction/${flowId}`;
const payload = {
question: question,
overrideConfig: {
vars: variables
}
};
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
// Example: Pass user information and preferences
sendWithVariables(
'your-flow-id',
'Create a personalized workout plan',
{
user_name: 'Alice',
fitness_level: 'intermediate',
preferred_duration: '30 minutes',
equipment: 'dumbbells, resistance bands',
goals: 'strength training, flexibility'
}
).then(result => {
console.log(result);
});
Загрузка изображений
Загружайте изображения для визуального анализа, если ваш поток поддерживает обработку изображений.
Подробнее см. раздел Изображения.
Структура загрузки:
{
"data": "",
"type": "",
"name": "",
"mime": ""
}
Data: Base64 или URL изображения
Type: url или file
Name: имя изображения
Mime: image/png, image/jpeg, image/jpg
import requests
import base64
import os
def upload_image(flow_id, question, image_path):
# Read and encode image
with open(image_path, 'rb') as image_file:
encoded_image = base64.b64encode(image_file.read()).decode('utf-8')
# Determine MIME type based on file extension
mime_types = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.webp': 'image/webp'
}
file_ext = os.path.splitext(image_path)[1].lower()
mime_type = mime_types.get(file_ext, 'image/png')
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
payload = {
"question": question,
"uploads": [
{
"data": f"data:{mime_type};base64,{encoded_image}",
"type": "file",
"name": os.path.basename(image_path),
"mime": mime_type
}
]
}
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Example usage
result = upload_image(
flow_id="your-flow-id",
question="Can you describe what you see in this image?",
image_path="path/to/your/image.png"
)
print(result)
import requests
import os
def upload_image_url(flow_id, question, image_url, image_name=None):
"""
Upload an image using a URL instead of base64 encoding.
This is more efficient for images that are already hosted online.
"""
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
# Extract filename from URL if not provided
if not image_name:
image_name = image_url.split('/')[-1]
if '?' in image_name:
image_name = image_name.split('?')[0]
# Determine MIME type from URL extension
mime_types = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.webp': 'image/webp'
}
file_ext = os.path.splitext(image_name)[1].lower()
mime_type = mime_types.get(file_ext, 'image/jpeg')
payload = {
"question": question,
"uploads": [
{
"data": image_url,
"type": "url",
"name": image_name,
"mime": mime_type
}
]
}
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Example usage with public image URL
result = upload_image_url(
flow_id="your-flow-id",
question="What's in this image? Analyze it in detail.",
image_url="https://example.com/path/to/image.jpg",
image_name="example_image.jpg"
)
print(result)
# Example with direct URL (no custom name)
result2 = upload_image_url(
agent_id="your-agent-id",
question="Describe this screenshot",
image_url="https://i.imgur.com/sample.png"
)
print(result2)
async function uploadImage(flowId, question, imageFile) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async function(e) {
const base64Data = e.target.result;
const payload = {
question: question,
uploads: [
{
data: base64Data,
type: 'file',
name: imageFile.name,
mime: imageFile.type
}
]
};
try {
const response = await fetch(`http://localhost:3000/api/v1/prediction/${flowId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
resolve(result);
} catch (error) {
reject(error);
}
};
reader.onerror = function() {
reject(new Error('Failed to read file'));
};
reader.readAsDataURL(imageFile);
});
}
// Example usage in browser
document.getElementById('imageInput').addEventListener('change', async function(e) {
const file = e.target.files[0];
if (file) {
try {
const result = await uploadImage(
'your-flow-id',
'Can you describe what you see in this image?',
file
);
console.log('Analysis result:', result);
} catch (error) {
console.error('Upload failed:', error);
}
}
});
async function uploadImageUrl(flowId, question, imageUrl, imageName = null) {
/**
* Upload an image using a URL instead of base64 encoding.
* This is more efficient for images that are already hosted online.
*/
// Extract filename from URL if not provided
if (!imageName) {
imageName = imageUrl.split('/').pop();
if (imageName.includes('?')) {
imageName = imageName.split('?')[0];
}
}
// Determine MIME type from URL extension
const mimeTypes = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.webp': 'image/webp'
};
const fileExt = imageName.toLowerCase().substring(imageName.lastIndexOf('.'));
const mimeType = mimeTypes[fileExt] || 'image/jpeg';
const payload = {
question: question,
uploads: [
{
data: imageUrl,
type: 'url',
name: imageName,
mime: mimeType
}
]
};
try {
const response = await fetch(`http://localhost:3000/api/v1/prediction/${flowId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
// Example usage with public image URL
async function analyzeImageFromUrl() {
try {
const result = await uploadImageUrl(
'your-flow-id',
'What is in this image? Analyze it in detail.',
'https://example.com/path/to/image.jpg',
'example_image.jpg'
);
console.log('Analysis result:', result);
} catch (error) {
console.error('Upload failed:', error);
}
}
// Example with direct URL (no custom name)
uploadImageUrl(
'your-flow-id',
'Describe this screenshot',
'https://i.imgur.com/sample.png'
).then(result => {
if (result) {
console.log('Analysis result:', result);
}
});
// Example with multiple image URLs
async function analyzeMultipleImages() {
const imageUrls = [
'https://example.com/image1.jpg',
'https://example.com/image2.png',
'https://example.com/image3.gif'
];
const results = await Promise.all(
imageUrls.map(url =>
uploadImageUrl(
'your-flow-id',
`Analyze this image: ${url}`,
url
)
)
);
results.forEach((result, index) => {
console.log(`Image ${index + 1} analysis:`, result);
});
}
const fs = require('fs');
const path = require('path');
async function uploadImage(flowId, question, imagePath) {
// Read image file
const imageBuffer = fs.readFileSync(imagePath);
const base64Image = imageBuffer.toString('base64');
// Determine MIME type
const ext = path.extname(imagePath).toLowerCase();
const mimeTypes = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.webp': 'image/webp'
};
const mimeType = mimeTypes[ext] || 'image/png';
const payload = {
question: question,
uploads: [
{
data: `data:${mimeType};base64,${base64Image}`,
type: 'file',
name: path.basename(imagePath),
mime: mimeType
}
]
};
try {
const response = await fetch(`http://localhost:3000/api/v1/prediction/${flowId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
// Example usage
uploadImage(
'your-flow-id',
'Can you describe what you see in this image?',
'path/to/your/image.png'
).then(result => {
console.log('Analysis result:', result);
});
Загрузка aудио (преобразование речи в текст)
Загружайте аудиофайлы для преобразования речи в текст.Подробнее в разделе «Аудио».
Структура загрузки:
{
"data": "",
"type": "",
"name": "",
"mime": ""
}
Data: Base64 или URL аудио
Type: url или file
Name: имя аудио Mime
Mime: audio/mp4, audio/webm, audio/wav, audio/mpeg
import requests
import base64
import os
def upload_audio(flow_id, audio_path, question=None):
# Read and encode audio
with open(audio_path, 'rb') as audio_file:
encoded_audio = base64.b64encode(audio_file.read()).decode('utf-8')
# Determine MIME type based on file extension
mime_types = {
'.webm': 'audio/webm',
'.wav': 'audio/wav',
'.mp3': 'audio/mpeg',
'.m4a': 'audio/mp4'
}
file_ext = os.path.splitext(audio_path)[1].lower()
mime_type = mime_types.get(file_ext, 'audio/webm')
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
payload = {
"uploads": [
{
"data": f"data:{mime_type};base64,{encoded_audio}",
"type": "audio",
"name": os.path.basename(audio_path),
"mime": mime_type
}
]
}
# Add question if provided
if question:
payload["question"] = question
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Example usage
result = upload_audio(
flow_id="your-flow-id",
audio_path="path/to/your/audio.wav",
question="Please transcribe this audio and summarize the content"
)
print(result)
import requests
import os
def upload_audio_url(flow_id, audio_url, question=None, audio_name=None):
"""
Upload an audio file using a URL instead of base64 encoding.
This is more efficient for audio files that are already hosted online.
"""
url = f"http://localhost:3000/api/v1/prediction/{flow_id}"
# Extract filename from URL if not provided
if not audio_name:
audio_name = audio_url.split('/')[-1]
if '?' in audio_name:
audio_name = audio_name.split('?')[0]
# Determine MIME type from URL extension
mime_types = {
'.webm': 'audio/webm',
'.wav': 'audio/wav',
'.mp3': 'audio/mpeg',
'.m4a': 'audio/mp4',
'.ogg': 'audio/ogg',
'.aac': 'audio/aac'
}
file_ext = os.path.splitext(audio_name)[1].lower()
mime_type = mime_types.get(file_ext, 'audio/wav')
payload = {
"uploads": [
{
"data": audio_url,
"type": "url",
"name": audio_name,
"mime": mime_type
}
]
}
# Add question if provided
if question:
payload["question"] = question
try:
response = requests.post(url, json=payload)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Error: {e}")
return None
# Example usage with public audio URL
result = upload_audio_url(
flow_id="your-flow-id",
audio_url="https://example.com/path/to/speech.mp3",
question="Please transcribe this audio and provide a summary",
audio_name="speech_recording.mp3"
)
print(result)
# Example with direct URL (no custom name or question)
result2 = upload_audio_url(
flow_id="your-flow-id",
audio_url="https://storage.googleapis.com/sample-audio/speech.wav"
)
print(result2)
# Example for meeting transcription
result3 = upload_audio_url(
flow_id="your-flow-id",
audio_url="https://meetings.example.com/recording-123.m4a",
question="Transcribe this meeting recording and extract key action items and decisions made",
audio_name="team_meeting_jan15.m4a"
)
print(result3)
async function uploadAudio(flowId, audioFile, question = null) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async function(e) {
const base64Data = e.target.result;
const payload = {
uploads: [
{
data: base64Data,
type: 'audio',
name: audioFile.name,
mime: audioFile.type
}
]
};
// Add question if provided
if (question) {
payload.question = question;
}
try {
const response = await fetch(`http://localhost:3000/api/v1/prediction/${flowId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const result = await response.json();
resolve(result);
} catch (error) {
reject(error);
}
};
reader.onerror = function() {
reject(new Error('Failed to read file'));
};
reader.readAsDataURL(audioFile);
});
}
document.getElementById('audioInput').addEventListener('change', async function(e) {
const file = e.target.files[0];
if (file) {
try {
const result = await uploadAudio(
'your-flow-id',
file,
'Please transcribe this audio and summarize the content'
);
console.log('Transcription result:', result);
} catch (error) {
console.error('Upload failed:', error);
}
}
});
async function uploadAudioUrl(flowId, audioUrl, question = null, audioName = null) {
if (!audioName) {
audioName = audioUrl.split('/').pop();
if (audioName.includes('?')) {
audioName = audioName.split('?')[0];
}
}
const mimeTypes = {
'.webm': 'audio/webm',
'.wav': 'audio/wav',
'.mp3': 'audio/mpeg',
'.m4a': 'audio/mp4',
'.ogg': 'audio/ogg',
'.aac': 'audio/aac'
};
const fileExt = audioName.toLowerCase().substring(audioName.lastIndexOf('.'));
const mimeType = mimeTypes[fileExt] || 'audio/wav';
const payload = {
uploads: [
{
data: audioUrl,
type: 'url',
name: audioName,
mime: mimeType
}
]
};
if (question) {
payload.question = question;
}
try {
const response = await fetch(`http://localhost:3000/api/v1/prediction/${flowId}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Error:', error);
return null;
}
}
async function transcribeAudioFromUrl() {
try {
const result = await uploadAudioUrl(
'your-flow-id',
'https://example.com/path/to/speech.mp3',
'Please transcribe this audio and provide a summary',
'speech_recording.mp3'
);
console.log('Transcription result:', result);
} catch (error) {
console.error('Upload failed:', error);
}
}
uploadAudioUrl(
'your-flow-id',
'https://storage.googleapis.com/sample-audio/speech.wav'
).then(result => {
if (result) {
console.log('Transcription result:', result);
}
});
uploadAudioUrl(
'your-flow-id',
'https://meetings.example.com/recording-123.m4a',
'Transcribe this meeting recording and extract key action items and decisions made',
'team_meeting_jan15.m4a'
).then(result => {
if (result) {
console.log('Meeting analysis:', result);
}
});
async function transcribeMultipleAudios() {
const audioUrls = [
{
url: 'https://example.com/interview1.wav',
question: 'Transcribe this interview and summarize key points',
name: 'interview_candidate_1.wav'
},
{
url: 'https://example.com/interview2.mp3',
question: 'Transcribe this interview and summarize key points',
name: 'interview_candidate_2.mp3'
},
{
url: 'https://example.com/lecture.m4a',
question: 'Transcribe this lecture and create bullet-point notes',
name: 'cs101_lecture.m4a'
}
];
const results = await Promise.all(
audioUrls.map(audio =>
uploadAudioUrl(
'your-flow-id',
audio.url,
audio.question,
audio.name
)
)
);
results.forEach((result, index) => {
console.log(`Audio ${index + 1} transcription:`, result);
});
}
Загрузка файлов
Загрузите файлы для обработки LLM, чтобы получить ответы на связанные запросы. Дополнительную информацию можно найти в разделе Файлы.
Ввод данных пользователем
Для возобновления выполнения с ранее остановленной контрольной точки необходимо предоставить ввод данных пользователем. Подробности приведены в разделе Управление пользователем в цикле.
Структура ввода данных пользователем { "type": "", "feedback": "" }
- type: Продолжить или отклонить
- feedback: Обратная связь по последнему выводу.
Необходимо указать тот же sessionId, на котором было остановлено выполнение.
{ "humanInput": { "type": "reject", "feedback": "Включить больше эмодзи" }, "overrideConfig": { "sessionId": "abc" } }
Устранение неполадок:
- 404 Not Found: Убедитесь, что идентификатор потока верен и поток существует.
- 401 Unauthorized Access: Подтвердите, что поток защищён ключом API.
- 400 Bad Request: Проверьте формат запроса и обязательные поля.
- 413 Payload Too Large: Уменьшите размер файлов или разделите большие запросы.
- 500 Internal Server Error: Проверьте правильность конфигурации узлов в потоке.

