Files
contractor/process_v2.cfm
T

159 lines
6.5 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--- process_v2.cfm — v2 pipeline: LLM-интерпретация ДС → apply_events --->
<cftry>
<cfquery name="supps" datasource="baza">
SELECT s.id as supp_id, s.type, d.id as doc_id, d.filename, d.elements_json
FROM supplements s
JOIN documents d ON s.document_id = d.id
WHERE s.contract_id = <cfqueryparam value="#url.contract_id#" cfsqltype="cf_sql_varchar">
AND d.elements_json IS NOT NULL
ORDER BY s.created_at
</cfquery>
<cfif supps.recordCount EQ 0>
<cfoutput>data: #serializeJSON({type:"error",message:"Нет распарсенных файлов"})#
</cfoutput><cfflush>
<cfabort>
</cfif>
<cfset totalUnresolved = 0>
<cfset llmStart = getTickCount()>
<cfloop query="supps">
<cfset sid = supps.supp_id>
<!--- Текущая спецификация из spec_current --->
<cfquery name="curSpec" datasource="baza">
SELECT name_hash, name, price, qty, sum, date_start
FROM spec_current
WHERE contract_id = <cfqueryparam value="#url.contract_id#" cfsqltype="cf_sql_varchar">
ORDER BY name
</cfquery>
<cfset currentSpec = []>
<cfloop query="curSpec">
<cfset arrayAppend(currentSpec, {
hash: curSpec.name_hash,
name: curSpec.name,
price: curSpec.price,
qty: curSpec.qty,
sum: curSpec.sum,
date_start: curSpec.date_start
})>
</cfloop>
<!--- textify elements_json → doc_text --->
<cfset elements = deserializeJSON(supps.elements_json)>
<cfset textLines = []>
<cfloop array="#elements#" index="el">
<cfif el.type EQ "paragraph">
<cfset prefix = len(el.style) ? "[#el.style#] " : "">
<cfset arrayAppend(textLines, prefix & el.text)>
<cfelseif el.type EQ "table">
<cfset rows = el.rows>
<cfif arrayLen(rows) GT 0>
<cfset ncols = arrayLen(rows[1])>
<cfset arrayAppend(textLines, "--- Таблица (" & arrayLen(rows) & "×" & ncols & ") ---")>
<cfloop array="#rows#" index="row">
<cfset cells = []>
<cfloop from="1" to="#ncols#" index="ci">
<cfset val = "">
<cfif ci LTE arrayLen(row)>
<cfset val = replace(replace(toString(row[ci]), chr(10), " ", "ALL"), "|", "\|", "ALL")>
</cfif>
<cfset arrayAppend(cells, val)>
</cfloop>
<cfset arrayAppend(textLines, "| " & arrayToList(cells, " | ") & " |")>
</cfloop>
<cfset arrayAppend(textLines, "")>
</cfif>
</cfif>
</cfloop>
<cfset docText = arrayToList(textLines, chr(10))>
<!--- SSE: начинаем LLM --->
<cfoutput>data: #serializeJSON({type:"extract_start",supplement_id:sid,filename:supps.filename})#
</cfoutput><cfflush>
<!--- Вызов ВМ /llm-ops --->
<cfset t0 = getTickCount()>
<cfset llmPayload = {
contract_id: url.contract_id,
supplement_id: sid,
current_spec: currentSpec,
doc_text: docText
}>
<cfhttp url="https://contracts.kube5s.ru/llm-ops" method="POST" timeout="130">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type="body" value="#serializeJSON(llmPayload)#">
</cfhttp>
<cfset elapsed = int((getTickCount() - t0) / 1000 * 10 + 0.5) / 10>
<cfif NOT (cfhttp.statusCode EQ 200 OR left(cfhttp.statusCode, 3) EQ "200")>
<cfoutput>data: #serializeJSON({type:"extract_error",supplement_id:sid,filename:supps.filename,error:"LLM HTTP #cfhttp.statusCode#",time_s:elapsed})#
</cfoutput><cfflush>
<cfcontinue>
</cfif>
<cftry>
<cfset llmResult = deserializeJSON(cfhttp.fileContent)>
<cfset ops = structKeyExists(llmResult, "ops") ? llmResult.ops : []>
<cfset mode = structKeyExists(llmResult, "mode") ? llmResult.mode : "partial">
<cfoutput>data: #serializeJSON({type:"llm_done",supplement_id:sid,filename:supps.filename,ops_count:arrayLen(ops),mode:mode,time_s:elapsed})#
</cfoutput><cfflush>
<!--- Применить операции --->
<cfset applyPayload = {
supplement_id: sid,
ops: ops
}>
<cfhttp url="https://contractor.luceek8s.dev.nubes.ru/apply_events.cfm?contract_id=#url.contract_id#&mode=#mode#" method="POST" timeout="30">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type="body" value="#serializeJSON(applyPayload)#">
</cfhttp>
<cfif cfhttp.statusCode EQ 200 OR left(cfhttp.statusCode, 3) EQ "200">
<cfset applyResult = deserializeJSON(cfhttp.fileContent)>
<cfif structKeyExists(applyResult, "summary")>
<cfset totalUnresolved += applyResult.summary.unresolved>
<cfoutput>data: #serializeJSON({type:"applied",supplement_id:sid,summary:applyResult.summary})#
</cfoutput><cfflush>
<cfelse>
<cfoutput>data: #serializeJSON({type:"apply_error",supplement_id:sid,error:structKeyExists(applyResult,'error')?applyResult.error:'unknown'})#
</cfoutput><cfflush>
</cfif>
<cfelse>
<cfoutput>data: #serializeJSON({type:"apply_error",supplement_id:sid,error:"apply HTTP #cfhttp.statusCode#"})#
</cfoutput><cfflush>
</cfif>
<cfcatch>
<cfoutput>data: #serializeJSON({type:"extract_error",supplement_id:sid,filename:supps.filename,error:"JSON parse: " & cfcatch.message,time_s:elapsed})#
</cfoutput><cfflush>
</cfcatch>
</cftry>
</cfloop>
<!--- Финальное событие --->
<cfset totalTime = int((getTickCount() - llmStart) / 1000 * 10 + 0.5) / 10>
<cfoutput>data: #serializeJSON({type:"done",total_time_s:totalTime,total_unresolved:totalUnresolved})#
</cfoutput><cfflush>
<cfcatch>
<cfoutput>data: #serializeJSON({type:"error",message:cfcatch.message,detail:cfcatch.detail})#
</cfoutput><cfflush>
</cfcatch>
</cftry>