Add text chunking functionality to chat endpoint
- Introduced SentenceTextChunker and SentenceTextChunkerConfig for improved text processing in chat responses. - Updated chat endpoint to conditionally use text chunking based on the new 'useTextChunk' parameter from the request. - Enhanced logging to include 'useTextChunk' status and adjusted text delta handling to support chunked responses. - Modified ProcessRequest_chat model to include 'useTextChunk' field for request handling. - Added unit tests for SentenceTextChunker to ensure correct chunking behavior and edge case handling.
This commit is contained in:
@@ -7,6 +7,7 @@ from fastgpt_client.exceptions import (
|
||||
)
|
||||
from ..core.fastgpt_client import get_fastgpt_client
|
||||
from ..core.config import Config
|
||||
from ..voice.text_chunker import SentenceTextChunker, SentenceTextChunkerConfig
|
||||
from loguru import logger
|
||||
import json
|
||||
import re
|
||||
@@ -173,12 +174,14 @@ async def chat(
|
||||
"""Handle chat completion request."""
|
||||
json_data = request.model_dump()
|
||||
need_form_update = json_data.get('needFormUpdate', False)
|
||||
use_text_chunk = json_data.get('useTextChunk', False)
|
||||
chat_variables = {'needFormUpdate': need_form_update}
|
||||
request_started_at = time.perf_counter()
|
||||
logger.info(
|
||||
"Chat request received "
|
||||
f"sessionId={json_data['sessionId']} stream={stream} "
|
||||
f"needFormUpdate={need_form_update} text_len={len(json_data.get('text', ''))} "
|
||||
f"needFormUpdate={need_form_update} useTextChunk={use_text_chunk} "
|
||||
f"text_len={len(json_data.get('text', ''))} "
|
||||
f"input={json_data.get('text', '')!r}"
|
||||
)
|
||||
|
||||
@@ -191,6 +194,17 @@ async def chat(
|
||||
text_delta_count = 0
|
||||
output_chunks = []
|
||||
form_update_payload = {}
|
||||
text_chunker = (
|
||||
SentenceTextChunker(
|
||||
SentenceTextChunkerConfig(
|
||||
min_chars=1,
|
||||
max_chars=0,
|
||||
use_soft_breaks=False,
|
||||
)
|
||||
)
|
||||
if use_text_chunk
|
||||
else None
|
||||
)
|
||||
try:
|
||||
# Use SDK's create_chat_completion with stream=True
|
||||
response = await client.create_chat_completion(
|
||||
@@ -227,6 +241,20 @@ async def chat(
|
||||
|
||||
def flush_form_update(form_update):
|
||||
return create_sse_event("formUpdate", form_update)
|
||||
|
||||
def build_text_delta_events(text: str):
|
||||
if not text:
|
||||
return []
|
||||
chunks = text_chunker.feed(text) if text_chunker else [text]
|
||||
return [flush_text_delta(chunk) for chunk in chunks if chunk]
|
||||
|
||||
def flush_text_chunker_events():
|
||||
if not text_chunker:
|
||||
return []
|
||||
chunk = text_chunker.flush()
|
||||
if not chunk:
|
||||
return []
|
||||
return [flush_text_delta(chunk)]
|
||||
|
||||
async for event in aiter_stream_events(response):
|
||||
try:
|
||||
@@ -294,10 +322,12 @@ async def chat(
|
||||
# Send remaining content as text_delta
|
||||
remaining_content = buffer[match.end():]
|
||||
if remaining_content:
|
||||
yield flush_text_delta(remaining_content)
|
||||
for text_event in build_text_delta_events(remaining_content):
|
||||
yield text_event
|
||||
buffer = "" # Clear buffer after extracting state
|
||||
else:
|
||||
yield flush_text_delta(delta_content)
|
||||
for text_event in build_text_delta_events(delta_content):
|
||||
yield text_event
|
||||
buffer = ""
|
||||
|
||||
except Exception as e:
|
||||
@@ -307,7 +337,11 @@ async def chat(
|
||||
# If stream ends and no state code found (unlikely if format is strict),
|
||||
# we might want to send what we have
|
||||
if not state_code_found and buffer:
|
||||
yield flush_text_delta(buffer)
|
||||
for text_event in build_text_delta_events(buffer):
|
||||
yield text_event
|
||||
|
||||
for text_event in flush_text_chunker_events():
|
||||
yield text_event
|
||||
|
||||
text_delta_end_ms = (
|
||||
f"{(last_text_delta_at - stream_started_at) * 1000:.1f}"
|
||||
@@ -320,6 +354,7 @@ async def chat(
|
||||
f"duration_ms={(time.perf_counter() - stream_started_at) * 1000:.1f} "
|
||||
f"text_delta_end_ms={text_delta_end_ms} "
|
||||
f"text_delta_count={text_delta_count} "
|
||||
f"useTextChunk={use_text_chunk} "
|
||||
f"stage_code_found={state_code_found} formUpdate_sent={module_form_sent} "
|
||||
f"output={''.join(output_chunks)!r} "
|
||||
f"formUpdate={form_update_payload!r}"
|
||||
|
||||
Reference in New Issue
Block a user